Jump to content

Recommended Posts

Posted (edited)

Hi everybody :)

This script displays a big MessageBox having a height higher than @DesktopHeight
While the MessageBox is displayed, you can "navigate" inside it like this :

* Mouse Left-click drag : to move the window up and down (displaying a new panel of lines)
* Mouse Right-click : to display the window at its initial position
* Up key
* Down key
* PageUp Key   (Fn + up key on some laptops)
* PageDown Key (Fn + down key on some laptops)
* Home Key     (Fn + left key on some laptops)
* End Key      (Fn + right key on some laptops)

The 6 keyboard keys allow to navigate inside the window. Click on a button (placed at top of the window) to make your choice.

All this could have been scripted more easily using a GUI, an Edit control containing the text to display, plus the buttons to choose from, but I just wanted to try it using a native MessageBox

#include <APISysConstants.au3>  ; $GCL_HCURSOR
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <MsgBoxConstants.au3>
#include <StaticConstants.au3>
#include <WinAPIRes.au3>        ; _WinAPI_LoadCursor()
#include <WinAPISysWin.au3>     ; _WinAPI_SetClassLongEx()
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration

Global $g_hGUI, $g_hDLL = DllOpen("user32.dll")
Global $g_aCaption, $g_sTitle

Example()

;===========================================
Func Example()

    $g_hGUI = GUICreate("Big MsgBox example", 400, 200)

    GUICtrlCreateLabel("Number of lines in MsgBox (2 - 1588)", 10, 20, 180, 20, $SS_SUNKEN)
    Local $idNbLines = GUICtrlCreateInput("200", 200, 20, 35, 20, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER)), $iNbLines
    GUICtrlSetLimit($idNbLines, 4)

    Local $idMsgBox = GUICtrlCreateButton("Big MsgBox", 10, 60, 100, 25, $BS_DEFPUSHBUTTON)
    Local $idExit = GUICtrlCreateButton("Exit", 10, 110, 100, 25)

    GUISetState()

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $idExit
                ExitLoop

            Case $idMsgBox
                Local $iRet = Prepare_MsgBox(GUICtrlRead($idNbLines))
                If $iRet Then MsgBox($MB_TOPMOST, "Big MsgBox return value", $iRet, 0, $g_hGUI)
                GUICtrlSetState($idNbLines, $GUI_FOCUS)
        EndSwitch
    WEnd

    DllClose($g_hDLL)
EndFunc   ;==>Example

;===========================================
Func Prepare_MsgBox(Const $iNbLines)

    If $iNbLines < 2 Or $iNbLines > 1588 Then
        MsgBox($MB_TOPMOST, "Error", "Enter a number of lines between 2 and 1588", 0, $g_hGUI)
        Return ; 0
    EndIf

    Local $sTxt = "Line 1 : first line" & @crlf
    For $i = 2 To $iNbLines - 1
        $sTxt &= "Line " & $i & @crlf
    Next
    $sTxt &= "Line " & $iNbLines & " : last line"

    Dim $g_aCaption[3] = ["Cancel", "Try Again", "Continue"]
    $g_sTitle = "MsgBox with 3 buttons"
    Local $iChoice = _MsgBox(BitOr($MB_CANCELTRYCONTINUE, $MB_TOPMOST), $g_sTitle, $sTxt, 0, $g_hGUI)

;~  Dim $g_aCaption[2] = ["Yes", "No"]
;~  $g_sTitle = "MsgBox with 2 buttons"
;~  Local $iChoice = _MsgBox(BitOr($MB_YESNO, $MB_TOPMOST), $g_sTitle, $sTxt, 0, $g_hGUI)

;~  Dim $g_aCaption[1] = ["OK"]
;~  $g_sTitle = "MsgBox with 1 button"
;~  Local $iChoice = _MsgBox(BitOr($MB_OK, $MB_TOPMOST), $g_sTitle, $sTxt, 0, $g_hGUI)

    Return $iChoice
EndFunc   ;==>Prepare_MsgBox

;===========================================
Func _MsgBox($iFlag, $g_sTitle, $sText, $iTimeOut = 0, $hWnd = 0)

    GUIRegisterMsg($WM_HELP , "WM_HELP")

    Local $hTimerProc = DllCallbackRegister('_MsgBoxTimerProc', 'none', 'hwnd;uint;uint_ptr;dword')
    Local $iTimerID = _WinAPI_SetTimer(0, 0, 10, DllCallbackGetPtr($hTimerProc))

    Local $iChoice = MsgBox($iFlag, $g_sTitle, $sText, $iTimeOut, $hWnd)

    _WinAPI_KillTimer(0, $iTimerID)
    DllCallbackFree($hTimerProc)

    GUIRegisterMsg($WM_HELP, "")

    Return $iChoice
EndFunc   ;==>_MsgBox

;===========================================
Func _MsgBoxTimerProc($hWnd, $iMsg, $iTimerID, $iTime)

    If WinExists($g_sTitle) Then
        _WinAPI_KillTimer(0, $iTimerID)
        Local $hMsgBox = WinGetHandle($g_sTitle)
        Local $aPosMsgBox = WinGetPos($hMsgBox)
        Local $bTooHigh = ($aPosMsgBox[3] > @DesktopHeight + 15) ? True : False
        If $bTooHigh Then
            Local $aPosButton, $aPosStatic = ControlGetPos($hMsgBox, "", "Static1") ; the text area
            For $i = 0 To Ubound($g_aCaption) - 1
                ControlSetText($hMsgBox, "", "Button" & ($i + 1), $g_aCaption[$i])
                $aPosButton = ControlGetPos($hMsgBox, "", "Button" & ($i + 1))
                WinMove(ControlGetHandle($hMsgBox, "", "Button" & ($i + 1)), "", $aPosButton[0], $aPosStatic[1])
            Next
            WinMove(ControlGetHandle($hMsgBox, "", "Static1"), "", $aPosStatic[0], $aPosStatic[1] + $aPosButton[3] + 10)
            _WinAPI_RedrawWindow($hMsgBox) ; +++
            Send("{F1}") ; => Func WM_HELP
        Else
            For $i = 0 To Ubound($g_aCaption) - 1
                ControlSetText($hMsgBox, "", "Button" & ($i + 1), $g_aCaption[$i])
            Next
        EndIf
    EndIf
EndFunc   ;==>_MsgBoxTimerProc

;==============================================
Func WM_HELP($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam

    If WinExists($g_sTitle) Then ; MessageBox window always exists at this stage
        Local $hMsgBox = WinGetHandle($g_sTitle)
        Local $aPosMsgBox = WinGetPos($hMsgBox), $aPosMsgBox_Init = $aPosMsgBox
        Local $aWinPos, $aMPos, $aMPosOld

        Local $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZEALL) ; $OCR_SIZENS ok too
        Local $iPrev = _WinAPI_SetClassLongEx($hMsgBox, $GCL_HCURSOR, $hCursor) ; see "147c.au3"

        HotKeySet("{SPACE}", "_Space")

        While 1
            If WinActive($hMsgBox) Then
                Select
                    Case _IsPressed("01", $g_hDLL) ; "01" = Left mouse button
                        $aMPosOld = MouseGetPos()
                        While _IsPressed("01", $g_hDLL)
                            $aMPos = MouseGetPos()
                            If $aMPos[1] <> $aMPosOld[1] Then
                                $aWinpos = WinGetPos($hMsgBox)
                                If ($aMPos[0] - 1 > $aWinpos[0]) And ($aMPos[0] + 1 < $aWinpos[0] + $aWinpos[2]) Then
                                    WinMove($hMsgBox, "", Default, $aWinpos[1] + ($aMPos[1] - $aMPosOld[1]))
                                    $aMPosOld = $aMPos
                                EndIf
                            EndIf
                            Sleep(10)
                        Wend

                    Case _IsPressed("02", $g_hDLL) ; Right mouse button
                        WinMove($hMsgBox, "", $aPosMsgBox_Init[0], $aPosMsgBox_Init[1])

                    Case _IsPressed("21", $g_hDLL) ; PageUp Key
                        While _IsPressed("21", $g_hDLL)
                            Sleep(10)
                        Wend
                        $aPosMsgBox = WinGetPos($hMsgBox)
                        WinMove( $hMsgBox, "", Default, ($aPosMsgBox[1] + @DesktopHeight > 0) ? 0 : $aPosMsgBox[1] + @DesktopHeight )

                    Case _IsPressed("22", $g_hDLL) ; PageDown Key
                        While _IsPressed("22", $g_hDLL)
                            Sleep(10)
                        Wend
                        $aPosMsgBox = WinGetPos($hMsgBox)
                        WinMove( $hMsgBox, "", Default, _
                            ($aPosMsgBox[3] + $aPosMsgBox[1] - @DesktopHeight < @DesktopHeight + 15) ? @DesktopHeight - $aPosMsgBox[3] : $aPosMsgBox[1] - @DesktopHeight )

                    Case _IsPressed("23", $g_hDLL) ; End Key
                        $aPosMsgBox = WinGetPos($hMsgBox)
                        WinMove($hMsgBox, "", Default, @DesktopHeight - $aPosMsgBox[3])

                    Case _IsPressed("24", $g_hDLL) ; Home Key
                        WinMove($hMsgBox, "", Default, 0)

                    Case _IsPressed("26", $g_hDLL) ; Up Key
                        $aPosMsgBox = WinGetPos($hMsgBox)
                        WinMove($hMsgBox, "", Default, ($aPosMsgBox[1] + 12 > 0) ? 0 : $aPosMsgBox[1] + 12)

                    Case _IsPressed("28", $g_hDLL) ; Down Key
                        $aPosMsgBox = WinGetPos($hMsgBox)
                        WinMove( $hMsgBox, "", Default, _
                            ($aPosMsgBox[3] + $aPosMsgBox[1] - 12 < @DesktopHeight) ? @DesktopHeight - $aPosMsgBox[3] : $aPosMsgBox[1] - 12 )
                EndSelect
            EndIf

            If Not BitAND(WinGetState($hMsgBox), $WIN_STATE_VISIBLE) Then ; one of MsgBox buttons was clicked
                ExitLoop
            EndIf

            Sleep(10)
        WEnd

        HotKeySet("{SPACE}")

        _WinAPI_SetClassLongEx($hMsgBox, $GCL_HCURSOR, $iPrev) ; needed, or cursor $OCR_SIZEALL will show... in final MsgBox from main loop
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HELP

;==============================================
Func _Space()

    HotKeySet("{SPACE}") ; deactivate Hotkey

    If WinActive($g_sTitle) Then
        HotKeySet("{SPACE}", "_DoNothing") ; this part to avoid a MsgBox button being triggered, when Spacebar key is pressed too long.
        While _IsPressed("20", $g_hDLL) ; Spacebar key
            Sleep(10)
        Wend
    Else
        Send("{SPACE}")
    EndIf

    HotKeySet("{SPACE}", "_Space") ; reactivate Hotkey
EndFunc   ;==>_Space

;==============================================
Func _DoNothing()

EndFunc   ;==>_DoNothing

BigMsgBox.png.efda2805087f4739eaa38b3ed5fc6325.png

Edited by pixelsearch
typo

"I think you are searching a bug where there is no bug..."

Posted

Thank you. Works great.

Only thing is visual issue at last line for me. But no problem.

image.png.db743817ef613a1f29f5a7aee1ba1731.png

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...