LoginSignup
1
1

More than 5 years have passed since last update.

Collapse Window by Clicking on the Title Bar

Last updated at Posted at 2012-02-28

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     
}

Alt OnClientArea
Alt NotOnClientArea

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1