Jump to content

Gradually hide GUI on the left of the screen


Lupo73
 Share

Recommended Posts

This is a code I wrote to gradually show/hide a GUI on the left of the screen:

#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WinAPIsysinfoConstants.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGUI = GUICreate("Example", 400, 400)
    Local $hButtonMove = GUICtrlCreateButton("OFF", 300, 360, 90, 26)
    Local $iToMove = 0
    ;WinSetOnTop($hGUI, "", 1)

    GUISetState(@SW_SHOW, $hGUI)

    While 1
        If $iToMove = 1 Then
            __GUIGraduallyHide($hGUI)
        EndIf

        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $hButtonMove
                If $iToMove = 1 Then
                    $iToMove = 0
                    __GUIInBounds($hGUI)
                    GUICtrlSetData($hButtonMove, "OFF")
                Else
                    $iToMove = 1
                    GUICtrlSetData($hButtonMove, "ON")
                EndIf

        EndSwitch
    WEnd

    GUIDelete($hGUI)
EndFunc   ;==>Example

Func __GUIGraduallyHide($hHandle, $iVisiblePixels = 50, $iVisibleMarginLeft = 10)
    #cs
        Description: Gradually Hide GUI On The Left Of The Screen.
        Returns: 1
    #ce
    Local $aWinPos, $aMousePos, $hControl, $hWin, $hOldWin, $iStep
    $aWinPos = WinGetPos($hHandle)
    $aMousePos = MouseGetPos()
    $hControl = __WindowFromPoint($aMousePos[0], $aMousePos[1])
    $hWin = _WinAPI_GetAncestor($hControl, 2)
    If $hWin <> $hOldWin Or ($aMousePos[0] < 1 And $aMousePos[1] > $aWinPos[1] And $aMousePos[1] < $aWinPos[1] + $aWinPos[3]) Then
        $iStep = Ceiling($aWinPos[2] / 100)
        If $aWinPos[0] < $iVisibleMarginLeft And ($hWin = $hHandle Or ($aMousePos[0] < 1 And $aMousePos[1] > $aWinPos[1] And $aMousePos[1] < $aWinPos[1] + $aWinPos[3])) Then
            If WinActive($hHandle) = 0 Then
                WinActivate($hHandle)
            EndIf
            WinMove($hHandle, "", $aWinPos[0] + $iStep, $aWinPos[1], $aWinPos[2], $aWinPos[3])
        ElseIf $aWinPos[0] > - ($aWinPos[2] - $iVisiblePixels) And $hWin <> $hHandle And ($aMousePos[0] > $aWinPos[3] Or $aMousePos[1] < $aWinPos[1] Or $aMousePos[1] > $aWinPos[1] + $aWinPos[3]) Then
            If $aWinPos[0] > 0 Then
                $aWinPos[0] = 0
            EndIf
            WinMove($hHandle, "", $aWinPos[0] - $iStep, $aWinPos[1], $aWinPos[2], $aWinPos[3])
        EndIf
        $hOldWin = $hWin
    EndIf
    Sleep(2)
    Return 1
EndFunc   ;==>__GUIGraduallyHide

Func __WindowFromPoint($iX, $iY) ; Used In __GUIGraduallyHide()
    Local $stInt64, $aRet, $stPoint = DllStructCreate("long;long")
    DllStructSetData($stPoint, 1, $iX)
    DllStructSetData($stPoint, 2, $iY)
    $stInt64 = DllStructCreate("int64", DllStructGetPtr($stPoint))
    $aRet = DllCall("user32.dll", "hwnd", "WindowFromPoint", "int64", DllStructGetData($stInt64, 1))
    If @error Then Return SetError(2, @error, 0)
    If $aRet[0] = 0 Then Return SetError(3, 0, 0)
    Return $aRet[0]
EndFunc   ;==>__WindowFromPoint

Func __GUIInBounds($hHandle) ; Original Idea By wraithdu, Modified By guinness.
    #cs
        Description: Check If The GUI Is Within View Of The Users Screen.
        Returns: Move GUI If Out Of Bounds
    #ce
    Local $iXPos = 5, $iYPos = 5, $tWorkArea = DllStructCreate($tagRECT)
    _WinAPI_SystemParametersInfo($SPI_GETWORKAREA, 0, DllStructGetPtr($tWorkArea))

    Local $iLeft = DllStructGetData($tWorkArea, "Left"), $iTop = DllStructGetData($tWorkArea, "Top")
    Local $iWidth = DllStructGetData($tWorkArea, "Right") - $iLeft
    If _WinAPI_GetSystemMetrics($SM_CYVIRTUALSCREEN) > $iWidth Then
        $iWidth = _WinAPI_GetSystemMetrics($SM_CYVIRTUALSCREEN)
    EndIf
    $iWidth -= $iLeft
    Local $iHeight = DllStructGetData($tWorkArea, "Bottom") - $iTop
    Local $aWinGetPos = WinGetPos($hHandle)
    If @error Then
        Return SetError(1, 0, WinMove($hHandle, "", $iXPos, $iYPos))
    EndIf

    If $aWinGetPos[0] < $iLeft Then
        $iXPos = $iLeft
    ElseIf ($aWinGetPos[0] + $aWinGetPos[2]) > $iWidth Then
        $iXPos = $iWidth - $aWinGetPos[2]
    Else
        $iXPos = $aWinGetPos[0]
    EndIf
    If $aWinGetPos[1] < $iTop Then
        $iYPos = $iTop
    ElseIf ($aWinGetPos[1] + $aWinGetPos[3]) > $iHeight Then
        $iYPos = $iHeight - $aWinGetPos[3]
    Else
        $iYPos = $aWinGetPos[1]
    EndIf
    WinMove($hHandle, "", $iXPos, $iYPos)
    Return 1
EndFunc   ;==>__GUIInBounds

Click ON/OFF button to enable/disable the feature. When enabled, the GUI gradually moves away on the left when mouse is not hover it and appears again on mouse hover.

Edited by Lupo73

SFTPEx, AutoCompleteInput_DateTimeStandard(), _ImageWriteResize()_GUIGraduallyHide(): some AutoIt functions.

Lupo PenSuite: all-in-one and completely free selection of portable programs and games.

DropIt: a personal assistant to automatically manage your files.

ArcThemALL!: application to multi-archive your files and folders.

Link to comment
Share on other sites

  • 2 months later...

I wrote an improved version of the code, that now correctly works on all screen sides (auto-detecting the nearest side and the taskbar position):

#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WinAPIsysinfoConstants.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGUI = GUICreate("Example", 300, 300)
    Local $hButtonIn = GUICtrlCreateButton("IN BOUNDS", 50, 60, 200, 26)
    Local $hButtonTop = GUICtrlCreateButton("TOP (ON/OFF)", 50, 160, 200, 26)
    Local $hButtonMove = GUICtrlCreateButton("HIDE (ON/OFF)", 50, 260, 200, 26)
    Local $iOnTop, $iToMove

    GUISetState(@SW_SHOW, $hGUI)

    While 1
        If $iToMove = 1 Then
            __GUIGraduallyHide($hGUI, $iOnTop)
        EndIf

        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $hButtonMove
                If $iToMove = 1 Then
                    $iToMove = 0
                    __GUIInBounds($hGUI)
                Else
                    $iToMove = 1
                EndIf

            Case $hButtonIn
                __GUIInBounds($hGUI)

            Case $hButtonTop
                If $iOnTop = 1 Then
                    $iOnTop = 0
                Else
                    $iOnTop = 1
                EndIf
                WinSetOnTop($hGUI, "", $iOnTop)

        EndSwitch
    WEnd

    GUIDelete($hGUI)
EndFunc   ;==>Example



Func __GUIGraduallyHide($hHandle, $iOnTop = 0, $iSpeed = 5, $iVisiblePixels = 50, $iMarginFromSide = 10, $iRevealOnly = 0, $iSide = -1)
    #cs
        Description: Gradually Hide GUI On The Nearest Side Of The Screen.
        Returns: 1
    #ce
    Local $aDesktopArea, $hMonitor, $aMousePos, $aWinPos, $iLength, $iMouseHover, $iInternalDist
    $aMousePos = MouseGetPos()
    $aWinPos = __WinGetPosEx($hHandle)
    If @error Then Return SetError(2, 0, 0)
    $hMonitor = __MonitorFromWindow($hHandle)
    If @error Then Return SetError(3, 0, 0)
    $aDesktopArea = __MonitorGetInfo($hMonitor)
    If @error Then Return SetError(4, 0, 0)
    If $iOnTop Then ; To Ignore Taskbar If Win On Top.
        $aDesktopArea[4] = $aDesktopArea[0]
        $aDesktopArea[5] = $aDesktopArea[1]
        $aDesktopArea[6] = $aDesktopArea[2]
        $aDesktopArea[7] = $aDesktopArea[3]
    EndIf
    If $iSide = -1 Then $iSide = __GetNearSide($aDesktopArea[2] - $aDesktopArea[0], $aDesktopArea[3] - $aDesktopArea[1], $aWinPos[4] - $aDesktopArea[0], $aWinPos[5] - $aDesktopArea[1])

    Switch $iSide
        Case 1 ; Hide On Top Side.
            If $hMonitor <> __MonitorFromPoint($aWinPos[4], $aDesktopArea[1] - 10) Then Return SetError(5, 0, 0) ; Do Not Hide On Sides Between Two Monitors.
            Local $aRefPos[4] = [$aWinPos[0] - 5, $aWinPos[6] + 5, $aDesktopArea[5], $aWinPos[7] + 10]
            $iInternalDist = $aWinPos[1] - $aDesktopArea[5]
            $iLength = $aWinPos[3]
        Case 2 ; Hide On Right Side.
            If $hMonitor <> __MonitorFromPoint($aDesktopArea[2] + 10, $aWinPos[5]) Then Return SetError(5, 0, 0) ; Do Not Hide On Sides Between Two Monitors.
            Local $aRefPos[4] = [$aWinPos[0] - 10, $aDesktopArea[6], $aWinPos[1] - 5, $aWinPos[7] + 5]
            $iInternalDist = $aDesktopArea[6] - $aWinPos[6]
            $iLength = $aWinPos[2]
        Case 3 ; Hide On Bottom Side.
            If $hMonitor <> __MonitorFromPoint($aWinPos[4], $aDesktopArea[3] + 10) Then Return SetError(5, 0, 0) ; Do Not Hide On Sides Between Two Monitors.
            Local $aRefPos[4] = [$aWinPos[0] - 5, $aWinPos[6] + 5, $aWinPos[1] - 10, $aDesktopArea[7]]
            $iInternalDist = $aDesktopArea[7] - $aWinPos[7]
            $iLength = $aWinPos[3]
        Case Else ; Hide On Left Side.
            If $hMonitor <> __MonitorFromPoint($aDesktopArea[0] - 10, $aWinPos[5]) Then Return SetError(5, 0, 0) ; Do Not Hide On Sides Between Two Monitors.
            Local $aRefPos[4] = [$aDesktopArea[4], $aWinPos[6] + 10, $aWinPos[1] - 5, $aWinPos[7] + 5]
            $iInternalDist = $aWinPos[0] - $aDesktopArea[4]
            $iLength = $aWinPos[2]
    EndSwitch
    If $aMousePos[0] >= $aRefPos[0] And $aMousePos[0] <= $aRefPos[1] And $aMousePos[1] >= $aRefPos[2] And $aMousePos[1] <= $aRefPos[3] Then $iMouseHover = 1 ; Show.

    If $iInternalDist < $iMarginFromSide And $iMouseHover = 1 Then ; Gradually Show Window.
        If WinActive($hHandle) = 0 Then WinActivate($hHandle)
        $iInternalDist += $iSpeed
        If $iInternalDist > $iMarginFromSide Then $iInternalDist = $iMarginFromSide
    ElseIf $iInternalDist > ($iVisiblePixels - $iLength) And $iMouseHover = 0 And $iRevealOnly = 0 Then ; Gradually Hide Window.
        If $iInternalDist > 0 Then $iInternalDist = 0
        $iInternalDist -= $iSpeed
        If $iInternalDist < ($iVisiblePixels - $iLength) Then $iInternalDist = $iVisiblePixels - $iLength
    Else
        Return SetError(1, 0, 0) ; Completely Hidden/Revealed.
    EndIf

    Switch $iSide
        Case 1 ; Hide On Top Side.
            $aWinPos[1] = $aDesktopArea[5] + $iInternalDist
        Case 2 ; Hide On Right Side.
            $aWinPos[0] = $aDesktopArea[6] - $iLength - $iInternalDist
        Case 3 ; Hide On Bottom Side.
            $aWinPos[1] = $aDesktopArea[7] - $iLength - $iInternalDist
        Case Else ; Hide On Left Side.
            $aWinPos[0] = $aDesktopArea[4] + $iInternalDist
    EndSwitch

    WinMove($hHandle, "", $aWinPos[0], $aWinPos[1])
    Sleep(20)
    Return 1
EndFunc   ;==>__GUIGraduallyHide

Func __WinGetPosEx($hHandle)
    #cs
        Description: Get Position And Size Of A Window.
        Returns: Array[8]
        [0] - Left-Side Position From Left
        [1] - Top-Side Position From Top
        [2] - Width
        [3] - Height
        [4] - Center Position From Left
        [5] - Center Position From Top
        [6] - Right-Side Position From Left
        [7] - Bottom-Side Position From Top
    #ce
    Local $aWinPos = WinGetPos($hHandle)
    If @error Then Return SetError(@error, 0, 0)
    Local $aReturn[8] = [$aWinPos[0], $aWinPos[1], $aWinPos[2], $aWinPos[3], $aWinPos[0] + Ceiling($aWinPos[2] / 2), $aWinPos[1] + Ceiling($aWinPos[3] / 2), $aWinPos[0] + $aWinPos[2], $aWinPos[1] + $aWinPos[3]]
    Return $aReturn
EndFunc   ;==>__WinGetPosEx

Func __GetNearSide($iScreenW, $iScreenH, $iWinCX, $iWinCY)
    #cs
        Description: Get The Nearest Side Of Current Monitor To The Window Center.
        Returns: 0 = Left, 1 = Top, 2 = Right, 3 = Bottom.
    #ce
    Local $iReturn
    Local $aRatio[3] = [$iScreenW / $iScreenH, $iWinCX / $iWinCY, ($iScreenW - $iWinCX) / $iWinCY]
    Select
        Case $iWinCX <= 0 Or ($aRatio[1] < $aRatio[0] And $aRatio[2] >= $aRatio[0]) ; Near Left.
            $iReturn = 0
        Case $iWinCY <= 0 Or ($aRatio[1] >= $aRatio[0] And $aRatio[2] >= $aRatio[0]) ; Near Top.
            $iReturn = 1
        Case $iWinCX >= $iScreenW Or ($aRatio[1] >= $aRatio[0] And $aRatio[2] < $aRatio[0]) ; Near Right.
            $iReturn = 2
        Case Else ; Near Bottom.
            $iReturn = 3
    EndSelect
    Return $iReturn
EndFunc   ;==>__GetNearSide

Func __GUIInBounds($hHandle) ; Original Idea By wraithdu, Modified By guinness And Lupo73.
    #cs
        Description: Check If The GUI Is Within View Of The Users Screen.
        Returns: Move GUI If Out Of Bounds
    #ce
    Local $iXPos = 5, $iYPos = 5, $aWinPos = __WinGetPosEx($hHandle)
    If @error Then Return SetError(1, 0, WinMove($hHandle, "", $iXPos, $iYPos))
    Local $aDesktopArea = __MonitorGetInfo(__MonitorFromWindow($hHandle))
    If @error Then Return SetError(2, 0, WinMove($hHandle, "", $iXPos, $iYPos))
    $iXPos = $aWinPos[0]
    $iYPos = $aWinPos[1]
    If $aWinPos[0] < $aDesktopArea[4] Then
        $iXPos = $aDesktopArea[4]
    ElseIf $aWinPos[6] > $aDesktopArea[6] Then
        $iXPos = $aDesktopArea[6] - $aWinPos[2]
    EndIf
    If $aWinPos[1] < $aDesktopArea[5] Then
        $iYPos = $aDesktopArea[5]
    ElseIf $aWinPos[7] > $aDesktopArea[7] Then
        $iYPos = $aDesktopArea[7] - $aWinPos[3]
    EndIf
    WinMove($hHandle, "", $iXPos, $iYPos)
    Return 1
EndFunc   ;==>__GUIInBounds

Func __MonitorGetInfo($hMonitor) ; Modified From: http://www.autoitscript.com/forum/topic/134534-desktopdimensions-details-about-the-primary-and-secondary-monitors/
    #cs
        Description: Get Info About A Monitor (Given A Monitor Handle).
        ; Returns: $Array[10]
        [0] = Monitor upper-left corner X coordinate (this rect is same as full-screen size)
        [1] = Monitor upper-left corner Y coordinate
        [2] = Monitor lower-right corner X coordinate
        [3] = Monitor lower-right corner Y coordinate
        [4] = Monitor Work Area upper-left corner X coordinate (this rect is same as maximized size)
        [5] = Monitor Work Area upper-left corner Y coordinate
        [6] = Monitor Work Area lower-right corner X coordinate
        [7] = Monitor Work Area lower-right corner Y coordinate
        [8] = Primary monitor boolean (0 = not, 1 = is)
        [9] = Monitor Or Display Device Name (usually '.DISPLAY#' where # starts at 1)
    #ce
    If IsPtr($hMonitor) = 0 Or $hMonitor = 0 Then Return SetError(1,0,'')
    Local $aRet, $stMonInfoEx = DllStructCreate('dword;long[8];dword;wchar[32]')
    DllStructSetData($stMonInfoEx, 1, DllStructGetSize($stMonInfoEx))
    $aRet = DllCall('user32.dll', 'bool', 'GetMonitorInfoW', 'handle', $hMonitor, 'ptr', DllStructGetPtr($stMonInfoEx))
    If @error Then Return SetError(2, 0, '')
    If $aRet[0] = 0 Then Return SetError(3, 0, '')
    Dim $aRet[10]
    For $A = 0 To 7 ; Both RECT's
        $aRet[$A] = DllStructGetData($stMonInfoEx, 2, $A + 1)
    Next
    $aRet[8] = DllStructGetData($stMonInfoEx, 3) ; 0 or 1 for Primary Monitor [MONITORINFOF_PRIMARY = 1]
    $aRet[9] = DllStructGetData($stMonInfoEx, 4) ; Device String of type '.DISPLAY1' etc
    Return $aRet
EndFunc   ;==>__MonitorGetInfo

Func __MonitorFromPoint($iX, $iY)
    Local $aRet, $stPoint = DllStructCreate($tagPOINT)
    DllStructSetData($stPoint, "x", $iX)
    DllStructSetData($stPoint, "y", $iY)
    $aRet = DllCall("user32.dll", "handle", "MonitorFromPoint", "struct", $stPoint, 'dword', 2)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>__MonitorFromPoint

Func __MonitorFromWindow($hWin)
    Local $aRet = DllCall("user32.dll", "hwnd", "MonitorFromWindow", "hwnd", $hWin, "int", 2)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>__MonitorFromWindow

Func __WindowFromPoint($iX, $iY)
    Local $stInt64, $aRet, $stPoint = DllStructCreate("long;long")
    DllStructSetData($stPoint, 1, $iX)
    DllStructSetData($stPoint, 2, $iY)
    $stInt64 = DllStructCreate("int64", DllStructGetPtr($stPoint))
    $aRet = DllCall("user32.dll", "hwnd", "WindowFromPoint", "int64", DllStructGetData($stInt64, 1))
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRet[0]
EndFunc   ;==>__WindowFromPoint

:thumbsup:

Edited by Lupo73

SFTPEx, AutoCompleteInput_DateTimeStandard(), _ImageWriteResize()_GUIGraduallyHide(): some AutoIt functions.

Lupo PenSuite: all-in-one and completely free selection of portable programs and games.

DropIt: a personal assistant to automatically manage your files.

ArcThemALL!: application to multi-archive your files and folders.

Link to comment
Share on other sites

Hey,

Thanks for sharing but missing file WinAPIsysinfoConstants.au3 :(

Update to the latest version of AutoIt.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

I updated the code in the second post... after several tests and improvements:

- it correctly manages taskbar on any side

- it works with both window on top or not

- it may works much better also with multiple monitors

Edited by Lupo73

SFTPEx, AutoCompleteInput_DateTimeStandard(), _ImageWriteResize()_GUIGraduallyHide(): some AutoIt functions.

Lupo PenSuite: all-in-one and completely free selection of portable programs and games.

DropIt: a personal assistant to automatically manage your files.

ArcThemALL!: application to multi-archive your files and folders.

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

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