Jump to content

How to resize a shape WHILE resizing a GUI


Recommended Posts

I am working on a script that draws a shape around a control. Right now it works but it does not update at the same time as the other controls in the GUI.  Does anyone know of a way that I can modify it to resize at the same time?

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>

Opt("GuiOnEventMode", 1)
Opt("MustDeclareVars", 1)

Global $g_hGUI, $g_idDummy

$g_hGUI = GUICreate("", 500, 500, -1, -1, $WS_SIZEBOX + $WS_MAXIMIZEBOX, $WS_EX_COMPOSITED)

$g_idDummy = GUICtrlCreateButton("", 250, 250, 50, 50)
GUICtrlSetResizing($g_idDummy, $GUI_DOCKAUTO)

GUISetState()

GUISetOnEvent($GUI_EVENT_CLOSE, "WinEvents", $g_hGUI)

; redraws on resize but only after mouse is released
GUISetOnEvent($GUI_EVENT_RESIZED, "ReDraw", $g_hGUI)

DrawSelector("Selector", $g_idDummy)

While 1
    Sleep(250)
WEnd

Func ReDraw()
    DrawSelector("Selector", $g_idDummy)
EndFunc   ;==>ReDraw

Func DrawSelector($sSelectorTitle, $idControl)
    Local $hBitmap, $hGui, $hGraphic, $GuiSizeX = @DesktopWidth, $GuiSizeY = @DesktopHeight
    Local $GuiSize = 70, $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $hPen
    Local $iOpacity = 255, $aPos

    If WinExists($sSelectorTitle, "") Then GUIDelete(WinGetHandle($sSelectorTitle))

    $aPos = ControlRelativeToDesktop($g_hGUI, $idControl)

    $hGui = GUICreate($sSelectorTitle, $GuiSizeX, $GuiSizeY, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
    GUISetState()

    _GDIPlus_Startup()
    $hWnd = _WinAPI_GetDC($g_hGUI)
    $hDC = _WinAPI_CreateCompatibleDC($hWnd)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY)
    _WinAPI_SelectObject($hDC, $hBitmap)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)

    $hPen = _GDIPlus_PenCreate(0xFFFF0000, 5)

    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", $GuiSizeX)
    DllStructSetData($tSize, "Y", $GuiSizeY)
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)

    _GDIPlus_GraphicsDrawRect($hGraphic, $aPos[0], $aPos[1], $aPos[2], $aPos[3], $hPen) ; <-- Graphics to layered wimdow.
    _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)

    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_ReleaseDC(0, $hWnd)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hDC)
    _GDIPlus_Shutdown()
EndFunc   ;==>DrawSelector

Func ControlRelativeToDesktop($hWnd, $idControl)
    Local $Point, $aControlXYPos

    Dim $aPos[4]

    $aControlXYPos = ControlGetPos($hWnd, "", $idControl)

    $Point = DllStructCreate("int;int")
    DllStructSetData($Point, 1, $aControlXYPos[0])
    DllStructSetData($Point, 2, $aControlXYPos[1])
    DllCall("User32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($Point))

    ;x
    $aPos[0] = DllStructGetData($Point, 1)

    ;y
    $aPos[1] = DllStructGetData($Point, 2)

    ;width
    $aPos[2] = $aControlXYPos[2]

    ;height
    $aPos[3] = $aControlXYPos[3]

    Return $aPos
EndFunc   ;==>ControlRelativeToDesktop

Func WinEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            Exit
    EndSelect
EndFunc   ;==>WinEvents

 

Link to comment
Share on other sites

I got it working after messing with it for a few days. It still has an annoying flash but it works. Here is the code for anyone that might be interested.

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

Opt("GuiOnEventMode", 1)
Opt("MustDeclareVars", 1)

Global $g_hGUI, $g_idDummy, $g_hChildGui

$g_hGUI = GUICreate("", 500, 500, -1, -1, $WS_SIZEBOX + $WS_MAXIMIZEBOX, $WS_EX_COMPOSITED)

$g_idDummy = GUICtrlCreateButton("", 250, 250, 50, 50)
GUICtrlSetResizing($g_idDummy, $GUI_DOCKAUTO)

GUISetState()

GUISetOnEvent($GUI_EVENT_CLOSE, "WinEvents", $g_hGUI)

GUISetOnEvent($GUI_EVENT_RESIZED, "UpdateSelector", $g_hGUI)
GUIRegisterMsg($WM_SIZE, "UpdateSelector")
DrawSelector("Selector", $g_idDummy)

While 1
    Sleep(250)
WEnd

Func DrawSelector($sSelectorTitle, $idControl)
    Local $hBitmap, $hGraphic, $aMainGUIPos, $GuiSize = 70, $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $hPen
    Local $iOpacity = 255, $aControlPos

    If WinExists($sSelectorTitle, "") Then
        GUIDelete(WinGetHandle($sSelectorTitle, ""))
    EndIf

    $aControlPos = ControlGetPos($g_hGUI, "", $idControl)

    $aMainGUIPos = WinGetClientSize($g_hGUI)

    $g_hChildGui = GUICreate($sSelectorTitle, $aControlPos[0], $aControlPos[1], 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))

    DllCall("user32.dll", "int", "SetParent", "hwnd", $g_hChildGui, "hwnd", $g_hGUI)

    _GDIPlus_Startup()
    $hWnd = _WinAPI_GetDC($g_hGUI)
    $hDC = _WinAPI_CreateCompatibleDC($hWnd)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $aMainGUIPos[0], $aMainGUIPos[1])
    _WinAPI_SelectObject($hDC, $hBitmap)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)

    $hPen = _GDIPlus_PenCreate(0xFFFF0000, 5)

    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", $aMainGUIPos[0])
    DllStructSetData($tSize, "Y", $aMainGUIPos[1])
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)

    _GDIPlus_GraphicsDrawRect($hGraphic, $aControlPos[0], $aControlPos[1], $aControlPos[2], $aControlPos[3], $hPen)
    _WinAPI_UpdateLayeredWindow($g_hChildGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)

    GUISetState(@SW_SHOW, $g_hChildGui)

    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_ReleaseDC(0, $hWnd)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hDC)
    _GDIPlus_Shutdown()
EndFunc   ;==>DrawSelector

Func UpdateSelector($hWnd, $iMsg, $wparam, $lparam)
    WinMove($g_hChildGui,"",-1000,-1000)

    DrawSelector("Selector", $g_idDummy)
EndFunc

Func WinEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            Exit
    EndSelect
EndFunc   ;==>WinEvents

 

Link to comment
Share on other sites

this is not the approach you are looking for but I have no idea what you want it for so hidden bellow, mostly out of shame

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
Local $Form1 = GUICreate("Form1", 200, 100, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP))
Local $Button1 = GUICtrlCreateButton_wBox(4, "Button1", 20, 20, 50, 50)
Local $Button2 = GUICtrlCreateButton_wBox(4, "Button2", 40, 60, 100, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

Func GUICtrlCreateButton_wBox($sBoxSize, $sText, $iLeft, $iTop, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1)
    Local $iCtrl = GUICtrlCreateButton($sText, $iLeft, $iTop, $iWidth, $iHeight, $iStyle, $iExStyle)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)
    GUICtrlCreateLabel("", $iLeft - $sBoxSize, $iTop - $sBoxSize, $sBoxSize, $iHeight + $sBoxSize + $sBoxSize, $iStyle, $iExStyle)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)
    GUICtrlCreateLabel("", $iLeft - $sBoxSize, $iTop - $sBoxSize, $sBoxSize + $sBoxSize + $iWidth, $sBoxSize, $iStyle, $iExStyle)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)
    GUICtrlCreateLabel("", $iLeft - $sBoxSize, $iTop + $iHeight, $sBoxSize + $sBoxSize + $iWidth, $sBoxSize, $iStyle, $iExStyle)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)
    GUICtrlCreateLabel("", $iLeft + $iWidth, $iTop - $sBoxSize , $sBoxSize, $iHeight + $sBoxSize + $sBoxSize, $iStyle, $iExStyle)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)
    Return $iCtrl
EndFunc   ;==>GUICtrlCreateButton_wBox

Func GUICtrlButton_wBox_Color($iCtrl, $iColor)
    For $n = $iCtrl + 1 To $iCtrl + 4
        GUICtrlSetBkColor($n, $iColor)
    Next
EndFunc   ;==>GUICtrlButton_wBox_Color

Local $sec = @SEC
Local $toBeOrNot = True
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            GUIDelete()
            ExitLoop
        Case $Button1
            ConsoleWrite("$Button1" & @CRLF)
    EndSwitch
    If $sec = @SEC Then ContinueLoop
    $sec = @SEC
    $toBeOrNot = Not $toBeOrNot
    If $toBeOrNot Then
        GUICtrlButton_wBox_Color($Button1, 0xFF0000)
        GUICtrlButton_wBox_Color($Button2, 0x00FFFF)
    Else
        GUICtrlButton_wBox_Color($Button2, 0xFF00FF)
        GUICtrlButton_wBox_Color($Button1, 0x0000FF)
    EndIf
WEnd

 

is my take :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Thanks @argumentum for taking a shot at it. Unfortunately I need to just show a border around a control because most of the time the control will actually be hidden.

Anyway, I came up with this. I was hoping to avoid splitting it into more then one script but I don't see a way around it for what I need.

Example GUI

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

Opt("GuiOnEventMode", 1)
Opt("MustDeclareVars", 1)

Global $g_hGUI, $g_idDummy

$g_hGUI = GUICreate("test", 500, 500, -1, -1, $WS_SIZEBOX + $WS_MAXIMIZEBOX, $WS_EX_COMPOSITED)

$g_idDummy = GUICtrlCreateButton("", 250, 250, 50, 50)
GUICtrlSetResizing($g_idDummy, $GUI_DOCKAUTO)

GUISetState()

GUISetOnEvent($GUI_EVENT_CLOSE, "WinEvents", $g_hGUI)

SelectControl($g_hGUI, "[INSTANCE:1]", 5, "0xFF0000")

While 1
    Sleep(250)
WEnd

Func SelectControl($hGUI, $idControl, $iBorderWidth, $iBorderColor)
    Run(@ScriptDir & "\Selector.exe " & $hGUI & " " & $idControl & " " & $iBorderWidth & " " & $iBorderColor)
EndFunc   ;==>SelectControl

Func WinEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            Exit
    EndSelect
EndFunc   ;==>WinEvents

 

Selector script (needs to be compiled to work).

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

Opt("TrayIconHide", 1)
Opt("MustDeclareVars", 1)

;will exit if not ran with all parameters
If $CmdLine[0] <> 4 Then
    Exit
EndIf

Global $g_hSelectorGUI, $g_aMainWinCtrlPos, $g_iBorderWidth, $g_hWinHandle, $g_idControl, $g_iBorderWidth, $g_iBorderColor

$g_hWinHandle = $CmdLine[1]
$g_idControl = $CmdLine[2]
$g_iBorderWidth = $CmdLine[3]
$g_iBorderColor = $CmdLine[4]

Dim $g_aMainWinCtrlPos[4]

$g_hSelectorGUI = GUICreate("Selector", 0, 0, 0, 0, $WS_POPUP, $WS_EX_TOPMOST + $WS_EX_TOOLWINDOW)
GUISetBkColor($g_iBorderColor)

GUISetState(@SW_SHOW, $g_hSelectorGUI)

;updates the selector
AdlibRegister("UpdateSelector")

While 1
    Sleep(250)
WEnd

Func UpdateSelector()
    ;exits if the main program closes
    If Not WinExists($g_hWinHandle) Then Exit

    Local $aPos, $hInner_rgn, $hOuter_rgn

    $aPos = ControlRelativeToDesktop($g_hWinHandle, $g_idControl)

    If $aPos[0] = $g_aMainWinCtrlPos[0] And $aPos[1] = $g_aMainWinCtrlPos[1] And $aPos[2] = $g_aMainWinCtrlPos[2] And $aPos[3] = $g_aMainWinCtrlPos[3] Then Return

    $g_aMainWinCtrlPos = $aPos

    $g_aMainWinCtrlPos = ControlRelativeToDesktop($g_hWinHandle, $g_idControl)
    WinMove($g_hSelectorGUI, "", $g_aMainWinCtrlPos[0] - $g_iBorderWidth, $g_aMainWinCtrlPos[1] - $g_iBorderWidth, $g_aMainWinCtrlPos[2] + $g_iBorderWidth * 2, $g_aMainWinCtrlPos[3] + $g_iBorderWidth * 2)
    $hInner_rgn = _WinAPI_CreateRectRgn($g_aMainWinCtrlPos[0], $g_aMainWinCtrlPos[1], $g_aMainWinCtrlPos[0] + $g_aMainWinCtrlPos[2], $g_aMainWinCtrlPos[1] + $g_aMainWinCtrlPos[3])

    Local $hOuter_rgn, $hInner_rgn, $hCombined_rgn

    $hOuter_rgn = _WinAPI_CreateRectRgn(0, 0, $g_aMainWinCtrlPos[2] + $g_iBorderWidth * 2, $g_aMainWinCtrlPos[3] + $g_iBorderWidth * 2)
    $hInner_rgn = _WinAPI_CreateRectRgn($g_iBorderWidth, $g_iBorderWidth, $g_aMainWinCtrlPos[2] + $g_iBorderWidth, $g_aMainWinCtrlPos[3] + $g_iBorderWidth)

    $hCombined_rgn = _WinAPI_CreateRectRgn(0, 0, 0, 0)
    _WinAPI_CombineRgn($hCombined_rgn, $hOuter_rgn, $hInner_rgn, $RGN_DIFF)
    _WinAPI_DeleteObject($hOuter_rgn)
    _WinAPI_DeleteObject($hInner_rgn)

    _WinAPI_SetWindowRgn($g_hSelectorGUI, $hCombined_rgn)
EndFunc   ;==>UpdateSelector

Func ControlRelativeToDesktop($hWnd, $idControl)
    Local $Point, $aControlXYPos

    Dim $aPos[4]

    $aControlXYPos = ControlGetPos($hWnd, "", $idControl)

    $Point = DllStructCreate("int;int")
    DllStructSetData($Point, 1, $aControlXYPos[0])
    DllStructSetData($Point, 2, $aControlXYPos[1])
    DllCall("User32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($Point))

    ;x
    $aPos[0] = DllStructGetData($Point, 1)

    ;y
    $aPos[1] = DllStructGetData($Point, 2)

    ;width
    $aPos[2] = $aControlXYPos[2]

    ;height
    $aPos[3] = $aControlXYPos[3]

    Return $aPos
EndFunc   ;==>ControlRelativeToDesktop

 

Edited by Herb191
Fixed small error in code.
Link to comment
Share on other sites

Instead of using WinAPI functions, what about using a simple label ? If what you need is just a border color, it could by sufficient.

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

Local $hMain = GUICreate("GUI", 400, 400, -1, -1, $WS_SIZEBOX + $WS_MAXIMIZEBOX, $WS_EX_COMPOSITED)

Local $id_button = GUICtrlCreateButton("Button", 100, 100, 200, 50)
GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

_CreateBorder($hMain, "", $id_button, 3, 0xFF0000)
GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

GUISetState()

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd


Func _CreateBorder($hGui, $sText, $vCtrl, $iWidth, $iColor)
    Local $aPos = ControlGetPos($hGui, $sText, $vCtrl)
    Local $idLabel = GUICtrlCreateLabel("", $aPos[0] - $iWidth, $aPos[1] -  $iWidth, $aPos[2] + $iWidth * 2, $aPos[3] + $iWidth * 2)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetBkColor(-1, $iColor)
    Return $idLabel
EndFunc

 

Link to comment
Share on other sites

I played with that option but the selector/border will actually be over the top of some image controls so labels don’t always display properly. The button control itself will be hidden. I am just using the button control to calculate the dimensions of the selector/border when the window gets resized. Also, I need the width of the selector’s border to stay the same even when the area is changing size.

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