Centered MessageRequester() / MessageBox()

Posted by on July 2, 2009

As usual, I was browsing the PureBasic forums to see what was new, nothing much (heh…) but something caught my attention, the fact that some user requested for the IDE’s message dialogs to be “centered” ( because he had multiple displays and the messages would appear in between them ) just to get shit-faced by an actual staff member!

You can’t just say “it’s Microsoft’s fault” — Are you in some sort of mac-only cleanse?, What’s your #%&%#$ problem?!

Those who “pass the ball” (as the user suggested) are part of the problem. You, being a programmer can certainly code a simple CBT hook, right?. Are you against hooks, perhaps – you are a purist, I hear… Sorry, but sometimes solutions are “dirty” and you have to live with them.

Just for the record, I too use a split-screen and I find it annoying that dialog boxes are not centered to their parent.

Just for the record, I too use a split-screen and I find it annoying that dialog boxes are not centered to their parent.

I certainly think that this sort of behavior is not good for a business, but then again they’ve been cat-walking away from reality for years now (Look at their website if not, look at the fact that they haven’t implemented basic functionality to their language and by basic I mean a proper container library and whatnot!). Most of their user-base consists of people who are afraid of real, world-class languages. That’s my opinion, take it or leave it.

But before you throw crap at me do remember that I support them, I just don’t like the way they’re doing things. Pretty much like Apple does (they do crap) however the fanboys don’t realize this and they see any criticism as bad for the company image, when in fact what damages the company is that nonsense wall they put up when anybody, and I do mean “anybody” says “anything” that appears to be “against” their product/s.

Even if you don’t like it at least have the decency to hear those who are genuinely interested in your product, those who are giving away (and for free) true and useful suggestions for you to improve them. I don’t give a damn about this particular user but I do care when a so called company does this sort of things to their own users, it’s just uncalled for and plainly unprofessional.

Have a nice day, code follows.

; This snippet was based on the following code by Microsoft:
; http://support.microsoft.com/kb/180936
EnableExplicit ; The only way to go.

Procedure.i CenterMsgCallBack( uMsg.i, wParam.i, lParam.i ) 

	Select uMsg
		Case #HCBT_ACTIVATE

			Define.RECT typFormRect, typRectMsg
			Define.i plMsgHook, hWnd
			Define.i lxPos, lyPos

			hWnd = GetParent_(wParam) 																																																		; the parent will be the callee

			If hWnd 																																																											; can't hurt to check.

				plMsgHook 	= GetWindowLong_( hWnd, #GWL_USERDATA ) 																																				; get the hook address

				If plMsgHook 																																																								; can't hurt to check.

					GetWindowRect_( hWnd, typFormRect )
					GetWindowRect_( wParam, typRectMsg )

					lxPos = (typFormRect\Left + (typFormRect\Right - typFormRect\Left) / 2) - ((typRectMsg\Right - typRectMsg\Left) / 2)
					lyPos = (typFormRect\Top  +	(typFormRect\Bottom - typFormRect\Top) / 2) - ((typRectMsg\Bottom - typRectMsg\Top) / 2)

					SetWindowPos_( wParam, 0, lxPos, lyPos, 0, 0,	#SWP_NOSIZE | #SWP_NOZORDER | #SWP_NOACTIVATE ) 														; position the window.
					UnhookWindowsHookEx_(plMsgHook) 																																													; release the hook.
					SetWindowLong_( hWnd, #GWL_USERDATA, #Null ) 																																							; unset the user data.

				EndIf

			EndIf
	EndSelect

EndProcedure 

Procedure.i CenteredMessageRequester( Title.s, Text.s, Flags.i=#Null, hWnd.i=#Null )

	Define.i lInstance, lThreadID, plMsgHook

	If Not hWnd
		hWnd = WindowID( GetActiveWindow() )
	EndIf

	If hWnd

		lInstance = GetWindowLong_( hWnd, #GWL_HINSTANCE )
		lThreadID = GetCurrentThreadId_()

		If lInstance And lThreadID 																																																			; just to make sure, can't hurt.

			plMsgHook = SetWindowsHookEx_(#WH_CBT, @CenterMsgCallBack(), lInstance, lThreadID) 																						; create the cbt hook.
			SetWindowLong_(	hWnd, #GWL_USERDATA, plMsgHook ) 																																							; save the hook address, we'll need it to release it.

			ProcedureReturn MessageBox_( hWnd, Text, Title, Flags )																																				; finally, create the message box.

		EndIf
	EndIf

EndProcedure

And a small example:

OpenWindow( 0, 500, 200, 400, 200, "testing" )																																											; test window
MessageRequester( ":(", "I'm a normal messagebox", #MB_APPLMODAL | #MB_ICONERROR )																									; conventional msgbox
CenteredMessageRequester( ":)", "I'm a centered messagebox!", #MB_APPLMODAL | #MB_ICONEXCLAMATION )																	; our centered msgbox.

The “Programmer” can now copy&paste and compile.

Cheers.

PS: You can also find the source in here: http://gushh.net/dev/?file=pb/centermessagebox.pb As usual, that’s my code repository for PB.