|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Hook Routines SetWindowsHookEx: Centre the API Message Box |
|
Posted: | Thursday April 11, 2002 |
Updated: | Monday December 26, 2011 |
Applies to: | VB5, VB6 |
Developed with: | VB6, Windows 2000 |
OS restrictions: | None |
Author: | VBnet - Randy Birch |
Related: |
SetWindowsHookEx: 'Self-Closing' Message Box using a VB Timer SetWindowsHookEx: 'Self-Closing' Message Box using SetTimer SetWindowsHookEx: Detect Caps/Numlock/Scrollock via System-wide Keyboard Hook SetWindowsHookEx: Customize the API Message Box SetWindowsHookEx: Trapping Special Key Events using Low Level Hooks MessageBoxEx: Displaying an API-created Message Box |
Prerequisites |
VB5 / VB6. |
|
Like
the other MessageBox demos, this one centres on centering, so to speak.
Using the same hook code from the timed and modify demos, and the same
centering code as the GetOpenFileName hook demo, the message box created
via API can be placed wherever you want ... in this demo centered in the
parent. The technique shown here is easily ported to any of the other hook demos above. Note too that this demo makes use of VB5 and VB6's ability to override existing VB functions by providing new methods using the same name ... i.e. this demo replaces VB's intrinsic MsgBox function by naming the API method called "MsgBox". For a complete discussion of hooking, see SetWindowsHookEx: Customize the API Message Boxabove. |
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'misc API constants Private Const WH_CBT = 5 Private Const GWL_HINSTANCE = (-6) Private Const HCBT_ACTIVATE = 5 'UDT for passing data through the hook Private Type MSGBOX_HOOK_PARAMS hwndOwner As Long hHook As Long End Type Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type 'need this declared at module level as 'it is used in the call and the hook proc Private mhp As MSGBOX_HOOK_PARAMS Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long Private Declare Function GetWindowLong Lib "user32" _ Alias "GetWindowLongA" _ (ByVal hwnd As Long, _ ByVal nIndex As Long) As Long Private Declare Function MessageBox Lib "user32" _ Alias "MessageBoxA" _ (ByVal hwnd As Long, _ ByVal lpText As String, _ ByVal lpCaption As String, _ ByVal wType As Long) As Long Private Declare Function SetWindowsHookEx Lib "user32" _ Alias "SetWindowsHookExA" _ (ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Private Declare Function UnhookWindowsHookEx Lib "user32" _ (ByVal hHook As Long) As Long Private Declare Function MoveWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal X As Long, _ ByVal Y As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal bRepaint As Long) As Long Private Declare Function GetWindowRect Lib "user32" _ (ByVal hwnd As Long, _ lpRect As RECT) As Long Public Function Msgbox(sPrompt As String, _ Optional dwStyle As Long, _ Optional sTitle As String) As Long 'replaces VB's built in MsgBox function in VB5/6 Dim hInstance As Long Dim hThreadId As Long If dwStyle = 0 Then dwStyle = vbOKOnly If Len(sTitle) = 0 Then sTitle = "VBnet Messagebox Demo" 'Set up the hook hInstance = GetWindowLong(Form1.hwnd, GWL_HINSTANCE) hThreadId = GetCurrentThreadId() 'set up the MSGBOX_HOOK_PARAMS values 'By specifying a Windows hook as one 'of the params, we can intercept messages 'sent by Windows and thereby manipulate 'the dialog With MHP .hwndOwner = Form1.hwnd .hHook = SetWindowsHookEx(WH_CBT, _ AddressOf MsgBoxHookProc, _ hInstance, hThreadId) End With 'call the MessageBox API and return the 'value as the result of this function Msgbox = MessageBox(Form1.hwnd, sPrompt, sTitle, dwStyle) End Function Public Function MsgBoxHookProc(ByVal uMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Dim rc As RECT 'temporary vars for demo Dim newLeft As Long Dim newTop As Long Dim dlgWidth As Long Dim dlgHeight As Long Dim scrWidth As Long Dim scrHeight As Long Dim frmLeft As Long Dim frmTop As Long Dim frmWidth As Long Dim frmHeight As Long Dim hwndMsgBox As Long 'When the message box is about to be shown, 'centre the dialog If uMsg = HCBT_ACTIVATE Then 'in a HCBT_ACTIVATE message, wParam holds 'the handle to the messagebox hwndMsgBox = wParam 'Just as was done in other API hook demos, 'position the dialog centered in the calling 'parent form Call GetWindowRect(hwndMsgBox, rc) frmLeft = Form1.Left \ Screen.TwipsPerPixelX frmTop = Form1.Top \ Screen.TwipsPerPixelY frmWidth = Form1.Width \ Screen.TwipsPerPixelX frmHeight = Form1.Height \ Screen.TwipsPerPixelX dlgWidth = rc.Right - rc.Left dlgHeight = rc.Bottom - rc.Top scrWidth = Screen.Width \ Screen.TwipsPerPixelX scrHeight = Screen.Height \ Screen.TwipsPerPixelY newLeft = frmLeft + ((frmWidth - dlgWidth) \ 2) newTop = frmTop + ((frmHeight - dlgHeight) \ 2) Call MoveWindow(hwndMsgBox, newLeft, newTop, dlgWidth, dlgHeight, True) 'done with the dialog so release the hook UnhookWindowsHookEx MHP.hHook End If 'return False to let normal 'processing continue MsgBoxHookProc = False End Function |
Form Code |
Add a text box (Text1) and a command button (Command1) to a form, along with the following code: |
|
Option Explicit Private Sub Command1_Click() 'Display the API message box Dim sTitle As String Dim sPrompt As String Dim dwStyle As Long sTitle = "VBnet MessageBox Hook Demo" sPrompt = "This is a demo of the MessageBox API showing how to hook" & vbCrLf & _ "the dialog and centre it with respect to the parent form." dwStyle = vbAbortRetryIgnore Or vbInformation Select Case Msgbox(sPrompt, dwStyle, sTitle) Case vbRetry: Text1.Text = "Retry button pressed" Case vbAbort: Text1.Text = "Abort button pressed" Case vbIgnore: Text1.Text = "Ignore button pressed" End Select End Sub |
Comments |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |