timmalos Posted July 20, 2017 Posted July 20, 2017 (edited) Hey all. I'm trying to know when my user clicks on a Rect drawn via GDI+. Everything is almost working except I have a strange behaviour in the "order" clicks are fired. I created a simplified code to help : expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled _GDIPlus_Startup() Global $hGUI, $hGraphics Global $iWidth = 1024, $iHeight = 762 createGUI() draw() While 1 Sleep(10) WEnd Func createGUI() $hGUI = GUICreate("Current CasparCG Output", $iWidth,$iHeight) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetBkColor(0x000000) GUISetState(@SW_SHOW) $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;sets the graphics object rendering quality (antialiasing) EndFunc ;==>Example Func draw() ;_WinAPI_draw($hGUI,"","",BitOR($RDW_ERASE,$RDW_INVALIDATE,$RDW_UPDATENOW)) _GDIPlus_GraphicsClear($hGraphics) $hFamily = _GDIPlus_FontFamilyCreate("Arial") $hFont = _GDIPlus_FontCreate($hFamily, 15, 1) $hPen = _GDIPlus_PenCreate(0xFFFEDCFF, 2) ;color format AARRGGBB (hex) $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) $hBrushString = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF00FF) ;color format AARRGGBB (hex) For $i = 1 to 2 Local $x = 0.25 Local $y = 0.25 Local $w = 0.5 Local $h = 0.5 Local $title = "Layer "&$i If $x >= -1 And $x <= 1 Then $x *= $iWidth If $y >= -1 And $y <= 1 Then $y *= $iHeight If $w >= -1 And $w <= 1 Then $w *= $iWidth If $h >= -1 And $h <= 1 Then $h *= $iHeight $hItem = GUICtrlCreateLabel("", $x,$y,$w,$h) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetOnEvent($hItem,"_gui_layer_clicked") ConsoleWrite("Created label with handle="&$hItem&" $i= " & $i&@CRLF) _GDIPlus_GraphicsFillRect($hGraphics, $x, $y, $w, $h,$hBrush) _GDIPlus_GraphicsDrawRect($hGraphics, $x, $y, $w, $h,$hPen) $tLayout = _GDIPlus_RectFCreate($x, $y, $w, $h) $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $title, $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsDrawStringEx($hGraphics, $title, $hFont, $aInfo[0], $hFormat, $hBrushString) Next _GDIPlus_BrushDispose($hBrush) _GDIPlus_PenDispose($hPen) _GDIPlus_FontDispose($hFont) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_BrushDispose($hBrushString) Return 1 EndFunc Func _gui_layer_clicked() ConsoleWrite("Clicked on " & @GUI_CtrlId&@CRLF) EndFunc Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Clean up resources _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() Exit EndSelect EndFunc ;==>SpecialEvents What happens there : We have two rectangles, with the one labelled "2" is front and, the one labelled "1" in background. However when we click, the fired label is the one created first (in the background) and not the second one (in the front). Is it normal ? If yes, is there any way to change this order ? If I create another label after a first one on the same coords, I would the second one to be fired instead of the first one (This is a simplified code I can't just invert the label order creation easily) Thanks for your help Edited July 20, 2017 by timmalos
InunoTaishou Posted July 20, 2017 Posted July 20, 2017 Both of your layers are the exact same size so if you want to differentiate between them you need to make one smaller. The reason the label is proccing for layer1 is because it's the first one created in the control chain. Might be easier to manually check, yourself, if the user clicks inside the GDI object using a GUIRegisterMsg. Here's how you can do it expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled _GDIPlus_Startup() Global $hGUI, $hGraphics Global $iWidth = 1024, $iHeight = 762 ; Holds the GDI+ object rects Global $aGdiPosition[2][5] createGUI() draw() While 1 Sleep(10) WEnd Func createGUI() $hGUI = GUICreate("Current CasparCG Output", $iWidth, $iHeight) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetBkColor(0x000000) GUISetState(@SW_SHOW) ; Register the LBUTTONUP message so we know when someone clicks on the GUI GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP) $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;sets the graphics object rendering quality (antialiasing) EndFunc ;==>createGUI Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam) ; X and Y positions are in the $lParam Local $iX = _WinAPI_LoWord($lParam) Local $iY = _WinAPI_HiWord($lParam) Local $bValidClick = False ; Go through these layers in reverse order they were created, top to bottom For $i = UBound($aGdiPosition) - 1 To 0 Step -1 ; The click is inside the rect where the GDI+ object is If (_WinAPI_PtInRectEx($iX, $iY, $aGdiPosition[$i][0], $aGdiPosition[$i][1], $aGdiPosition[$i][2], $aGdiPosition[$i][3])) Then ConsoleWrite("Clicked on " & $aGdiPosition[$i][4] & @LF) $bValidClick = True ExitLoop EndIf Next If (Not $bValidClick) Then ConsoleWrite("Clicked outside the valid layers" & @LF) Return $GUI_RUNDEFMSG EndFunc ;==>WM_LBUTTONUP Func draw() ;_WinAPI_draw($hGUI,"","",BitOR($RDW_ERASE,$RDW_INVALIDATE,$RDW_UPDATENOW)) _GDIPlus_GraphicsClear($hGraphics) $hFamily = _GDIPlus_FontFamilyCreate("Arial") $hFont = _GDIPlus_FontCreate($hFamily, 15, 1) $hPen = _GDIPlus_PenCreate(0xFFFEDCFF, 2) ;color format AARRGGBB (hex) $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) $hBrushString = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF00FF) ;color format AARRGGBB (hex) For $i = 1 To 2 Local $x = 0.25 Local $y = 0.25 Local $w = 0.5 Local $h = 0.5 Local $title = "Layer " & $i If $x >= -1 And $x <= 1 Then $x *= $iWidth If $y >= -1 And $y <= 1 Then $y *= $iHeight If $w >= -1 And $w <= 1 Then $w *= $iWidth / $i ; so the second one is smaller If $h >= -1 And $h <= 1 Then $h *= $iHeight / $i ; so the second one is smaller $aGdiPosition[$i - 1][0] = $x $aGdiPosition[$i - 1][1] = $y $aGdiPosition[$i - 1][2] = $x + $w $aGdiPosition[$i - 1][3] = $y + $h $aGdiPosition[$i - 1][4] = $title _GDIPlus_GraphicsFillRect($hGraphics, $x, $y, $w, $h, $hBrush) _GDIPlus_GraphicsDrawRect($hGraphics, $x, $y, $w, $h, $hPen) $tLayout = _GDIPlus_RectFCreate($x, $y, $w, $h) $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $title, $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsDrawStringEx($hGraphics, $title, $hFont, $aInfo[0], $hFormat, $hBrushString) Next _GDIPlus_BrushDispose($hBrush) _GDIPlus_PenDispose($hPen) _GDIPlus_FontDispose($hFont) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_BrushDispose($hBrushString) Return 1 EndFunc ;==>draw Func _gui_layer_clicked() ConsoleWrite("Clicked on " & @GUI_CtrlId & @CRLF) EndFunc ;==>_gui_layer_clicked Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Clean up resources _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() Exit EndSelect EndFunc ;==>SpecialEvents
timmalos Posted July 20, 2017 Author Posted July 20, 2017 (edited) Hey all. Managed to find a solution with the right keyword : "z-order". This makes the trick : GUICtrlSetState(-1, $GUI_ONTOP) EDIT : Just saw InunoTaishou answer which works well without needing the text controls, I'll use your solution , thanks ! Edited July 20, 2017 by timmalos
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now