Jump to content

Recommended Posts

Posted (edited)

Hello,

it's quite often, that someone asks how to change the texts of the MsgBox buttons or the InputBox buttons or how to change the position of ta MsgBox. Since years I use CBT hooks for that, but now I made a small UDF out of it for the ease of use. Of course you can build your own GUI or use already existing UDFs to do the same, but I like this way and you can hack (hook) the inbuild InputBox.

 

HookDlgBox.au3

#include-once
#include <WinAPI.au3>

Global Const $tagCBT_CREATEWND = "ptr lpcs;HWND tagCBT_CREATEWND"
Global Const $tagCREATESTRUCT = "ptr lpCreateParams;handle hInstance;HWND hMenu;HWND hwndParent;int cy;int cx;int y;int x;LONG style;ptr lpszName;ptr lpszClass;DWORD dwExStyle"

Global $g__hProcDlgBox = DllCallbackRegister("__DlgBox_CbtHookProc", "LRESULT", "int;WPARAM;LPARAM")
Global $g__TIdDlgBox = _WinAPI_GetCurrentThreadId()
Global $g__hHookDlgBox = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($g__hProcDlgBox), 0, $g__TIdDlgBox)

Global Const $g__MaxDlgBtns = 5 ; maximum of 5 buttons to rename text
Global Const $g__MaxDlgItemId = 11 ; maximun ID of buttons to search is 11 as this is the maximun used in Messagebox

Global $g__DlgBoxPosX, $g__DlgBoxPosY, $g__DlgBoxWidth, $g__DlgBoxHeight
Global $g__aDlgBoxBtnText[$g__MaxDlgBtns]

Global $g__DlgBtnCount = 0

_DlgBox_SetDefaults()

OnAutoItExitRegister("__DlgBox_UnregisterHook")


Func _DlgBox_SetButtonNames($TxtBtn1 = Default, $TxtBtn2 = Default, $TxtBtn3 = Default, $TxtBtn4 = Default, $TxtBtn5 = Default)
    $g__aDlgBoxBtnText[0] = $TxtBtn1
    $g__aDlgBoxBtnText[1] = $TxtBtn2
    $g__aDlgBoxBtnText[2] = $TxtBtn3
    $g__aDlgBoxBtnText[3] = $TxtBtn4
    $g__aDlgBoxBtnText[4] = $TxtBtn5

    $g__DlgBtnCount = @NumParams
EndFunc   ;==>_DlgBox_SetButtonNames

Func _DlgBox_SetPosition($x = Default, $y = Default) ;only for MsgBox, not working and not needed for InputBox
    $g__DlgBoxPosX = $x
    $g__DlgBoxPosY = $y
EndFunc   ;==>_DlgBox_SetPosition

Func _DlgBox_SetSize($w = Default, $h = Default)
    $g__DlgBoxWidth = $w
    $g__DlgBoxHeight = $h
EndFunc   ;==>_DlgBox_SetSize

Func _DlgBox_SetDefaults()
    $g__DlgBoxPosX = Default
    $g__DlgBoxPosY = Default
    $g__DlgBoxWidth = Default
    $g__DlgBoxHeight = Default
    For $i = 0 To UBound($g__aDlgBoxBtnText) - 1
        $g__aDlgBoxBtnText[$i] = Default
    Next
EndFunc   ;==>_DlgBox_SetDefaults

Func __DlgBox_CbtHookProc($nCode, $wParam, $lParam)
    Local $tcw, $tcs
    Local $iSearch = 0
    Local $ahBtn[$g__DlgBtnCount]
    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($g__hHookDlgBox, $nCode, $wParam, $lParam)
    EndIf

    Switch $nCode
        Case 3 ;5=HCBT_CREATEWND
            If _WinAPI_GetClassName(HWnd($wParam)) = "#32770" Then ;Dialog window class
                $tcw = DllStructCreate($tagCBT_CREATEWND, $lParam)
                $tcs = DllStructCreate($tagCREATESTRUCT, DllStructGetData($tcw, "lpcs"))

                If $g__DlgBoxPosX <> Default Then DllStructSetData($tcs, "x", $g__DlgBoxPosX)
                If $g__DlgBoxPosY <> Default Then DllStructSetData($tcs, "y", $g__DlgBoxPosY)
                If $g__DlgBoxWidth <> Default Then DllStructSetData($tcs, "cx", $g__DlgBoxWidth)
                If $g__DlgBoxHeight <> Default Then DllStructSetData($tcs, "cy", $g__DlgBoxHeight)
            EndIf
        Case 5 ;5=HCBT_ACTIVATE
            If _WinAPI_GetClassName(HWnd($wParam)) = "#32770" Then ;Dialog window class
                For $i = 1 To $g__MaxDlgItemId
                    If IsHWnd(_WinAPI_GetDlgItem($wParam, $i)) Then
                        If $g__aDlgBoxBtnText[$iSearch] <> Default Then _WinAPI_SetDlgItemText($wParam, $i, $g__aDlgBoxBtnText[$iSearch])
                        $iSearch += 1
                        If $iSearch >= UBound($ahBtn) Then ExitLoop
                    EndIf
                Next
            EndIf
    EndSwitch
    Return _WinAPI_CallNextHookEx($g__hHookDlgBox, $nCode, $wParam, $lParam)
EndFunc   ;==>__DlgBox_CbtHookProc

Func __DlgBox_UnregisterHook()
    _WinAPI_UnhookWindowsHookEx($g__hHookDlgBox)
    DllCallbackFree($g__hProcDlgBox)
EndFunc   ;==>__DlgBox_UnregisterHook

Func _WinAPI_SetDlgItemText($hDlg, $nIDDlgItem, $lpString)
    Local $aRet = DllCall('user32.dll', "int", "SetDlgItemText", _
            "hwnd", $hDlg, _
            "int", $nIDDlgItem, _
            "str", $lpString)
    Return $aRet[0]
EndFunc   ;==>_WinAPI_SetDlgItemText

 

Simple example to see how to use it

#include "HookDlgBox.au3"

_DlgBox_SetButtonNames("1", "two", "3")
MsgBox(4, "Test 1", "Custom button texts")


_DlgBox_SetPosition(20, 20)
MsgBox(66, "Test 2", "Custom position and button texts")

_DlgBox_SetButtonNames("Submit", "Don't submit", "Don't know")
InputBox("Test 3", "Where were you born?", "Planet Earth")

_DlgBox_SetSize(800, 800)
InputBox("Test 4", "Where were you born?", "Planet Earth")

_DlgBox_SetSize(Default, 800)
MsgBox(66, "Test 5", "Strange but working")

_DlgBox_SetButtonNames(Default, "Wait", "What?")
_DlgBox_SetSize(Default, Default)
_DlgBox_SetPosition(500, 500)
MsgBox(66, "Test 6", "So far so good!")


_DlgBox_SetDefaults()

MsgBox(6, "Test 7", "Default position and button texts")

Hope you like it.

 

Best regards

funkey

HookDlgBox Example.au3

 

 

HookDlgBox.au3

Edited by funkey
Bugfix

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Posted

Thanks.

I was quite sure I repaired this. I first used DlgWnd but then I found out that Microsoft is talking about Dialog Boxes.

Here another example with other dialog boxes

 

#include <Misc.au3>
#include "HookDlgBox.au3"


; force german custum button texts for FileOpenDialog
_DlgBox_SetButtonNames("Datei öffnen", "Auswahl abbrechen")
FileOpenDialog("Test", @ScriptDir, "AutoIt scriptses (*.au3)")


_DlgBox_SetButtonNames(Default)
 _DlgBox_SetPosition(500, 100)
_ChooseColor()


_DlgBox_SetButtonNames("Lets go", "No no")
_ChooseFont()

 

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

  • 4 years later...
Posted

Do you know if this can be used to hook msgboxes from other applications? Or do you need to create a DLL in order to do this?

  • 6 months later...
Posted

Hello funkey!

Thank you for sharing this - it's very helpful!

However I believe I have found a bug, perhaps it is on my end only but when using it with a GUI, upon pressing the button and once the message box closes, the controls in the GUI get assigned the text of the buttons - I suspect it's confusing control IDs with the button IDs but I am not up to speed with this type of advanced coding.

To replicate, here is a simplified code I made - just click on "OK" and select any of the buttons in the box and you should see that the controls get assigned the buttons text (orderly) :

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

#include "HookDlgBox.au3"

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Dialog", 442, 327, 346, 262)
$GroupBox1 = GUICtrlCreateGroup("", 10, 1, 365, 238)
$Label1 = GUICtrlCreateLabel("Label1", 48, 32, 45, 20)
$Label2 = GUICtrlCreateLabel("Label2", 84, 96, 45, 20)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("&OK", 80, 250, 92, 31)
$Button2 = GUICtrlCreateButton("&Cancel", 199, 250, 93, 31)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE, $Button2
            Exit
        Case $Button1
            _DlgBox_SetButtonNames("AAAA", "BBBB", "CCCC")
            MsgBox(4, "Test 1", "Custom button texts")
            _DlgBox_SetDefaults()
    EndSwitch
WEnd

Since I prefer this approach partially of being lazy but more likely for keeping things visually consistent I have a temporary solution to others who might encounter such an issue, just add empty labels, one for each button. Create them before all of your other controls and set their size to zero (you can even hide them just in case).

If we use the script above as an example, this is where you would inject the code:

...

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Dialog", 442, 327, 346, 262)

; DUMMY BUTTONS TO CAPTURE THE BUTTONS TEXT - START
GUICtrlCreateLabel("", 0, 0, 0, 0)
GUICtrlCreateLabel("", 0, 0, 0, 0)
GUICtrlCreateLabel("", 0, 0, 0, 0)
; DUMMY BUTTONS TO CAPTURE THE BUTTONS TEXT - END

$GroupBox1 = GUICtrlCreateGroup("", 10, 1, 365, 238)
$Label1 = GUICtrlCreateLabel("Label1", 48, 32, 45, 20)

...

Thanks again!

Posted

Hi 0Ethan0,

thanks for reporting the error. I updated the UDF in post #1.

I'm happy you like it.

 

BR

funkey

 

 

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...