Scott Scovell on Visual FoxPro

Wednesday, November 23, 2005

BindEvent() and Compile

Recently I have been working on a Fox IDE tool called FoxTabs. FoxTabs utilises my favourite feature of VFP 9.0, binding to Windows message events. The design approach is to hook into window events within the Fox IDE and manage multiple editing windows via tab controls on a toolbar. We, Craig and I, have just posted a beta version for all to check out. However there is one issue preventing me from getting some well earned sleep. (issue posted by Alan Stevens on the forum)
 
When running FoxTabs, if an error occurs during compiling your source code, VFP crashes. I admit, its only a minor issue. I mean, who writes code with bugs in it right? :-P
 
So what's happening? We have event bindings to all WM_CREATE events received by Fox. When a window is created, we interrogate its properties to see if it is an IDE window we want to manage via a toolbar tab. When the compile error occurs, Fox will create a dialog box to display the error. It is when we process the WM_CREATE event of this dialog box we get the fatal crash.
 
Here is some simplified code to demonstrate this:
 

* Window messaging constants

#define GWL_WNDPROC           (-4)

#define WM_CREATE             0x0001

#define WM_DESTROY            0x0002

#define WM_SETTEXT            0x000C

 

* Create an instance of the wnHandler class

Public wmHandler As wmHandler

wmHandler = NewObject("wmHandler")

 

* Bind to all window create notifications

BindEvent(0, WM_CREATE, wmHandler, "wmEventHandler")

 

Return

 

* Define Windows messages event handler class

Define Class wmHandler As Custom

 

      PrevWndFunc       = 0

      IgnoreEvents      = .F.

     

      Function wmEventHandler(hWnd As Integer, Msg As Integer, wParam As Integer, lParam As Integer)

     

            Local lnReturn As Integer

           

            Do Case

                  Case This.IgnoreEvents

                        ? "Ignoring WM events"

 

                  Case Msg = WM_CREATE

                        ? Transform(hWnd, "@0x"), "WM_CREATE", Transform(wParam, "@0x"), Transform(lParam, "@0x")

 

                        * Bind to the WM_SETTEXT messages received by this window

                        BindEvent(hWnd, WM_SETTEXT, wmHandler, "wmEventHandler")

 

                  Case Msg = WM_SETTEXT        

                        ? Transform(hWnd, "@0x"), "WM_SETTEXT", Transform(wParam, "@0x"), Transform(lParam, "@0x")

 

                  Case Msg = WM_DESTROY

                        * Remove all WM event bindings to this window

                        UnBindEvents(hWnd)

 

            EndCase

 

            * Pass the WM event to the intended Window procedure

            lnReturn = CallWindowProc(This.PrevWndFunc, hWnd, Msg, wParam, lParam)

           

            Return lnReturn

           

      EndFunc

 

      Function Init()

           

            * Declare Win32 API functions

            Declare Integer CallWindowProc In Win32API Integer lpPrevWndFunc, Integer hWnd, Integer Msg, Integer wParam, Integer lParam

            Declare Integer GetWindowLong In Win32API Integer hWnd, Integer nIndex

 

            * Store handle for use in CallWindowProc

            This.PrevWndFunc = GetWindowLong(_Vfp.hWnd, GWL_WNDPROC)

 

      EndFunc

 

      Function Destroy()

     

            * Remove all WM event bindings

            UnBindEvents(0)

           

      EndFunc

     

EndDefine

 

Copy the code into a PRG and run. Open some IDE editing windows and observe the text outputted to the desktop. To reproduce the crash, open a new PRG and enter some junk (anything that will generate a compilation error). Compile the PRG...Bugger!

 

Now run the test again, only this time before you compile the PRG, go the command window and type

 

wmHandler.IgnoreEvents = .T.

 

Compile the PRG and notice the sky does not fall in.

 

So it would seem that the solution may be to implement some sort of BeforeCompile() event hook and disable my Windows message event processing. But how can I determine whether Fox is in the middle of compiling some code? I have tried the call stack but no luck there.

 

I have no choice, I am going to have to use the emergency red phone (the Fox phone) and contact Calvin. After all, it was Calvin who coded all this great functionality. If he can not help me, I am truly Wallaby Ted's brother Roo!

 
Powered By Qumana

2 Comments:

  • Hi Scott,

    Over on my blog I have an FLL that will allow you to do this and much more using a CBT hook. In any event, it could be used to solve your problem if Calvin doesn't come through for you and you don't mind an FLL dependency. Here's the link...

    http://www.sweetpotatosoftware.com/SPSBlog/CommentView,guid,f7644db8-b155-4d43-8216-4cfde233edb7.aspx

    By Blogger Craig Boyd, at November 25, 2005 11:01 pm  

  • Sorry to hear that I'm causing others to lose sleep.

    ++Alan

    By Blogger ++Alan, at November 28, 2005 6:01 am  

Post a Comment

<< Home