Attribute VB_Name = "modMsgBoxEnh"
'--------------------------------------------------------------
' Thanks to Randy Birch for this code.
'--------------------------------------------------------------

'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), _
                vbOKCancel Or vbQuestion)

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, "Log Off"
      
     '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, IDOK, "Log Off"
      SetDlgItemText wParam, IDCANCEL, "Cancel"
            
     'Change the dialog prompt text ...
      SetDlgItemText wParam, IDPROMPT, "Are you sure you want to log off?"
                                             
     '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



