Partager via


Why does BINDEVENT not work with StatusBar_Change?

A customer had a question and sent some code:

PUBLIC oHandler

oHandler = NEWOBJECT("StatusBarText")

?BINDEVENT(_VFP,[STATUSBAR],oHandler,[STATUSBAR_CHANGE],1)

_VFP.StatusBar = "AAAA" && triggers handler

SET MESSAGE TO "1111" && does not trigger handler

*navigate menus: does not trigger handler

DEFINE CLASS StatusBarText AS Session

      PROCEDURE StatusBar_Change

            ?PROGRAM(),_vfp.StatusBar

      RETURN

ENDDEFINE

This code demonstrates 3 ways to change the status bar text, but only one fires the hooked event.

The status bar text can change in various ways, which means there are various code paths internal to VFP that are followed. When changing the status bar text directly via direct assignment to _VFP.Statusbar, the normal VFP code (the object manager) that changes an object’s property gets invoked, which knows to check for and execute any BindEvent code.

When the user activates a menu, the WM_ENTERIDLE Notification is sent to VFP’s Window procedure with WPARAM = MSGF_MENU, which tells VFP to draw the menu message on the status bar.

When the user executes SET MESSAGE TO, the internal VFP object manager is completely bypassed to change the status bar text.

The BINDEVENT feature allows the user to bind events to when an object property or method is invoked or changed. When I implemented the feature, I modified the internal VFP object manager to check for user bound events. I paid no attention to the SET MESSAGE TO and the WM_ENTERIDLE code, which had been in existence for several versions.

I suppose one could argue that this is a bug, but the documentation says:

to bind events, properties, or methods from native Visual FoxPro objects to other Visual FoxPro objects.

There is a simple workaround: use Bindevents to bind to the WM_ENTERIDLE message and change SET MESSAGE TO cNewMessage to _VFP.StatusBar=cNewMessage

#define GWL_WNDPROC (-4)

#define WM_ENTERIDLE 0x0121

#define MSGF_DIALOGBOX 0

#define MSGF_MESSAGEBOX 1

#define MSGF_MENU 2

#define MSGF_SCROLLBAR 5

PUBLIC oHandler

oHandler = NEWOBJECT("StatusBarText")

?BINDEVENT(_VFP,[STATUSBAR],oHandler,[STATUSBAR_CHANGE],1)

?BINDEVENT(_vfp.HWnd,WM_ENTERIDLE,oHandler, "HandleMsg",5)

_VFP.StatusBar = "AAAA" && triggers handler

SET MESSAGE TO TRANSFORM(SECONDS()) && does not trigger handler

DEFINE CLASS StatusBarText AS Session

      dwOrigWindProc=0

      PROCEDURE init

            DECLARE integer GetWindowLong IN WIN32API ;

                  integer hWnd, ;

                  integer nIndex

            DECLARE integer CallWindowProc IN WIN32API ;

                  integer lpPrevWndFunc, ;

                  integer hWnd,integer Msg,;

                  integer wParam,;

                  integer lParam

            THIS.dwOrigWindProc =GetWindowLong(_VFP.HWnd,GWL_WNDPROC)

      PROCEDURE HandleMsg(hWnd as Integer, msg as Integer, wParam as Integer, lParam as Integer)

            LOCAL nRetvalue

            nRetvalue=0

* ?PROGRAM(),msg,TRANSFORM(wParam,"@0x"),TRANSFORM(lParam,"@0x")," "

            DO CASE

            CASE msg =WM_ENTERIDLE

                  IF wParam = MSGF_MENU

                        *call default processing to set menu message

                        nRetvalue=CallWindowProc(this.dwOrigWindProc,hWnd,msg,wParam,lParam)

                        ?PROGRAM(),_vfp.StatusBar

                  ENDIF

            ENDCASE

            RETURN nRetvalue

      PROCEDURE StatusBar_Change

            ?PROGRAM(),_vfp.StatusBar

      RETURN

ENDDEFINE

See also How to hook command window keystrokes.

Why doesn't drag/drop work with BindEvents?

Is this a bug in BindEvents?

Comments

  • Anonymous
    March 09, 2006
    Nice workaround, thanks! Can this code be used freely?

    Now, what about the StatusBarText property of controls?

    And lets not forget about the database:table recno/reccount, etc messages, but those nobody wants to display anyway...

    It looks like there are a lot of guys displaying text in the VFP statusbar, each of them competing to overwrite each other´s text.

    If they all just relied on setting the _vfp.statusbar property, that would be nice.

  • Anonymous
    March 13, 2006
    It works great! but only when a Menu or Popup has a MESSAGE, but not occurs the same when i modify the property StatusBarText of a control (commandbutton, textBox, comboBox, ..., etc.). What can i do in that case?

  • Anonymous
    May 23, 2006
    Calvin, any other workaround for what Fabian wrote?

  • Anonymous
    July 19, 2006
    Calvin - would like to SET STATUS BAR OFF and add a container c/w controls to _SCREEN to create a standalone StatusBar class.

    Your code posted relies on SET STATUS BAR ON and outputting the messages to controls in the container simulating the statusbar fails if SET STATUS BAR OFF.

    Any ideas on a workaround?

    Chris

  • Anonymous
    December 27, 2006
    Is it possible to trap for the instant a form resize begins and the instant it stops? Looking for a list of other CallWindowProc message pointers, like "WM_ENTERIDLE" that would be appropriate to bind to a form "resize" in VFP. Thanks

  • Anonymous
    January 20, 2009
    PingBack from http://www.hilpers-esp.com/319966-bindevent-a-una-propiedad