Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Reposition Common Dialog
Message
General information
Forum:
Visual FoxPro
Category:
Windows API functions
Environment versions
Visual FoxPro:
VFP 8 SP1
OS:
Windows XP SP2
Network:
Windows 2003 Server
Database:
Visual FoxPro
Miscellaneous
Thread ID:
01057138
Message ID:
01057313
Views:
44
>>>Hi again.
>>>
>>>I can get to his home page and all others except his SPS WEBLOG. Can you open that page? Might be trouble on my end if so.
>>>
>>>Thanks
>>
>>Yes I can.
>
>It does not work for me either, maybe you are accessing a cached version? Try cleaning the cache and navigate again.

I didn't visited Craig's BLOG since two or more months. I just put his BLOG in my mail client :-) and I receive all his news at a time.
I clear my cache yetarday because of foxite.com (I still can't login with FireFox there) and I have any problems. Here ALL Graig's post:
The file he referes to:

http://www.sweetpotatosoftware.com/files/vfpex.zip
BindEvent on Steroids

The ability for BindEvent to hook into windows message events in Visual FoxPro 9 is great.
It is no doubt wrapping the SetWindowLong API function somewhere in the source and facilitates
the magic by subclassing the target window. My hat goes off to the Fox Team for coming up with this.
But, what if you want to modify a messagebox before it appears (such as change the button
captions and centering it with the form that called it) or what if you want to create a Global
Keyboard Hook? Basically, what if, as a Visual FoxPro developer, you want to take advantage of
the SetWindowsHookEx API function and all the doors it opens up? Maybe I'm missing something, but
BindEvent doesn't seem to be able to do this.

I've got some ideas on things that I want Visual FoxPro to do long before Sedna gets here, and
some of these ideas require that I am able to use the SetWindowsHookEx. So, today I decided to
figure out how we (the Visual FoxPro Community) could do this.

To start this show, here's an FLL I've created using Visual C++ 7.0, that gives us two more
functions for Visual FoxPro. BindEventEX and UnBindEventEx. Download the vfpex.fll here. These
functions will give you indirect access to SetWindowsHookEx for your Visual FoxPro
applications/code. There is more to be done, but this is a good start for now.

Then, below are a couple of "cut-n-paste into a prg file and execute" examples I worked up in
Visual FoxPro that use the vfpex.fll.

***************************************************
*!* MODIFY MESSAGEBOX EXAMPLE
*!*
*!* Requires: vfpex.fll
***************************************************
PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN

DEFINE CLASS form1 AS form
 Top = 0
 Left = 0
 Height = 259
 Width = 373
 DoCreate = .T.
 Caption = "Using the New BindEventsEx - MessageBox Modification"
 WindowType = 1
 Name = "Form1"

 ADD OBJECT command1 AS commandbutton WITH ;
  Top = 216, ;
  Left = 144, ;
  Height = 27, ;
  Width = 132, ;
  Caption = "R\<un Example", ;
  Name = "Command1"

 ADD OBJECT command2 AS commandbutton WITH ;
  Top = 216, ;
  Left = 276, ;
  Height = 27, ;
  Width = 84, ;
  Caption = "E\<xit", ;
  Name = "Command2"

 PROCEDURE wineventhandler
  #DEFINE IDOK   1
  #DEFINE IDCANCEL  2
  #DEFINE IDABORT  3
  #DEFINE IDRETRY  4
  #DEFINE IDIGNORE  5
  #DEFINE IDYES   6
  #DEFINE IDNO   7
  #DEFINE IDCLOSE  8
  #DEFINE IDHELP   9
  #DEFINE IDTRYAGAIN 10
  #DEFINE IDCONTINUE 11
  #DEFINE IDPROMPT 65535

  IF nCode == 5
   SetWindowText(wParam, "VFP - WH_CBT HOOK") && Title
   SetDlgItemText(wParam, IDPROMPT, "Visual FoxPro BindEventEx Example") && Message
   SetDlgItemText(wParam, IDABORT, "VFP Rocks!") && First Button Caption
   SetDlgItemText(wParam, IDRETRY, "Always Has") && Second Button Caption
   SetDlgItemText(wParam, IDIGNORE, "Always Will") && Third Button Caption

   Thisform.CenterMessageBox(wParam)

   CallNextHookEx(hHook, nCode, wParam, LPARAM) && all 4 variables exist
   UnBindEventEx()
   SET LIBRARY TO
  ELSE
   CallNextHookEx(hHook, nCode, wParam, LPARAM) && all 4 variables created by FLL
  ENDIF

  RELEASE nCode, wParam, LPARAM, hHook
 ENDPROC

 PROCEDURE buf2dword
  LPARAMETERS tcBuffer
  RETURN Asc(SUBSTR(tcBuffer, 1,1)) + ;
       Asc(SUBSTR(tcBuffer, 2,1)) * 2^8 +;
       Asc(SUBSTR(tcBuffer, 3,1)) * 2^16 +;
       Asc(SUBSTR(tcBuffer, 4,1)) * 2^24
 ENDPROC

 PROCEDURE centermessagebox
  LPARAMETERS tnwParam

  LOCAL lcBuffer, lnMsgLeft, lnMsgTop, lnMsgRight, lnMsgBottom, lnMsgWidth, lnMsgHeight

  lcBuffer = REPLI(CHR(0), 2^4)

  =GetWindowRect(tnwParam, @lcBuffer)

  lnMsgLeft = THISFORM.buf2dword(SUBSTR(lcBuffer, 1, 4))
  lnMsgTop = THISFORM.buf2dword(SUBSTR(lcBuffer, 5, 4))
  lnMsgRight = THISFORM.buf2dword(SUBSTR(lcBuffer, 9, 4))
  lnMsgBottom = THISFORM.buf2dword(SUBSTR(lcBuffer, 13, 4))
  lnMsgWidth = lnMsgRight - lnMsgLeft
  lnMsgHeight = lnMsgBottom - lnMsgTop
  lnMsgLeft = THISFORM.LEFT + (THISFORM.WIDTH - lnMsgWidth) / 2
  lnMsgTop = _screen.Top + THISFORM.TOP + (THISFORM.HEIGHT - lnMsgHeight) / 2

  MoveWindow(tnwParam, lnMsgLeft, lnMsgTop, lnMsgWidth, lnMsgHeight, .T.)
 ENDPROC

 PROCEDURE Load
  DECLARE INTEGER SetDlgItemText IN user32;
   LONG hDlg,;
   LONG nIDDlgItem,;
   STRING lpString

  DECLARE INTEGER SetWindowText IN user32;
   LONG HWND,;
   STRING  lpString

  DECLARE LONG CallNextHookEx IN user32;
   LONG, LONG, LONG, LONG

  DECLARE INTEGER MoveWindow IN user32;
   INTEGER HWND,;
   INTEGER X,;
   INTEGER Y,;
   INTEGER nWidth,;
   INTEGER nHeight,;
   INTEGER bRepaint

  DECLARE SHORT GetWindowRect IN user32 INTEGER HWND, STRING @ lpRect
 ENDPROC
 
 PROCEDURE command1.Click
  *!* Some of the various Windows Hook constants
  #define WH_MSGFILTER -1
  #define WH_JOURNALRECORD 0
  #define WH_JOURNALPLAYBACK 1
  #define WH_KEYBOARD 2
  #define WH_GETMESSAGE 3
  #define WH_CALLWNDPROC 4
  #define WH_CBT 5 && the one used here
  #define WH_SYSMSGFILTER 6
  #define WH_MOUSE 7
  #define WH_HARDWARE 8
  #define WH_DEBUG 9
  #define WH_SHELL 10
  #define WH_FOREGROUNDIDLE 11
  #define WH_CALLWNDPROCRET 12
  #define WH_KEYBOARD_LL 13
  #define WH_MOUSE_LL 14
  
  *!* Set library so BindEventEx and UnBindEventEx can be used
  *!* in VFP
  SET LIBRARY TO (LOCFILE(ADDBS(JUSTPATH(SYS(16))) + "vfpex.fll"))
  *!* You must have a Named reference to the form or object
  *!* as thisform or this cannot be used with BindEventEx
  BindEventEx('oform1.wineventhandler()', WH_CBT) && SetWindowsHookEx
  *!* This messagebox will be modified before it is shown
  MESSAGEBOX(" ", 2, "") && Just A Blank Messagebox with Abort, Retry, Ignore buttons
 ENDPROC

 PROCEDURE command2.Click
  Thisform.Release()
 ENDPROC

ENDDEFINE

***************************************************
*!* GLOBAL KEYBOARD HOOK EXAMPLE
*!*
*!* Requires: vfpex.fll
***************************************************
PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN

DEFINE CLASS form1 AS form

 Top = 0
 Left = 1
 Height = 256
 Width = 454
 DoCreate = .T.
 Caption = "Using the New BindEventsEx - Global Keyboard Hook"
 Name = "form1"

 ADD OBJECT command1 AS commandbutton WITH ;
  Top = 216, ;
  Left = 311, ;
  Height = 27, ;
  Width = 132, ;
  Caption = "R\<un Example", ;
  Name = "Command1"

 ADD OBJECT edit1 AS editbox WITH ;
  Height = 193, ;
  Left = 11, ;
  ReadOnly = .T., ;
  Top = 12, ;
  Width = 432, ;
  Name = "Edit1"

 PROCEDURE wineventhandler
  LOCAL HookStruct
  *!* Real basic example, just to show it's possible
  IF wParam = 256 && keydown
   HookStruct = REPLICATE(CHR(0), 20)
   CopyMemory(@Hookstruct, lParam, 20)
   thisform.edit1.value = thisform.edit1.value + Chr(thisform.buf2dword(Hookstruct))
  ENDIF
  CallNextHookEx(hHook, nCode, wParam, lParam) && all 4 variables created by FLL
  RELEASE nCode, wParam, LPARAM, hHook
 ENDPROC

 PROCEDURE buf2dword
  LPARAMETERS tcBuffer
  RETURN Asc(SUBSTR(tcBuffer, 1,1)) + ;
       Asc(SUBSTR(tcBuffer, 2,1)) * 2^8 +;
       Asc(SUBSTR(tcBuffer, 3,1)) * 2^16 +;
       Asc(SUBSTR(tcBuffer, 4,1)) * 2^24
 ENDPROC

 PROCEDURE Load         
  DECLARE LONG CallNextHookEx IN user32;
   LONG, LONG, LONG, LONG

  DECLARE RtlMoveMemory IN kernel32 As CopyMemory;
      STRING  @ Destination,;
      INTEGER   Source,;
      INTEGER   nLength 

  SET LIBRARY TO (LOCFILE("vfpex.fll", "FLL"))
 ENDPROC

 PROCEDURE Destroy
  *!* Unhook when form is destroyed
  UnBindEventEx()
  SET LIBRARY TO
 ENDPROC

 PROCEDURE command1.Click
  #define WH_MSGFILTER -1
  #define WH_JOURNALRECORD 0
  #define WH_JOURNALPLAYBACK 1
  #define WH_KEYBOARD 2
  #define WH_GETMESSAGE 3
  #define WH_CALLWNDPROC 4
  #define WH_CBT 5
  #define WH_SYSMSGFILTER 6
  #define WH_MOUSE 7
  #define WH_HARDWARE 8
  #define WH_DEBUG 9
  #define WH_SHELL 10
  #define WH_FOREGROUNDIDLE 11
  #define WH_CALLWNDPROCRET 12
  #define WH_KEYBOARD_LL 13 && this is the one used
  #define WH_MOUSE_LL 14

  this.Enabled = .F.
  WAIT "Go type in another application - your keystrokes will be recorded" WINDOW TIMEOUT 2
  *!* You must have a Named reference to the form or object
  *!* as thisform or this cannot be used with BindEventEx
  BINDEVENTEX('oform1.wineventhandler()', WH_KEYBOARD_LL) && SetWindowsHookEx
 ENDPROC

ENDDEFINE
That is CRAIG MVP (Again congratulations Craig) post!
Against Stupidity the Gods themselves Contend in Vain - Johann Christoph Friedrich von Schiller
The only thing normal about database guys is their tables.
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform