Collapse Window by Clicking on the Title Bar

5644 단어 WindowsAutoHotkey
In the previous post , I showed a way to check whether the cursor is on the client area of a target window. The method can be applied similarly to detect if the cursor is on the title bar of a window. Once the position of the client top-left corner is retrieved, it is merely a subtraction to get the height of the title bar of the window.
The below script lets you un/fold a window with a middle click on the title bar.
WindowCollapse.ahk
#Noenv
SetWorkingDir %A_ScriptDir%

Hotkey, ~MButton, CollapseWindow    ; set the hotkey
oCollapsedWindows := []         ; a stack object for collapsed windows
Loop, %A_WinDir%\Media\*.wav    ; find the sound file to play when the window gets un/folded
    if InStr(A_LoopFileName, "Information Bar") {
        sSoundFile := A_LoopFileLongPath
        Break
    }
Return

CollapseWindow:
    ; This label is called when the user presses the middle button of the mouse
    ; If the clicked area is not the title bar, just return
    if !IsCursorOnWindowTopBorder(hWndActive := WinExist("A")) 
        Return

    SoundPlay, % sSoundFile
    WinGetPos,,,, nWndActiveH, ahk_id %hWndActive%      ; Retrieve the current height of the active window.
    WinGet, nStyle, Style, ahk_id %hWndActive%      
    if !oCollapsedWindows[hWndActive] {
        ; Collapse the window
        ; Resizable window -> 0 Non-resizablw window -> Top-border height
        WinMove, ahk_id %hWndActive%,,,,, % (nStyle & 0x40000) ? 0 : GetTopBorderHight(hWndActive)  
        oCollapsedWindows[hWndActive] := nWndActiveH        ; Store the current height
        SetTimer, WinExistCheck, 60000              ; Set a timer to check stored windows still exist
    } else 
        ; Unfold the window.
        WinMove, ahk_id %hWndActive%,,,,, % oCollapsedWindows.Remove(hWndActive)        ; The remove method returns the stored value
Return
WinExistCheck:
    oRemove := []       ; Create an object to store removing keys.
    DHW := A_DetectHiddenWindows
    DetectHiddenWIndows, On
    For hWnd in oCollapsedWindows                       
        if !WinExist("ahk_id " hWnd)                    ; Check if the window still exists
            oRemove.Insert(hWnd)
    Loop, % oRemove.MaxIndex()
        oCollapsedWindows.Remove(oRemove[A_Index])      ; Remove the item from the stack object
    DetectHiddenWindows, % DHW
    if !oCollapsedWindows.MaxIndex() 
        SetTimer,, Off                              ; If the stack object is empty, turn off the timer
Return
GetTopBorderHight(hWnd) {
    ;[Descriptions]
    ;   Retrieves the top-border height of a specified window.
    ;[Parameters]
    ;   hWnd:       the subject window handle.
    ;[Return Value]
    ;   the height of the top-border 

    ; AutoHotkey Basic users should uncomment this line.
    ;ptr := A_PtrSize ? "ptr" : "uint"    

    ; Retrieve the window position.
    WinGetPos,, nWndY,,, ahk_id %hWnd%

    ; Retrieve the client top-left position in screen coordinate.
    VarSetCapacity(pt, 16), NumPut(0, pt, 0), NumPut(0, pt, 4)
    DllCall("ClientToScreen", ptr, hwnd, ptr, &pt)
    nClientY := NumGet(pt, 4, "int")

    Return nClientY - nWndY

    ; by A_Samurai 2012/2/16 licence: Public Domain 
}
IsCursorOnWindowTopBorder(hWnd) {
    ;[Descriptions]
    ;   Checks whether the position of the current mouse cursor is within the top-border of a specified window. 
    ;[Parameters]
    ;   hWnd:       the window handle of the subject window.
    ;[Return Value]
    ;   If the window is not active, it returns an empty value.
    ;   Returns True if the mouse cursor is on the top-border of the specified window; otherwise, it returns False.

    ; AutoHotkey Basic users should uncomment this line.
    ;ptr := A_PtrSize ? "ptr" : "uint"  

    ; Check if the window is active.
    if !WinActive("ahk_id " hWnd)
        Return

    ; Retrieve the window position and the width.
    WinGetPos, nWndX, nWndY, nWndW,, ahk_id %hWnd%

    ; Retrieve the client top-left position in screen coordinate.
    VarSetCapacity(pt, 16), NumPut(0, pt, 0), NumPut(0, pt, 4)
    DllCall("ClientToScreen", ptr, hwnd, ptr, &pt)
    nClientX := NumGet(pt, 0, "int") ,  nClientY := NumGet(pt, 4, "int")        

    ; Calculate the top-border height.
    nBorderTopH := nClientY - nWndY

    ; Retrieve the mouse cursor position and convert it to be window relative.
    VarSetCapacity(pos, 8), DllCall("GetCursorPos", ptr, &pos)
    nCursorX := NumGet(pos, 0, "int") , nCursorY := NumGet(pos, 4, "int")
    nCursorX := nCursorX - nWndX, nCursorY := nCursorY - nWndY

    ; Return True if the cursor is on the top-border of the window. 
    if (nCursorX >= 0) && (nCursorY >= 0) && (nCursorX <= nWndW) && (nCursorY <= nBorderTopH)
        Return True
    Else
        Return False

    ; by A_Samurai 2012/2/16 licence: Public Domain     
}

좋은 웹페이지 즐겨찾기