My.ADVISOR.com Sign-In
ID
Password

Member Center / Sign-Up
Go to Article
Advanced Search 

ADVISOR ANSWERS

Manage VFP Grid Actions

Q: I have code in my grid column header's Click event to sort data in the column—similar to the Microsoft Office programs. However, if I resize that column with my mouse, it causes the header's Click to occur, which runs the sorting code. Is there a way to resize a column with the mouse that does not also run the header Click event?

By Tamar E. Granor, Technical Editor

Q: I have code in my grid column header's Click event to sort data in the column -- similar to the Microsoft Office programs. However, if I resize that column with my mouse, it causes the header's Click to occur, which runs the sorting code. Is there a way to resize a column with the mouse that does not also run the header Click event?


-- Bob Thomsen (via Advisor.com)

A: You can't prevent the header's Click method from firing in this situation. Sizing a grid column always calls the Click method for the actual column being sized, which is the left-hand column of the two the mouse is between. However, there's a way to determine whether the Click came from a resizing action. The key is to use the grid's GridHitTest method, which lets you determine where you are in the grid.

GridHitTest was added in VFP 6.0 and provides some really useful information. You pass it coordinates and it tells you what component of the grid that point is over (or if it isn't in the grid at all), as well as the relative row and column of the point. GridHitTest is an unusual method in that it expects several of its parameters to be passed by reference—that's how it can return multiple data values. Here's the syntax for GridHitTest:

GridHitTest( nXCoord, nYCoord, @nComponent,
  @nRelativeRow, @nRelativeColumn
  [, @nPane ] )

The value stored in nComponent is a number that indicates which part of the grid that point is on. It's assigned a 0 if the specified point isn't in the grid. For your task, the key values are 1, which indicates a header, and 2, which indicates between headers. (The nPane parameter is for situations where the grid is split. It tells you which pane of the grid contains the specified point.)

To apply GridHitTest to prevent Click code from running, you need to get your hands on the point at which the Click occurred. The Click method doesn't have this information, but MouseDown does. It also turns out that you have to test the point before the move occurs, so the header's MouseDown method is a good place to call GridHitTest. After you've done so, you have to store the nComponent value to make it available in the header's Click method.

Here are the steps you have to take to prevent your custom Click code from firing when you resize a column:

1. Add a custom property to the form. Call it nLastComponent.

2. Add this code to the MouseDown method of each header:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
LOCAL nComp, nRelRow, nRelCol

This.Parent.Parent.GridHitTest(nXCoord, nYCoord, ;
  @nComp, @nRelRow, @nRelCol)
ThisForm.nLastComponent = nComp

3. In the header's Click method, use code like this to check whether it's a real click or a resize:
IF ThisForm.nLastComponent = 1
  * This is actually a click. Put your custom code here.
ELSE
  * This is a resize. Behave appropriately.
ENDIF

The biggest problem with this solution is that you have to put code in two methods of every header. Clearly, a better solution is to subclass the header class, and put the code you need there. This raises two (related) problems. First, headers can't be subclassed using the Class Designer. The solution is to create your subclass in code. Here's the code for a header subclass. I've moved the nLastComponent property from the form to the header for better encapsulation.

DEFINE CLASS hdrResize AS Header

nLastComponent = 0


PROCEDURE MouseDown
LPARAMETERS nButton, nShift, nXCoord, nYCoord

LOCAL nComp, nRelRow, nRelCol

This.Parent.Parent.GridHitTest(nXCoord, nYCoord, ;
  @nComp, @nRelRow, @nRelCol)
This.nLastComponent = nComp

RETURN

PROCEDURE Click
IF This.nLastComponent = 1
  * This is actually a click. Put your custom code here.
ELSE
  * This is a resize. Behave appropriate.
ENDIF

RETURN

ENDDEFINE

The second problem is more difficult. You can't tell the grid to simply use a particular header class. Instead, you need to change the header of each column. You can do this by removing the base class header and substituting your custom header class. Although it's possible to do so at design-time with a builder, that approach raises other problems that make it more trouble than it's worth. The robust way to do this is to replace the headers at runtime by putting code in the grid's Init method.

The code assumes the header class above is stored in a file called HdrClass.PRG. It gives the new header for each column the same name and caption as the one it's replacing:

FOR EACH oColumn IN This.Columns
  FOR EACH oControl IN oColumn.Controls
    IF UPPER(oControl.BaseClass) = "HEADER"
      cHdrName = oControl.Name
      cCaption = oControl.Caption
      oColumn.RemoveObject(cHdrName)
      oColumn.NewObject(cHdrName, "hdrResize", ;
        "hdrClass.PRG")
      oColumn.&cHdrName..Caption = cCaption
    ENDIF
  ENDFOR
ENDFOR

Of course, if you're replacing base class headers with your own custom class, you can put whatever code you think appropriate in the class. Your code to re-order the grid is one obvious candidate for this treatment.
In addition, if you're using a grid subclass, you can do the job once by adding custom properties to hold the header class name and class library. Then, in the grid class' Init method, check those properties. If they aren't empty, run the loop above, substituting the properties for the hard-coded names I used.

You'll find the simple Header class and the code for the grid's Init on this issue's PROFESSIONAL RESOURCE CD.
-- Tamar


Manage Visual FoxPro Grid Actions

No reader comments ... yet.

    What do YOU think about this topic? Share your advice and thoughts using this form.

    Your Name

    REQUIRED : PUBLIC

    Your E-Mail

    REQUIRED : PRIVATE

    Job, Company

    OPTIONAL : PUBLIC

    City, State, Country

    OPTIONAL : PUBLIC

    Your Web Site

    OPTIONAL : PUBLIC

    Your Comment

    Please help everyone by keeping your comments on-topic, using clean language, and not defaming or making personal attacks.


    Your e-mail address is required, but it will not be displayed to the public or given to anyone. See our Privacy Policy. Comments become visible after they pass our spam filter, and spammers and abusers are permanently blocked. Please report spam or abuse.

    Technical Editor Tamar E. Granor is an independent consultant specializing in database applications using Visual FoxPro, a Microsoft Certified Professional, and a Microsoft Support Most Valuable Professional. She is co-author of Microsoft Office Automation with Visual FoxPro (Hentzenwerke Publishing), Hacker's Guide to Visual FoxPro 6.0 (Hentzenwerke Publishing) and Hacker's Guide to Visual FoxPro 3.0. Some of the code in Advisor Answers is based on the work Tamar did for the Hacker's Guide, which was partially inspired by questions submitted to Advisor Answers. tamar_granor@compuserve.com.

    Printer-friendly
    page layout

    Keyword Tags: Application Design, Database, Database Development, Grids, Integration, Microsoft, Microsoft Visual FoxPro

    ADVISORAMA
    We must not sit down and wait for miracles. Up and be going!
    -- John Eliot

    ARTICLE INFO

    DataBased Advisor

    Print Edition: January 2001, Page 14

    FREE ACCESS FREE ACCESS


     Article files are on this issue's Resource CD.

    SUBSCRIPTION STATUS
    You are not signed-in. If you are a subscriber to this publication, sign-in above to access locked articles. To subscribe or renew go to www.AdvisorStore.com.

    Subscribe to FileMaker Advisor Magazine

    Read the advanced guide to creating custom business database solutions with FileMaker software. Subscribe now to gain access to all the archives and downloads.

    FileMaker.Advisor.com

    Subscribe to Advisor Basics of FileMaker Pro

    Learn the fundamentals of using FileMaker Pro software. Every issue gives you step-by-step instructions on creating the databases you need. Subscribe now!

    FileMaker.AdvisorBasics.com

    Showcase Your Smarts

    Submit your tips, techniques and advice and let Advisor promote your business and build your career. Show the world what you know!

    AdvisorTips.com

    Use of this or any other site, content, product or service of Advisor Media constitutes acceptance of Terms of Use.
    Portions copyright ©1983-2008 Advisor Media, Inc. All Rights Reserved.
    Reuse or reproduction of any portion or quantity of Advisor Media's copyrighted content, in any form, for any purpose, requires written permission.
    ADVISOR®, the ADVISOR logo, and other names and logos that incorporate ADVISOR are registered trademarks, trademarks or service marks of Advisor Media, Inc. in the United States and/or other countries.
    Other trademarks are used for identification, editorial or descriptive purposes and are the property of their owners.
    Hosted by Prominic.NET Website powered by
    LOTUS SOFTWARE
    GRANL07-03 posted 12/28/2000 modified 11/23/2008 04:11:15 AM ztdbms/ztdbms
    domino-144.advisor.com my.advisor.com 11/23/2008 08:37:56 AM