Jump to content

Recommended Posts

Posted

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

 

Posted

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

 

Posted

​is not working for me. Maybe in the paste to the post something got lost ?

​Interesting. I just copied the code from the forum and it worked for me. What do you mean when you say its "not working"?

Posted

Darn. I just tested it on another computer and had the same problem. I have been going at it all day. I will try to fix it tomorrow. Unless anyone knows why its not working. :whistle:

Posted

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

Posted (edited)

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

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

 

Posted

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.

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