Thanks in advance,
Roman
===================================
'** put this in a bas file
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2002 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.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'uType parameters
Private Const MB_ICONINFORMATION As Long = &H40&
Private Const MB_ABORTRETRYIGNORE As Long = &H2&
Private Const MB_TASKMODAL As Long = &H2000&
'Windows-defined Return values. The return
'values and control IDs are identical.
Public Const IDOK = 1
Public Const IDCANCEL = 2
Public Const IDABORT = 3
Public Const IDRETRY = 4
Public Const IDIGNORE = 5
Public Const IDYES = 6
Public Const IDNO = 7
'VBnet-defined control ID for the message prompt
Private Const IDPROMPT = &HFFFF&
'misc 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
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function GetDesktopWindow Lib "user32" () 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 SetDlgItemText Lib "user32" _
Alias "SetDlgItemTextA" _
(ByVal hDlg As Long, _
ByVal nIDDlgItem As Long, _
ByVal lpString As String) 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 SetWindowText Lib "user32" _
Alias "SetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Function MessageBoxH(hwndThreadOwner As Long, hwndOwner As Long) As Long
'Wrapper function for the MessageBox API
Dim hInstance As Long
Dim hThreadId As Long
'Set up the CBT (computer-based training) hook
hInstance = GetWindowLong(hwndThreadOwner, 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 MSGHOOK
.hwndOwner = hwndOwner
.hHook = SetWindowsHookEx(WH_CBT, _
AddressOf MsgBoxHookProc, _
hInstance, hThreadId)
End With
'call the MessageBox API and return the
'value as the result of the function. The
'Space$(120) statements assures the messagebox
'is wide enough for the message that will
'be set in the hook.
'
'NOTE: I am setting the text in the hook only
'for demo purposes, to show how its done. You
'certainly can pass the title and prompt text
'right in the API call instead.
MessageBoxH = MessageBox(hwndOwner, _
Space$(120), _
Space$(120), _
MB_ABORTRETRYIGNORE Or MB_ICONINFORMATION)
End Function
Public Function MsgBoxHookProc(ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
'When the message box is about to be shown,
'we'll change the titlebar text, prompt message
'and button captions
If uMsg = HCBT_ACTIVATE Then
'in a HCBT_ACTIVATE message, wParam holds
'the handle to the messagebox
SetWindowText wParam, "VBnet MessageBox Hook Demo"
'the ID's of the buttons on the message box
'correspond exactly to the values they return,
'so the same values can be used to identify
'specific buttons in a SetDlgItemText call.
SetDlgItemText wParam, IDABORT, "Search C:\"
SetDlgItemText wParam, IDRETRY, "Search D:\"
SetDlgItemText wParam, IDIGNORE, "Cancel"
'Change the dialog prompt text ...
SetDlgItemText wParam, IDPROMPT, "MyApp will now locate the application." & _
"Please select the drive to search."
'we're done with the dialog, so release the hook
UnhookWindowsHookEx MSGHOOK.hHook
End If
'return False to let normal processing continue
MsgBoxHookProc = False
End Function
'--end block--'
'***** Put this is a form file
Prerequisites
VB5 / VB6.
--------------------------------------------------------------------------------
Windows provides a series of hook types, designed for specific purposes. Each type
provides access to a different aspect of its message-handling mechanism -- for
example, an application can use the WH_MOUSE hook to monitor the message traffic for
mouse messages. The system also maintains a separate hook chain for each type of
hook. A hook chain is a list of pointers to special, application-defined callback
functions called hook procedures. When a message occurs that is associated with a
particular type of hook, the system passes the message to each hook procedure
referenced in the hook chain, one after the other.
To take advantage of a particular type of hook, the developer provides a hook
procedure using the SetWindowsHookEx function to install it into the chain associated
with the hook. In this demo we will construct a standard messagebox using the
MessageBox API, then create a hook for the messagebox so we can catch the ACTIVATE
message sent just prior to its display. When the message is received, we'll use
SetDlgItemText to change the button captions, message prompt and dialog title.
What this code does is change the existing elements of the dialog. What it does not
do is change the orientation or size of those elements. Therefore, a few preliminary
words are necessary.
When a messagebox is normally created, its size is set to accommodate the wider of
the message or title passed, and the buttons are sized corresponding to the size
required for the MB_xxx parameter specified. Because, by the time we intercept the
HCBT_ACTIVATE message the dialog's dimensions have already been established,
subsequent code to change any aspect of the dialog needs to assure that the change
fits within the dialog's real estate, including that of the buttons. This means that,
without adding significant code to retrieve the size and resize/reposition the dialog
and buttons, you are restricted to displaying button text no longer than the original
captions. With prudent thought to the captions desired, this shouldn't be too
difficult a proposal.
The demo begins in a wrapper function for the MessageBox and SetWindowsHookEx APIs.
You may extend the capabilities of the wrapper to include passing the captions and
styles. For demo purposes, I chose to use the "Abort, Retry, Ignore" flag for the
buttons. One interesting thing that you can do is pass a Space$(x) as the prompt and
title parameters. By increasing the string passed, the dialog will grow wider.
Similarly, if you pass a series of shorter strings with imbedded vbCrLf's, you can
increase the height to accommodate a multi-line prompt.
The public Hook function traps the HCBT_ACTIVATE message, changes the captions and
unhooks itself, as no further processing is required.
A message box has pre-defined constants representing the return values from the
dialog. In VB we know these as vbOk, vbCancel, vbAbort, etc. In the API their values
are the same, but are known as IDOK, IDCANCEL and IDABORT, respectively.
Interestingly, and handily, these same return values are also the message box button
control ID's, which allows us to use the SetDlgItemText API to change the captions.
SetDlgItemText takes the hwnd of the messagebox (returned in the hook as wParam), and
the control ID upon which to act. The ID for the prompt text is &HFFFF&.
The thing to remember here is that the values you receive back from the dialog will
be the same values as if the dialog was displaying its default button text. So for
this example, the "Search C:\" button will return IDABORT, the "Search D:\" button
will return IDRETRY, and the the "Cancel" button will return IDIGNORE, because the
dialog was created with the MB_ABORTRETRYIGNORE style. Similarly, if you passed
vbYesNoCancel as the style, the return values would be vbYes, vbNo and vbCancel
(IDYES, IDNO, IDCANCEL in API-speak). You may find it practical, in an application
that routinely used different meanings for the buttons, to define your own constants
using Const ID_SCAN_C = IDABORT, ID_SCAN_D = IDRETRY, and ID_SCAN_CANCEL = IDIGNORE.
Your select case statements would then make more sense.
To show how little code is needed to actually perform this demo, I have only provided
the declares for functions and constants actually used. You can grab the complete set
from the API viewer, or from the MessageBoxEx example page here in the sample Using
Win32's MessageBoxEx API.
BAS Module Code
Place the following code into the general declarations area of a bas module:
--------------------------------------------------------------------------------
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2002 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.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'uType parameters
Private Const MB_ICONINFORMATION As Long = &H40&
Private Const MB_ABORTRETRYIGNORE As Long = &H2&
Private Const MB_TASKMODAL As Long = &H2000&
'Windows-defined Return values. The return
'values and control IDs are identical.
Public Const IDOK = 1
Public Const IDCANCEL = 2
Public Const IDABORT = 3
Public Const IDRETRY = 4
Public Const IDIGNORE = 5
Public Const IDYES = 6
Public Const IDNO = 7
'VBnet-defined control ID for the message prompt
Private Const IDPROMPT = &HFFFF&
'misc 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
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function GetDesktopWindow Lib "user32" () 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 SetDlgItemText Lib "user32" _
Alias "SetDlgItemTextA" _
(ByVal hDlg As Long, _
ByVal nIDDlgItem As Long, _
ByVal lpString As String) 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 SetWindowText Lib "user32" _
Alias "SetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Function MessageBoxH(hwndThreadOwner As Long, hwndOwner As Long) As Long
'Wrapper function for the MessageBox API
Dim hInstance As Long
Dim hThreadId As Long
'Set up the CBT (computer-based training) hook
hInstance = GetWindowLong(hwndThreadOwner, 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 MSGHOOK
.hwndOwner = hwndOwner
.hHook = SetWindowsHookEx(WH_CBT, _
AddressOf MsgBoxHookProc, _
hInstance, hThreadId)
End With
'call the MessageBox API and return the
'value as the result of the function. The
'Space$(120) statements assures the messagebox
'is wide enough for the message that will
'be set in the hook.
'
'NOTE: I am setting the text in the hook only
'for demo purposes, to show how its done. You
'certainly can pass the title and prompt text
'right in the API call instead.
MessageBoxH = MessageBox(hwndOwner, _
Space$(120), _
Space$(120), _
MB_ABORTRETRYIGNORE Or MB_ICONINFORMATION)
End Function
Public Function MsgBoxHookProc(ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
'When the message box is about to be shown,
'we'll change the titlebar text, prompt message
'and button captions
If uMsg = HCBT_ACTIVATE Then
'in a HCBT_ACTIVATE message, wParam holds
'the handle to the messagebox
SetWindowText wParam, "VBnet MessageBox Hook Demo"
'the ID's of the buttons on the message box
'correspond exactly to the values they return,
'so the same values can be used to identify
'specific buttons in a SetDlgItemText call.
SetDlgItemText wParam, IDABORT, "Search C:\"
SetDlgItemText wParam, IDRETRY, "Search D:\"
SetDlgItemText wParam, IDIGNORE, "Cancel"
'Change the dialog prompt text ...
SetDlgItemText wParam, IDPROMPT, "MyApp will now locate the application." & _
"Please select the drive to search."
'we're done with the dialog, so release the hook
UnhookWindowsHookEx MSGHOOK.hHook
End If
'return False to let normal processing continue
MsgBoxHookProc = False
End Function
'--end block--'
~~~ Form Code ~~~~~
Option Explicit
Private Sub Command1_Click()
'Display our wrapper message box.
'The first parameter passed is
'required for GetWindowLong, and
'specifies the window who's instance
'will be passed to SetWindowsHookEx.
'The second parameter is used in the
'hook and MessageBox call, and indicates
'who receives error messages and where
'the dialog will appear.
Select Case MessageBoxH(Me.hwnd, GetDesktopWindow())
Case IDABORT: Text1.Text = "Scan C selected"
Case IDRETRY: Text1.Text = "Scan D selected"
Case IDIGNORE: Text1.Text = "Cancel selected"
End Select
End Sub
'--end block--'
============================================
NO CREDITS TO ME...
This code is taken from Randy Birch's Homepage...
http://www.mvps.org/vbnet/index.html
--
Regards
(¯`·._Munim.VIP_.·´¯)
* Respect Human Intellectual,
But Help Those Who Cannot Afford.
My E-Mail: Munim...@MyRealBox.com
My Msn ID: Munim_...@Hotmail.com (primary)
My Yahoo! ID: Munim_Online
My Homepage : HTTP://WWW.Munim.TK
(FREE!!! Win32 API Delphi, Visual Basic 'N Visual C++ source codes)
"Roman >" <<Rom...@mbsnetinc.com> wrote in message
news:#y9PDI6bCHA.384@tkmsftngp11...
> ' 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.
--
Ken Halter - MS-MVP-VB - Please keep it in the groups..
http://www.vbsight.com - http://www.vbsight.com/MultiColumn.htm
http://www.vbsight.com/TBGDialogCTL.htm
"Munim.VIP" <Munim...@MyRealBox.com> wrote in message
news:ao1gvt$if4n6$1...@ID-164377.news.dfncis.de
Even if he did (a tad doubtful), posting a link would still have been
infinitely preferable to posting a 500 line message. *sigh*
Adam
--
In war, truth is the first casualty.
-- U Thant