Wiki Home

Window Proc VFP


Namespace: WIN_COM_API
The Window Proc function is an application-defined function that processes messages sent to a window.

The Get Window LongOffsite link to http://www.news2news.com/vfp/?function=159
API function retrieves the address of the window procedure, or a handle representing the address of the window procedure. The Set Window LongOffsite link to http://www.news2news.com/vfp/?function=290
function creates the subclass by changing the window procedure associated with a particular window, causing the system to call the new window procedure instead of the previous one.

This is how it works in VB:
OldWindowProc = Set Window LongOffsite link to http://www.news2news.com/vfp/?function=290
(hWnd, GWL_WNDPROC, Address Of NewWindowProc)

There is no direct way how to provide this function with the address of a VFP procedure (VFP6, imho). Creating a DLL and passing hWnd to its function solves this problem, though new Window Proc will be contained within this DLL. Still it gives a chance to intercept messages being sent to the VFP form.

The next problem is how to pass the intercepted messages back to the VFP.

The VFP application creates a DDE Server with a topic linked to a VFP function intended to process messages. The DLL code connects to this server then sending intercepted messages through the DdeClientTransaction function with XTYP_POKE parameter (similar to the DDEPoke function).

The mentioned VFP function receives three main parameters for every message: Msg, wParam, and lParam.

The following Windows Messages are typically sent to the Window Proc function of a VFP form (the list is not complete):
WM_CAPTURECHANGED
WM_CHILDACTIVATE
WM_DESTROY
WM_ENTERSIZEMOVE
WM_ERASEBKGND
WM_EXITSIZEMOVE
WM_GETMINMAXINFO
WM_GETTEXT
WM_KEYUP
WM_KILLFOCUS
WM_LBUTTONDBLCLK
WM_LBUTTONUP
WM_MOUSEACTIVATE
WM_MOUSEMOVE
WM_MOVE
WM_MOVING
WM_NCCALCSIZE
WM_NCDESTROY
WM_NCHITTEST
WM_NCLBUTTONDOWN
WM_NCMOUSEMOVE
WM_NCPAINT
WM_PAINT
WM_QUERYNEWPALETTE
WM_QUERYOPEN
WM_SETCURSOR
WM_SETFOCUS
WM_SHOWWINDOW
WM_SIZE
WM_SIZING
WM_STYLECHANGED
WM_STYLECHANGING
WM_SYSCOMMAND
WM_SYSKEYDOWN
WM_WINDOWPOSCHANGED
WM_WINDOWPOSCHANGING


Anatoliy Mogylevets
Hi Anatoliy,
When yo set up the structure WNDCLASSEX (which requires in the structure the 'Address Of' pointer to the Window Proc function), do you think there is a way of using a custom object with a property_assign (eg WindowProc_Assign) which would fire everytime the 'property' is changed? (I hope that you can understand this as it's a complicated thought process!). If this could work, the assign method could handle the same logic as a true Window Proc function in VB.

Peter Easson


This code needs it's own page, but I couln't figure out a topic title, so I figured I would let someone else do that part.

*!*   API calls to know how many times a program is running:

*!*   This looks like we might be able to see if someone else is in the application on a server.

*!*   If ur application is running from central server then it is possible
*!*   to count no. of instanses dynamacally using API Calls.
*!*
*!*   this method is used in my application.
*!*   You can change Your Application Caption insted of "Int-E-View 2000" in following Code.

*!*   You are free to use this code in your application.
#Define AppName "WinPars"
Set Step on

lox = CreateObject( "AppInstances" )

Define Class AppInstances As Custom
	Procedure Init
	This.VerifyInstance(.t.)
	Endproc

	Procedure VerifyInstance(lMessageOnly As Boolean) As Integer
	With This
		.DllInit()
		Local hWinActive, hWindow, lcWinText, hWinCount, lnWinIndex
		hWinActive = GetActiveWindow()
		hWindow = -1
		hWinCount = 0
		nCounter = 0

		#Define GW_HWNDFIRST  0
		#Define GW_HWNDLAST   1
		#Define GW_HWNDNEXT   2

		Do While hWindow <> GetWindow (hWinActive, GW_HWNDLAST)
			If hWindow = -1
				hWindow = GetWindow(hWinActive, GW_HWNDFIRST)
			Else
				hWindow = GetWindow(hWindow, GW_HWNDNEXT)
			Endif

			If IsWindow(hWindow) <> 0 And IsWindowVisible(hWindow) <> 0;
					And GetWindowTextLength(hWindow) > 0
				lcWinText = .GetWinText(hWindow)
				If hWindow <> hWinActive And Not "Program Manager" $ lcWinText
					hWinCount = hWinCount + 1
					Dimen arrWin[hWinCount, 2]
					arrWin[hWinCount, 1] = hWindow
					arrWin[hWinCount, 2] = lcWinText
				Endif
			Endif
		Enddo

		If hWinCount > 0
			nCounter = 0
			For lnWinIndex=1 To hWinCount
				aa = Upper(arrWin[lnWinIndex, 2])

				? aa

				If Left(aa,15) = AppName
					nCounter = nCounter + 1
				Endif
			Endfor
			If lMessageOnly  And nCounter >= 1
				If nCounter = 1
					Messagebox(Transform(nCounter,"999  ")+" Instance of Your Application is already opened.  ",0,_Screen.Caption)
				Else
					Messagebox(Transform(nCounter,"999  ")+" Instance of Your Application  are already opened  ",0,_Screen.Caption)
				Endif
			Else
			Endif
		Endif
	Endwith
	Return nCounter
	Endproc

	Function  CloseApp (hWindow)
	#Define WM_QUIT            18
	#Define WM_SYSCOMMAND     274
	#Define SC_CLOSE        61536 && 0xF060
	#Define PROCESS_TERMINATE   1
	Local hWinProcId, hWinThreadId, hProcess

	Declare SHORT PostMessage In user32;
		INTEGER HWnd, Integer Msg, Integer wParam, Integer Lparam
	= PostMessage(hWindow, WM_SYSCOMMAND, SC_CLOSE, 0)
	= Inkey(0.1)
	If IsWindow(hWindow) = 0
		Return .T.
	Endif
	This.GetThreadProcessId (hWindow, @hWinProcId, @hWinThreadId)
	hProcess = OpenProcess(PROCESS_TERMINATE, 0, hWinProcId)
	If hProcess <> 0
		=TerminateProcess(hProcess, 0)
		=CloseHandle(hProcess)
	Endif
	Endfunc

	Function  GetWinText(hWindow)
	Local lnBufsize, lcBuffer
	lnBufsize = 1024
	lcBuffer = Repli(Chr(0), lnBufsize)
	lnBufsize = GetWindowText(hWindow, @lcBuffer, lnBufsize)
	Return  Iif(lnBufsize=0, "", Left(lcBuffer,lnBufsize))
	Endfunc

	Procedure  GetThreadProcessId(hWindow, hProcId, hThreadId)
	Store 0 To hProcId, hThreadId
	hThreadId = GetWindowThreadProcessId(hWindow, @hProcId)
	Endproc

	Procedure  DllInit
	Declare Integer GetActiveWindow  In user32
	Declare Integer GetWindow In user32 Integer HWnd, Integer wFlag
	Declare Integer IsWindow In user32 Integer HWnd
	Declare Integer IsWindowVisible In user32 Integer HWnd
	Declare Integer GetWindowTextLength In user32 Integer HWnd
	Declare Integer CloseHandle In kernel32 Integer hObject

	Declare Integer GetWindowText In user32;
		INTEGER HWnd, String @lpString, Integer cch

	Declare Integer GetWindowThreadProcessId In user32;
		INTEGER HWnd, Integer @lpdwProcId

	Declare Integer OpenProcess In kernel32;
		INTEGER dwDesiredAccess, Integer bInheritHandle,;
		INTEGER dwProcId

	Declare Integer TerminateProcess In kernel32;
		INTEGER hProcess, Integer uExitCode
	Endproc
Enddefine

____
( Topic last updated: 2004.05.14 12:10:38 PM )