Jump to content

Recommended Posts

Posted

Or an alternative..

#include <guiConstants.au3>
#include <winapi.au3>
#include <misc.au3>

Opt("MustDeclareVars", 1)

Global Const $SC_MAXIMIZE = 0xF030
Global Const $tagMINMAXINFO = "struct;long[2];long MaxSize[2];long MaxPosition[2];long MinTrackSize[2];long MaxTrackSize[2];endstruct"

Global $hGui = GUICreate("", 300, 200, 100, 100, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX))
Global $idCtrl = GUICtrlCreateButton("Test", 4, 4, 80, 40, $WS_BORDER)
Global $hCtrl = GUICtrlGetHandle($idCtrl)
Global $idCtrl2 = GUICtrlCreateButton("Test", 4, 48, 80, 40, $WS_BORDER)
Global $hCtrl2 = GUICtrlGetHandle($idCtrl2)


Global $hCtrlProc = DllCallbackRegister("CtrlProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")
Global $pCtrlProc = DllCallbackGetPtr($hCtrlProc)
_WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, $idCtrl)
_WinAPI_SetWindowSubclass($hCtrl2, $pCtrlProc, $idCtrl2)

Global $hCursor = _WinAPI_CopyCursor(_WinAPI_LoadCursor(0, $OCR_HAND))
GUIRegisterMsg($WM_SIZE, "WM_SIZE")
GUISetState()

Local $iMsg
While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch
WEnd

Func CtrlProc($hWnd, $uMsg, $wParam, $lParam, $uIdSubclasss, $dwRefData)
    Local $iRet

    Switch $uMsg
        Case $WM_NCHITTEST
            ;resize on left and right edges, draggable by caption in middle of button.

            ;Mouse position.
            Local $aPoint[2] = [BitAND($lParam, 0xFFFF),  BitShift($lParam, 16)]

            ;Mouse coords can be negative on edge cases!
            ;These are 16bit values, so test for the sign and backfill with 1's if need be. (i.e. convert to 32bit signed int)
            If BitAND($aPoint[0], 0x8000) Then $aPoint[0] = BitOR(0xFFFF0000, $aPoint[0])
            If BitAND($aPoint[1], 0x8000) Then $aPoint[1] = BitOR(0xFFFF0000, $aPoint[1])

            ;By default we are in the caption. Normally this would be set the client area of the button. ($HTCLIENT)
            $iRet = $HTCAPTION

            ;If we are in 10px of the Left or Right edge, we want to resize the button
            Local $aPos = WinGetPos($hWnd), $iMar = 10
            If $aPoint[0] - $aPos[0] < $iMar Then $iRet = $HTLEFT
            If $aPoint[0] - $aPos[0] > ($aPos[2] - $iMar) Then $iRet = $HTRIGHT

            ;If we're outside the button, do normal things.
            If $aPoint[0] < 0 Then $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam)
            If $aPoint[1] < 0 Then $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam)

        Case $WM_MOVING
            ;Prevent button from moving on the Y axis.
            $iRet = 1
            Local $tNewRect = DllStructCreate($tagRect, $lParam)
            Local $tOldRect = _WinAPI_GetWindowRect($hWnd)
            $tNewRect.Top = $tOldRect.Top
            $tNewRect.Bottom = $tOldRect.Bottom

        Case $WM_SYSCOMMAND
            ;Because the WM_NCHITTEST handler puts us in the button's caption, the button will want to maximize when double clicking it.
            ;intercept SC_MAXIMIZE to block that behaviour.
            Switch BitAnd(0xFFF0, $wParam)
                Case $SC_MAXIMIZE
                    $iRet = 0
                Case Else
                    $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam)
            EndSwitch

        Case $WM_SETCURSOR
            ;Set to hand when we're in the middle of the button.
            Local $iSrc = BitAND($lParam, 0xFFFF), $iEvent = BitShift($lParam, 16)
            If $iSrc = $HTCAPTION Then
                _WinAPI_SetCursor($hCursor)
                $iRet = 1
            Else
                ;DefSubclassProc will take care of cursor automatically on the left and right edges.
                $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam)
            EndIf

        Case $WM_GETMINMAXINFO
            ;Set minimum button width.
            Local $tMINMAXINFO = DllStructCreate($tagMINMAXINFO, $lParam)
            $tMINMAXINFO.MinTrackSize(1) = 40
            $iRet = 0

        Case Else
            $iRet = _WinAPI_DefSubclassProc($hWnd, $uMsg, $wParam, $lParam)
    EndSwitch

    Return $iRet
EndFunc   ;==>btnProc

;Prevent autoit's docking behaviour kicking in by handling WM_SIZE.
;By default the control will want to return to its creation point when restoring the GUI.
Func WM_SIZE($hWnd, $uMsg, $wParam, $lParam)
    Return _WinAPI_DefWindowProcW($hWnd, $uMsg, $wParam, $lParam)
EndFunc   ;==>WM_SIZE

 

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...