Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using RegisterWindowMessage API in VFP 6.0

Status
Not open for further replies.

WIREMESH

Programmer
Mar 15, 2004
109
US
Our VFP 6.0 SP5 application needs to communicate with another application written in DELPHI. The Delphi developers wish to use custom windows messaging for communications. In their initial specification, they use the RegisterWindowMessage API to establish a connection between both systems. After searching various fox resources, I have not found anything on RegisterWindowMessage(). Can this function be utilized in VFP6.0?
 
Rob

You can do anything in fox...

Do you an example of the function in VFP code?

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Hello ClarkPro.

Does this help?

Code:
DECLARE INTEGER RegisterWindowMessage in Win32Api String @
DECLARE INTEGER GetLastError in Win32Api 
lcString = 'This is my cool message' + CHR( 0 )
lnRetVal = RegisterWindowMessage( @lcString )
IF lnRetVal = 0
  lnError = GetLastError()
ENDIF



Marcia G. Akins
 
I should have been more detailed in my original post. The solution advocated involves sending custom windows messages back and forth between the two applications. On the Delphi side, they replaced their applications windows messaging loop with so custom code that looks for a specific message. If that message is received they perform some work, other wise they pass the message to the standard message handler. When the reccommended we take the same approach, I informed them in VFP 6, there is no way to replace the standard messaing loop. Calling Read Events initiates the standard windows messaging loop. I don't think that can be replaced, nor would I want to mess with the main application messaging loop for fear of crashing our app. What I would like to know, however, is there a way to communicate with their application using a custom windows messaging?
 
I've seen descriptions of custom FLLs that will hook into the message loop, but they are probably VFP version dependent. I can't seem to find any references on my system right now, but check on the UT ( and Google!

Rick
 
This code is from the VFP8 SysTray class and is self-explanatory if you read it carefully. It shows how to use a hack to intercept one window message given to the main VFP window: MouseWheel, and enable inter-process communication (the event gets handed to the ReceiveIconEvent method):
Code:
*!*	This is where the magic happens.
*!*	This is an unabashed hack to allow us to get the full functionality
*!*	of the Taskbar Notification Area ("System Tray") without having to
*!*	use an external C++ library.
*!*	To communicate with the systray, we tell it to send us messages via
*!*	the MouseWheel event. (This is the only VFP event that doesn't alter
*!*	or discard event data before firing the corresponding internal event.)
*!*	The second trick is that only the main VFP window will accept the events
*!*	without checking to see if the event coordinates are invalid. (The screen
*!* doesn't even need to be visible, so you can have SCREEN=OFF in your 
*!* config.fpw file.)  So we use VFP8's BINDEVENT() function to bind to the 
*!* _SCREEN.MouseWheel event.
*!*	This method sets up that communication path.
*!*	Returns 1 if successful.


LOCAL lcNotifyIconData

** NOTIFYICON struct defines
#define NIF_MESSAGE     0x00000001
#define NIF_ICON        0x00000002
#define NIF_TIP         0x00000004
#define NIF_STATE       0x00000008  && Win2k and later.
#define NIF_INFO        0x00000010	&& Use balloon tip.  Win2k and later.


&& Notify Icon Infotip flags
#define NIIF_NONE       0x00000000
&& icon flags are mutually exclusive
&& and take only the lowest 2 bits
#define NIIF_INFO       0x00000001
#define NIIF_WARNING    0x00000002
#define NIIF_ERROR      0x00000003
#define NIIF_ICON_MASK  0x0000000F
#define NIIF_NOSOUND    0x00000010	&& Windows XP and later.

#define NIM_ADD         0x00000000
#define NIM_MODIFY      0x00000001
#define NIM_DELETE      0x00000002
#define NIM_SETFOCUS    0x00000003	&& Windows 2000 and later.
#define NIM_SETVERSION  0x00000004	&& Windows 2000 and later.

#define NOTIFYICON_VERSION 3
#define NIS_HIDDEN              0x00000001
#define NIS_SHAREDICON          0x00000002


WITH THIS

*  If no icons loaded, do nothing.
IF .IconCount < 1 OR .CurrentIconIndex = 0
	RETURN 0
ENDIF


IF NOT .Enabled
	*  Each SystemTray icon in this process requires a unique ID. We'll
	*  use an _screen property to make sure each instance of this class
	*  gets its own ID.  Properties on _screen aren't affected by CLEAR ALL. 
	*  Because VFP drops the least significant two bytes of the mousewheel event's
	*  WPARAM parameter, our unique SysTray Icon ID must use the most significant 
	*  two bytes:
	#DEFINE MIN_SYSTRAY_ICON_ID	0x4000
	IF TYPE("_screen.nSysTrayCount") == "U"
		*  We're the first one here.
		_screen.AddProperty("nSysTrayCount", 0)	
	ELSE
		IF _Screen.nSysTrayCount > 0x3FFF
			* User is apparently creating and destroying this object repeatedly.
			_Screen.nSysTrayCount = 0	
		ENDIF
	ENDIF
	_screen.nSysTrayCount = _screen.nSysTrayCount + 1
	this.SystrayIconID = _screen.nSysTrayCount + MIN_SYSTRAY_ICON_ID


	*  By default, VFP combines MouseWheel events. (That is, if we receive
	*  a MouseWheel event from the OS, we check our internal queue to see
	*  if there is already a MouseWheel event that hasn't been processed yet.
	*  If found, we just add the number of MouseWheel turns to the existing
	*  event.)  This behavior makes our communication with the SystemTray
	*  unstable, so we must disable this combining of events.  SYS(2060)
	*  accomplishes this:
	THIS.nPrevMWAccrual = VAL(SYS(2060))
	SYS(2060, 1)
ENDIF



* Declare the WinAPI function that lets us install the icon.
* We redeclare the function every time, just in case CLEAR DLLS is called
* elsewhere in the app. 	
DECLARE INTEGER Shell_NotifyIcon IN shell32.dll AS WinAPI_Shell_NotifyIcon ;
	INTEGER dwMessage, ;
	STRING @ PNOTIFYICONDATA 

IF THIS.ShellVersion = 0	&& If we haven't set the version yet.
	nTipTextMaxLength = 63	&& Default to version 4.
ELSE
	nTipTextMaxLength = 127
ENDIF


*  Build NOTIFYICONDATA structure.
lcNotifyIconData = .IntegerToString(_VFP.Hwnd)	&& Messages get sent to VFP's main window.
lcNotifyIconData = lcNotifyIconData + .IntegerToString(.SystrayIconID * 0x10000)	
lcNotifyIconData = lcNotifyIconData + .IntegerToString(BITOR(NIF_TIP,NIF_MESSAGE ,NIF_ICON))	&&NIF_TIP,NIF_INFO,NIF_STATE
lcNotifyIconData = lcNotifyIconData + .IntegerToString(0x20A)	&& uCallback
lcNotifyIconData = lcNotifyIconData + .IntegerToString(.aIconList[.CurrentIconIndex])	&& icon handle
lcNotifyIconData = lcNotifyIconData + PADR(LEFT(TRANSFORM(.TipText), nTipTextMaxLength ), nTipTextMaxLength  + 1, CHR(0))	&& TipText
IF .ShellVersion >= 5
	lcNotifyIconData = lcNotifyIconData + .IntegerToString(0)	&& dwState
	lcNotifyIconData = lcNotifyIconData + .IntegerToString(0)	&& dwStateMask
	lcNotifyIconData = lcNotifyIconData + REPLICATE(CHR(0),256)	&& balloon tip.
	lcNotifyIconData = lcNotifyIconData + .IntegerToSTring(NOTIFYICON_VERSION) && Timeout/Version
	lcNotifyIconData = lcNotifyIconData + REPLICATE(CHR(0),64)	&& balloon tip title.
	lcNotifyIconData = lcNotifyIconData + .IntegerToSTring(BITAND(0, 0x1F)) && Info flags
ENDIF

lcNotifyIconData = .IntegerToString(LEN(lcNotifyIconData) + 4) + lcNotifyIconData	&& length of structure

IF NOT .Enabled		&& If not already in Taskbar Notification Area....

	*  Add icon to Taskbar Notification Area.
	nReturn = WinAPI_Shell_NotifyIcon( NIM_ADD, @lcNotifyIconData)
	IF nReturn <> 1
		*  Adding item to tray failed!!!
		IF _Screen.nSysTrayCount = 1
			* There has not been two simultaneous instances of this object
			* in the current session.  We can clean up after ourselves.
			_Screen.nSysTrayCount = 0
			SYS(2060, .nPrevMWAccrual)	&& Reset mousewheel behavior.
		ENDIF
		RETURN nReturn
	ENDIF
	*  Bind to the MouseWheel event on VFP's main window.
	nReturn = BINDEVENT(_screen,"MouseWheel",this,"receiveIconEvent",2)
	.Enabled = .t.
	
	* We've just added the icon.  Now we see if we can set to Version 5 shell behavior,
	* with larger tooltip lengths and support for balloon Tips.
	IF  .GetShellVersion() >= 5
		* This OS supports version 5 features.  Switch to version 5.
		
		* We have to inform the Shell that we want to use Version 5 features.
		* Build a version 5 structure for sending message to change version.
		lcNotifyIconData = .IntegerToString(_vfp.hwnd)
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(.SystrayIconID * 0x10000)	
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(BITOR(NIF_TIP,NIF_MESSAGE ,NIF_ICON))	&&NIF_TIP,NIF_INFO,NIF_STATE
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(0x20A)	&& uCallback
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(.aIconList[.CurrentIconIndex])	&& icon handle
		lcNotifyIconData = lcNotifyIconData + PADR(LEFT(TRANSFORM(.TipText), 127), 128, CHR(0))	&& TipText
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(0)	&& dwState
		lcNotifyIconData = lcNotifyIconData + .IntegerToString(0)	&& dwStateMask
		lcNotifyIconData = lcNotifyIconData + REPLICATE(CHR(0),256)	&& balloon tip.
		lcNotifyIconData = lcNotifyIconData + .IntegerToSTring(NOTIFYICON_VERSION) && Timeout/Version
		lcNotifyIconData = lcNotifyIconData + REPLICATE(CHR(0),64)	&& balloon tip title.
		lcNotifyIconData = lcNotifyIconData + .IntegerToSTring(BITAND(0, 0x1F)) && Info flags
		lcNotifyIconData = .IntegerToString(LEN(lcNotifyIconData) + 4) + lcNotifyIconData	&& length of structure
		
		*  First we check to see if we can switch to using version 5 events.
		nReturn = WinAPI_Shell_NotifyIcon( NIM_SETVERSION, @lcNotifyIconData)
		IF nReturn <> 1
			*  Couldn't switch to version 5 events
			RETURN -1
		ENDIF

		.ShellVersion = 5

		*  Now that we've updated to Version 5, we have to modify the existing icon
		*  if the .TipText is longer than 63 characters.
		IF LEN(.TipText) > 63
			nReturn = WinAPI_Shell_NotifyIcon( NIM_MODIFY, @lcNotifyIconData)
			IF nReturn <> 1
				RETURN nReturn
			ENDIF
		ENDIF
	ELSE
		.ShellVersion = 4
	ENDIF

ELSE
	*  Already in the Taskbar Notification Area.  Just update existing icon.
	nReturn = WinAPI_Shell_NotifyIcon( NIM_MODIFY, @lcNotifyIconData)
	IF nReturn <> 1
		MESSAGEBOX("		*  Modifying item in tray failed!!!")
		RETURN nReturn
	ENDIF
ENDIF

ENDWITH

RETURN nReturn	
**********************************
FUNCTION ReceiveIconEvent
LPARAMETERS nDirection, nShift, nXCoord, nYCoord
	* This is the procedure that receives the Notify Icon events.  Since
	* we execute the BindEvent() function from within this class, this
	* procedure can be hidden.
	* nDirection contains our icon identifier.

IF nDirection != this.SystrayIconID
	* Not our icon, or this a real MouseWheel event on the VFP window.
	RETURN .F.
ENDIF

*  These are the events that we receive from the Taskbar icon.
#DEFINE WM_MOUSEMOVE		0x0200
#DEFINE WM_LBUTTONDOWN		0x0201
#DEFINE WM_LBUTTONUP		0x0202
#DEFINE WM_LBUTTONDBLCLK	0x0203
#DEFINE WM_RBUTTONDOWN		0x0204
#DEFINE WM_RBUTTONUP		0x0205
#DEFINE WM_RBUTTONDBLCLK	0x0206
#DEFINE WM_MBUTTONDOWN		0x0207
#DEFINE WM_MBUTTONUP		0x0208
#DEFINE WM_MBUTTONDBLCLK	0x0209
*  Mousewheel events also get passed, but are difficult to decipher.
#define WM_CONTEXTMENU      0x007B	&& Same as RightClick, but used when 
									&& Version 5 events have been specified.
									&& (See the DisplayBalloonTip method.)

#define WM_USER             0x0400
#define NIN_SELECT          WM_USER + 0
#define NINF_KEY            0x1
#define NIN_KEYSELECT       BITOR(NIN_SELECT , NINF_KEY)

* Balloon events supported on Windows ME and Windows XP, and later. Not supported on Win2k.
#DEFINE NIN_BALLOONSHOW     (WM_USER + 2)
#DEFINE NIN_BALLOONHIDE     (WM_USER + 3)
#DEFINE NIN_BALLOONTIMEOUT  (WM_USER + 4)
#DEFINE NIN_BALLOONUSERCLICK (WM_USER + 5)

* Even though this isn't a real MouseWheel event on the VFP window,
* VFP gives us the coordinates with respect to the location of the
* main VFP window.  Must change back to global coordinates.
nXCoord = nXCoord + _screen.Left

IF nXCoord <> WM_MOUSEMOVE	&& Ignore mousemove events.
	* The Version 5 events are more difficult to deal with,
	* but Version 5 supports Balloon Tips.  So the extra work
	* is worth it.
	IF THIS.ShellVersion >= 5
		DO CASE
		CASE nXCoord = NIN_SELECT OR nXCoord = NIN_KEYSELECT
			THIS.IconClickEvent
		CASE nXCoord = WM_LBUTTONDBLCLK ;
				OR nXCoord = WM_RBUTTONDBLCLK ;
				OR nXCoord = WM_MBUTTONDBLCLK
			* We'll just use one DoubleClick event, and ignore what button was used.
			THIS.IconDblClickEvent
			RETURN
		CASE nXCoord = WM_CONTEXTMENU  && Shell version 5 and later
			THIS.IconRightClickEvent
			RETURN
		CASE nXCoord = WM_MBUTTONDOWN
			THIS.IconMiddleClickEvent
			RETURN
		CASE nXCoord = NIN_BALLOONSHOW
			THIS.BalloonShowEvent
			RETURN
		CASE nXCoord = NIN_BALLOONHIDE
			THIS.BalloonHideEvent
			RETURN
		CASE nXCoord = NIN_BALLOONTIMEOUT
			THIS.BalloonTimeoutEvent
			RETURN
		CASE nXCoord = NIN_BALLOONUSERCLICK
			This.BalloonClickEvent
			RETURN
		OTHERWISE
			*  Unknown event.  Just ignore it.
			RETURN
		ENDCASE
	ELSE
		*  Using Version 4 events.
		DO CASE
		CASE nXCoord = WM_LBUTTONDOWN 
			THIS.IconClickEvent
		CASE nXCoord = WM_LBUTTONDBLCLK ;
				OR nXCoord = WM_RBUTTONDBLCLK ;
				OR nXCoord = WM_MBUTTONDBLCLK
			* We'll just use one DoubleClick event, and ignore what button was used.
			THIS.IconDblClickEvent
			RETURN
		CASE nXCoord = WM_RBUTTONDOWN
			THIS.IconRightClickEvent
			RETURN
		CASE nXCoord = WM_MBUTTONDOWN 
			THIS.IconMiddleClickEvent
			RETURN
		OTHERWISE
			*  Unknown event.  Just ignore it.
			RETURN
		ENDCASE
	ENDIF
	
ENDIF

- Bill

Get the best answers to your questions -- See FAQ481-4875.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top