Creating an application-defined hook

Share your advanced PureBasic knowledge/code with the community.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Creating an application-defined hook

Post by Mistrel »

Converted to PureBasic from this example.
http://www.codeguru.com/cpp/w-p/win32/m ... php/c4541/

"Message boxes are normally placed in the center of the desktop window. It is often desirable to create messages boxes over the parent app window. This cannot be done by using the standard Win32 API call:"

Code: Select all

MessageBox_(hwnd,lpText.s,lpCaption.s,uType)
"The code below centers a message box over a parent window by using a CBT (computer-based training) hook. All message box calls are made with a substitute function called "CBTMessageBox," which inserts the CBT hook prior to activating a message box.

The CBTProc function processes a thread-specific hook. The needed notification code is HCBT_ACTIVATE, which is issued whenever a new window is about to be activated (made visible). The wParam holds the forthcoming window handle value. The parent window handle can be found by using the GetForegroundWindow() function.

Centering is done by finding the center point of the parent window and by calculating the upper left corner starting point of the message box. The starting point will be adjusted if the message box dimensions exceed the desktop window region.

The CBT hook will remain active until the necessary HCBT_ACTIVATE code is issued. Because several other CBT codes may be waiting in the hook queue when the SetWindowsHookEx call is made, it is useful to have the CBTProc continue the hook chain if another code is issued first. The CallNextHookEx function helps to ensure proper chaining of hooks issued by other apps.

The CBT hook process can be used to center any window to another. Just declare the hhk=SetWindowsHookEx function before activating a window."

Code: Select all

; Declare functions
Declare CBTMessageBox(hwnd,lpText.s,lpCaption.s,uType)
Declare CBTProc(nCode,wParam,lParam)

; Declare hook handle As Global
Global hhk

; Add functions
Procedure CBTMessageBox(hwnd,lpText.s,lpCaption.s,uType)
	hhk=SetWindowsHookEx_(#WH_CBT,@CBTProc(),0,GetCurrentThreadId_())
	ProcedureReturn MessageBox_(hwnd,lpText.s,lpCaption.s,uType)
EndProcedure

Procedure CBTProc(nCode,wParam,lParam)
	Define hParentWnd
	Define hChildWnd ; msgbox is "child"
	Define rParent.RECT
	Define rChild.RECT
	Define rDesktop.RECT
	Define pCenter.POINT
	Define pStart.POINT
	Define nWidth
	Define nHeight
	
	; notification that a window is about To be activated
	; window handle is wParam
	If nCode=#HCBT_ACTIVATE
		Debug 1
		; set window handles
		hParentWnd=GetForegroundWindow_()
		hChildWnd=wParam
		
		If hParentWnd And hChildWnd And (GetWindowRect_(GetDesktopWindow_(),@rDesktop)) And (GetWindowRect_(hParentWnd,@rParent)) And (GetWindowRect_(hChildWnd,@rChild))
			; calculate message box dimensions
			nWidth=(rChild\right-rChild\left)
			nHeight=(rChild\bottom-rChild\top)
			
			; calculate parent window center point
			pCenter\x=rParent\left+((rParent\right-rParent\left)/2)
			pCenter\y=rParent\top+((rParent\bottom-rParent\top)/2)
			
			; calculate message box starting point
			pStart\x=(pCenter\x-(nWidth/2))
			pStart\y=(pCenter\y-(nHeight/2))
			
			; adjust If message box is off desktop
			If(pStart\x<0)
				pStart\x=0
			EndIf
			If(pStart\y<0)
				pStart\y=0
			EndIf
			If(pStart\x+nWidth>rDesktop\right)
				pStart\x=rDesktop\right-nWidth
			EndIf
			If(pStart\y+nHeight>rDesktop\bottom)
				pStart\y=rDesktop\bottom-nHeight
			EndIf
			
			; move message box
			MoveWindow_(hChildWnd,pStart\x,pStart\y,nWidth,nHeight,#False)
			EndIf
		; exit CBT hook
		UnhookWindowsHookEx_(hhk);
	Else ; otherwise, Continue With any possible chained hooks
		CallNextHookEx_(hhk,nCode,wParam,lParam)
	EndIf
	ProcedureReturn 0
EndProcedure

OpenWindow(0,0,0,320,240,"")

;MessageBox_(WindowID(0),"Hello!","",#MB_OK)
CBTMessageBox(WindowID(0),"Hello!","",#MB_OK)

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
; Substitute CBTMessageBox(HWND,LPTEXT,LPCAPTION,UITYPE);
; instead of MessageBox(HWND,LPTEXT,LPCAPTION,UITYPE);
; To produce a centered message box.
tomijan
Enthusiast
Enthusiast
Posts: 107
Joined: Sun Dec 11, 2005 1:32 pm

Post by tomijan »

Works fine,
thanks Mistrel!
tom
registered user
Post Reply