geon79

Graphics transparent to clicks

8 posts in this topic

I have a nagging problem I can't seem to find the solution of. 

What I'd like to create are graphic objects that overlay with specific areas of the screen and are completely "inconsistent" in the sense that any click will pass right through to the underlying window. My purpose is to highlight precisely specific areas that a user should click with bright colours: these areas are very irregular so they will be typically be drawn on a pixel-by-pixel basis. The rest of the window must be completely visible, so total transparency of the background of the hosting GUI is mandatory and the coloured areas must not block the clicking of what's under them, of course. 

Any idea of how it could be done?

Thanks all in advance for help.

Share this post


Link to post
Share on other sites



Have a look at:

WinSetTrans

 


Snips & Scripts


My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ

 

Share this post


Link to post
Share on other sites

Try this:

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

Global $hGui = GUICreate("Click-through topmost GUI", -1, -1, -1, -1, -1, BitOR($WS_EX_TOPMOST, $WS_EX_TRANSPARENT, $WS_EX_LAYERED))
; ............. Add your controls here
GUISetControlsVisible($hGui)
guisetstate(@SW_SHOW)

Func GUISetControlsVisible($hWnd) ;thanks to the author of the function
    Local $aM_Mask, $aCtrlPos, $aMask

    $aM_Mask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
    $aLastID = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", GUICtrlGetHandle(-1))

    For $i = 3 To $aLastID[0]
        $aCtrlPos = ControlGetPos($hWnd, '', $i)
        If Not IsArray($aCtrlPos) Then ContinueLoop

        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", _
            "long", $aCtrlPos[0], _
            "long", $aCtrlPos[1], _
            "long", $aCtrlPos[0] + $aCtrlPos[2], _
            "long", $aCtrlPos[1] + $aCtrlPos[3])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
    Next
    DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWnd, "long", $aM_Mask[0], "int", 1)
EndFunc

 


No matter whatever the challenge maybe control on the outcome its on you its always have been.

MY UDF: Transpond UDF (Sent vriables to Programs) , Utter UDF (Speech Recognition)

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

It doesn't work :(  A GUI will show at all only if GUISetState(@SW_SHOW) is called before  GUISetControlsVisible function is called and the extended style "layered" is removed, but even then the result is wrong graphically (shows the top left part of the GUI window, not the control) and it isn't transparent. Setting the style to $WS_POPUP does show the control correctly but I can't click through it, probably because the GUI lacks the "layered" attribute.

My programming skills aren't enough to understand how it's supposed to work. Any idea? 

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
HotKeySet("{ESC}","esc")
Global $hGui = GUICreate("Click-through topmost GUI", 100, 100,200, 200, -1, BitOR($WS_EX_TOPMOST, $WS_EX_TRANSPARENT, $WS_EX_LAYERED))
GuiCtrlCreateLabel("Label",-1,-1)
GUISetState(@SW_SHOW)
GUISetControlsVisible($hGui)

While 1
    Sleep(100)
WEnd
Func GUISetControlsVisible($hWnd) ;thanks to the author of the function
    Local $aM_Mask, $aCtrlPos, $aMask

    $aM_Mask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
    $aLastID = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", GUICtrlGetHandle(-1))

    For $i = 3 To $aLastID[0]
        $aCtrlPos = ControlGetPos($hWnd, '', $i)
        If Not IsArray($aCtrlPos) Then ContinueLoop

        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", _
            "long", $aCtrlPos[0], _
            "long", $aCtrlPos[1], _
            "long", $aCtrlPos[0] + $aCtrlPos[2], _
            "long", $aCtrlPos[1] + $aCtrlPos[3])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
    Next
    DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWnd, "long", $aM_Mask[0], "int", 1)
EndFunc
Func esc() ;ESC to quit
    Exit
EndFunc

 

Edited by geon79
Additional analysis

Share this post


Link to post
Share on other sites

Here is a more modified version :

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinApi.au3>
Global $trans = 200

HotKeySet("{ESC}","esc")

Global $hgui = GUICreate("Click-through topmost GUI", 100, 100,200, 200,$WS_POPUP)
GuiCtrlCreateLabel("Label",-1,-1)

WinSetOnTop($hgui, "", 1)
WinSetTrans($hgui,"",$trans)

GUISetControlsVisible($hgui)

_WinAPI_SetWindowLong($hgui, $GWL_EXSTYLE, _
            BitOR(_WinAPI_GetWindowLong($hgui, $GWL_EXSTYLE), $WS_EX_TRANSPARENT))

GUISetState()
While 1
    Sleep(100)
WEnd
Func GUISetControlsVisible($hWnd) ;thanks to the author of the function
    Local $aM_Mask, $aCtrlPos, $aMask

    $aM_Mask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
    $aLastID = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", GUICtrlGetHandle(-1))

    For $i = 3 To $aLastID[0]
        $aCtrlPos = ControlGetPos($hWnd, '', $i)
        If Not IsArray($aCtrlPos) Then ContinueLoop

        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", _
            "long", $aCtrlPos[0], _
            "long", $aCtrlPos[1], _
            "long", $aCtrlPos[0] + $aCtrlPos[2], _
            "long", $aCtrlPos[1] + $aCtrlPos[3])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
    Next
    DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWnd, "long", $aM_Mask[0], "int", 1)
EndFunc
Func esc() ;ESC to quit
    Exit
EndFunc

Set the $trans variable to your suitable transparency value


No matter whatever the challenge maybe control on the outcome its on you its always have been.

MY UDF: Transpond UDF (Sent vriables to Programs) , Utter UDF (Speech Recognition)

Share this post


Link to post
Share on other sites

Now the label shows, but still I can't click through it. I couldn't anticipate this would be so much trouble to implement!

Share this post


Link to post
Share on other sites

Ok, I don't know exactly why, with a few changes it actually works without using WinAPI, all it  needs is the extended style $WS_EX_TRANSPARENT in the GUI creation. Why didn't it work in previous versions? I haven't got he slightest clue.

Now it's usable, thanks a lot Surya for help. The only final improvement that would make it perfect is having totally transparent background (for Graphic controls mainly), I can set only overall transparency at the moment, $GUI_BKCOLOR_TRANSPARENT seems to be ignored even for labels (while other colours can be set).

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $trans = 200

HotKeySet("{ESC}","esc")
Global $hgui = GUICreate("Click-through topmost GUI", 250, 250,350, 350,$WS_POPUP,$WS_EX_TRANSPARENT)
GuiCtrlCreateLabel("Label",60,60)
GUICtrlSetBkColor(-1,$GUI_BKCOLOR_TRANSPARENT)
GUICtrlCreateGraphic(0,0,21,21)
GUICtrlSetGraphic(-1,$GUI_GR_COLOR,0xff0000)
GUICtrlSetGraphic(-1,$GUI_GR_PIXEL,10,10)
GUICtrlSetGraphic(-1,$GUI_GR_COLOR,0x33ff22)
GUICtrlSetGraphic(-1,$GUI_GR_ELLIPSE,0,0,21,21)


WinSetOnTop($hgui, "", 1)
WinSetTrans($hgui,"",$trans)

GUISetControlsVisible($hgui)


GUISetState()
While 1
    Sleep(100)
WEnd
Func GUISetControlsVisible($hWnd) ;thanks to the author of the function
    Local $aM_Mask, $aCtrlPos, $aMask

    $aM_Mask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
    $aLastID = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", GUICtrlGetHandle(-1))

    For $i = 3 To $aLastID[0]
        $aCtrlPos = ControlGetPos($hWnd, '', $i)
        If Not IsArray($aCtrlPos) Then ContinueLoop

        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", _
            "long", $aCtrlPos[0], _
            "long", $aCtrlPos[1], _
            "long", $aCtrlPos[0] + $aCtrlPos[2], _
            "long", $aCtrlPos[1] + $aCtrlPos[3])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
    Next
    DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hWnd, "long", $aM_Mask[0], "int", 1)
EndFunc
Func esc() ;ESC to quit
    Exit
EndFunc

 

 

Share this post


Link to post
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