zfisherdrums Posted June 7, 2006 Posted June 7, 2006 I must believe that this question has been posted before, but my eyes are about to explode from reading all the results of my forum search. Please bear with me... My ultimate goal is replicating what I would call the "mouse spotlight" that I have seen on many online software-training videos (a 'la recent video tutorials for Visual Studio 2005). This spotlight is a transparent shape (usually round) that follows the mouse cursor. In addition, any mouse click messages get sent "through" to the controls/windows underneath. Maybe it's best to think of it as a very obvious shadow. Having said that, I've tinkered a bit with creating a rounded gui that re-adjusts its position whenever it registers a mouse move event on the form itself. Hopefully this prototype is more descriptive: expandcollapse popupOpt("GUICoordMode",1) Dim $x Dim $y Dim $WinInfo Dim $MouseInfo $MouseInfo = MouseGetPos() $Form1 = GUICreate("AForm1", 118, 100, $MouseInfo[0]-59, $MouseInfo[1]-50, BitOR($WS_BORDER,$WS_CLIPSIBLINGS, $WS_EX_LAYERED, $WS_EX_TRANSPARENT), 0) WinSetTrans($Form1,"",150) GUISetState() GuiRoundCorners($Form1,10,10,270,270);<----- thanks gaFrost While 1 $msg = GUIGetMsg(1) Select Case $msg[0] = $GUI_EVENT_MOUSEMOVE $WinInfo = WinGetPos($Form1) $MouseInfo = MouseGetPos() $x = ($WinInfo[2]/2) $y = ($WinInfo[3]/2) WinMove($Form1,"",$MouseInfo[0]-$x,$MouseInfo[1]-$y) Case $msg[0] = $GUI_EVENT_CLOSE Exit EndSelect WEnd ;=============================================================================== ; ; Function Name: GuiRoundCorners() ; Description: Rounds the corners of a window ; Parameter(s): $h_win ; $i_x1 ; $i_y1 ; $i_x3 ; $i_y3 ; Requirement(s): AutoIt3 ; Return Value(s): ; Author(s): gaFrost ; ;=============================================================================== Func GuiRoundCorners($h_win, $i_x1, $i_y1, $i_x3, $i_y3) Dim $pos, $ret, $ret2 $pos = WinGetPos($h_win) $ret = DllCall("gdi32.dll", "long", "CreateRoundRectRgn", "long", $i_x1, "long", $i_y1, "long", $pos[2], "long", $pos[3], "long", $i_x3, "long", $i_y3) If $ret[0] Then $ret2 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $ret[0], "int", 1) If $ret2[0] Then Return 1 Else Return 0 EndIf Else Return 0 EndIf EndFunc ;==>_GuiRoundCorners The caveat here is that mouse button events are not being allowed to "fall through" the window. I'm pretty sure that having the window under constant focus doesn't help either. MSDN documentation on Win 32 Window Classes and Layered Windows were promising initially, but the devil has come out in the details. So the question is: could this shadowing/spotlight behavior possibly work with the logic above? If not, any suggestions? This community seems to be very supportive, so I look forward to hearing from some of you. Identify .NET controls by their design time namesLazyReader© could have read all this for you. Unit Testing for AutoItFolder WatcherWord Doc ComparisonThis here blog...
Richard Robertson Posted June 8, 2006 Posted June 8, 2006 You could always put a pixel hole at the cursor. I've made things like this for flash games that hide the cursor. The shape looked like [][][][][] [][][][][] [][]--[][] [][][][][] [][][][][] Where [] = pixel, -- = hole. Window regions are fun. Otherwise, you could find the control directly below the shadow and send a Control Click.
zfisherdrums Posted June 8, 2006 Author Posted June 8, 2006 Dear Mr. Icekirby1, I'd love to try your suggestion. Do you have any prototypes or code snippets that would showcase this? I must admit that if my life depended on placing a pixel hole in a form, the world would be less one idiot. Most posts I've found seemed to assume this knowledge beforehand. Please help me stay alive another day. Sincerely, zfisherdrums You could always put a pixel hole at the cursor. I've made things like this for flash games that hide the cursor. The shape looked like [][][][][] [][][][][] [][]--[][] [][][][][] [][][][][] Where [] = pixel, -- = hole. Window regions are fun. Otherwise, you could find the control directly below the shadow and send a Control Click. Identify .NET controls by their design time namesLazyReader© could have read all this for you. Unit Testing for AutoItFolder WatcherWord Doc ComparisonThis here blog...
b8bboi Posted June 8, 2006 Posted June 8, 2006 Here you go. Just change the size, location, etc. to your liking. Also, add some error checking just in case. expandcollapse popup#include <GUIConstants.au3> Opt("GUICoordMode",1) Dim $x Dim $y Dim $WinInfo Dim $MouseInfo Global $size = 200 $MouseInfo = MouseGetPos() $Form1 = GUICreate("AForm1", $size, $size, $MouseInfo[0]-59, $MouseInfo[1]-50, $WS_POPUP, 0) WinSetTrans($Form1,"",150) GUISetState() GuiRoundHole($Form1,0,0,$size,$size);<----- thanks gaFrost While 1 $msg = GUIGetMsg(1) Select Case $msg[0] = $GUI_EVENT_MOUSEMOVE $WinInfo = WinGetPos($Form1) $MouseInfo = MouseGetPos() $x = ($WinInfo[2]/2) $y = ($WinInfo[3]/2) WinMove($Form1,"",$MouseInfo[0]-$x+1,$MouseInfo[1]-$y+1) Case $msg[0] = $GUI_EVENT_CLOSE Exit EndSelect WEnd ;=============================================================================== ; ; Function Name: GuiRoundHole() ; Description: Rounds the corners of a window ; Parameter(s): $h_win ; $i_x1 ; $i_y1 ; $i_x3 ; $i_y3 ; Requirement(s): AutoIt3 ; Return Value(s): ; Author(s): gaFrost ; ;=============================================================================== Func GuiRoundHole($h_win, $i_x1, $i_y1, $i_x3, $i_y3) Local $halfx = Int(($i_x3 - $i_x1) / 2) Local $halfy = Int(($i_y3 - $i_y1) / 2) Local $holesize = 3 Local $outer_rgn = DllCall("gdi32.dll", "long", "CreateEllipticRgn", "long", $i_x1, "long", $i_y1, "long", $i_x3 , "long", $i_y3) Local $inner_rgn = DllCall("gdi32.dll", "long", "CreateEllipticRgn", "long", $i_x1+$halfx-$holesize, "long", $i_y1+$halfy-$holesize, "long", $i_x1+$halfx+$holesize, "long", $i_y1+$halfy+$holesize) If $outer_rgn[0] and $inner_rgn[0] Then Local $combined_rgn = DllCall("gdi32.dll", "long", "CreateEllipticRgn", "long", 0, "long", 0, "long", 0, "long", 0) DllCall("gdi32.dll", "long", "CombineRgn", "long", $combined_rgn[0], "long", $outer_rgn[0], "long", $inner_rgn[0], "int", 4) Local $ret3 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $combined_rgn[0], "int", 1) If $ret3[0] Then Return 1 Else Return 0 EndIf Else Return 0 EndIf EndFunc ;==>_GuiRoundHole
zfisherdrums Posted June 9, 2006 Author Posted June 9, 2006 First, thank you all for your help and superior talent with this "weird" design.b8bboi, I used your code and it really helped me understand IceKirby1's suggestion about the window regions. After some initial tinkering with lining up the region and adjusting the size of the hole, I could see how it works. The only problem I'm running into is the mouse events are not passed "through" 100% of the time. If this behavior is not as apparent on your system, I'd be willing to bet it is the death rattle of this HP Pavillion Laptop. But being that's it will be used for a tutorial that will distributed, I'd be willing to bet it would happen to some other poor sap.A while back, I found an example on the codeproject that created a click through window in VB.net, but having it follow the mouse proved problematic. Pilot error. At this point I'm beginning to think that if this is the wrong direction, then I might try something like this:; create alpha-blended, semi-transparent form that overlays application under test; capture mouse movements and render GDI shape in the form to follow; pass mouse event to control located underneath the form/ application under testBut somehow, this seems like a lot of overhead. Like pulling an aircraft carrier into port just to fix a bolt.If anyone can help me out with programatically determining the control under cursor, I'd be grateful.Although something tells me that its probably already on the forum. Feel free to read me the riot act.Finally, if you've read this far, the example I'm trying to emulate can be observed here.Look specifically at the picture used for Lesson 2. Identify .NET controls by their design time namesLazyReader© could have read all this for you. Unit Testing for AutoItFolder WatcherWord Doc ComparisonThis here blog...
b8bboi Posted June 9, 2006 Posted June 9, 2006 You can hide the "spotlight" and do a mouse click on the area underneath. Try this. Double-click doesn't work. You'll have to modify the code to make it work. expandcollapse popup#include <GUIConstants.au3> Opt("GUICoordMode",1) Dim $x Dim $y Dim $WinInfo Dim $MouseInfo Global $size = 200 $MouseInfo = MouseGetPos() Global $Form1 = GUICreate("AForm1", $size, $size, $MouseInfo[0]-59, $MouseInfo[1]-50, $WS_POPUP, 0) Global $label = GUICtrlCreateLabel("", 0, 0, $size, $size) WinSetTrans($Form1,"",150) GUISetState() GuiRound($Form1,0,0,$size,$size);<----- thanks gaFrost While 1 $msg = GUIGetMsg(1) Select Case $msg[0] = $GUI_EVENT_MOUSEMOVE $WinInfo = WinGetPos($Form1) $MouseInfo = MouseGetPos() $x = ($WinInfo[2]/2) $y = ($WinInfo[3]/2) WinMove($Form1,"",$MouseInfo[0]-$x+1,$MouseInfo[1]-$y+1) Case $msg[0] = $label MouseClicked() Case $msg[0] = $GUI_EVENT_CLOSE Exit EndSelect WEnd Func MouseClicked() Local $mousepos = MouseGetPos() GUISetState(@SW_HIDE, $Form1) Sleep(100) MouseClick("", $mousepos[0], $mousepos[1], 1, 1) GUISetState(@SW_SHOW, $Form1) EndFunc ;=============================================================================== ; ; Function Name: GuiRoundHole() ; Description: Rounds the corners of a window ; Parameter(s): $h_win ; $i_x1 ; $i_y1 ; $i_x3 ; $i_y3 ; Requirement(s): AutoIt3 ; Return Value(s): ; Author(s): gaFrost ; ;=============================================================================== Func GuiRound($h_win, $i_x1, $i_y1, $i_x3, $i_y3) Local $halfx = Int(($i_x3 - $i_x1) / 2) Local $halfy = Int(($i_y3 - $i_y1) / 2) Local $holesize = 3 Local $outer_rgn = DllCall("gdi32.dll", "long", "CreateEllipticRgn", "long", $i_x1, "long", $i_y1, "long", $i_x3 , "long", $i_y3) If $outer_rgn[0] Then Local $ret3 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $outer_rgn[0], "int", 1) If $ret3[0] Then Return 1 Else Return 0 EndIf Else Return 0 EndIf EndFunc ;==>_GuiRoundHole
greenmachine Posted June 9, 2006 Posted June 9, 2006 This works. You were almost there, but you just have to put the window styles in the right places. HotKeySet ("+{ESC}", "IWannaQuit") Global $Width = 100, $Height = 100, $Left = MouseGetPos (0) - $Width/2, $Top = MouseGetPos (1) - $Height/2 $ClickWin = GUICreate ("Click Through Me", $Width, $Height, $Left, $Top, $WS_POPUP, BitOR ($WS_EX_TRANSPARENT, $WS_EX_LAYERED, $WS_EX_TOPMOST)) WinSetTrans ($ClickWin, "", 150) GUISetState () While 1 Sleep (10) TheMouseMoved() WEnd Func TheMouseMoved() $WinPos = WinGetPos ($ClickWin) WinMove ($ClickWin, "", MouseGetPos (0) - $Width/2, MouseGetPos (1) - $Height/2) EndFunc Func IWannaQuit() Exit EndFunc
Richard Robertson Posted June 10, 2006 Posted June 10, 2006 Glad I could help, at least in theory. I'm not really very good at interop between AutoIt and things AutoIt doesn't directly support.
zfisherdrums Posted June 10, 2006 Author Posted June 10, 2006 Dear IceKirby1, greenmachine, b8bboi, and slightly-abnormal; I could not have done this without you all. Thanks for a great re-introduction into posting. I've been admittedly shy on these because I've seen how ugly some individuals can be. Your help restores my faith in e-humanity. I'm officially closing this thread. The final code is placed here in hopes that it will help others. expandcollapse popup#include <GUIConstants.au3> HotKeySet ("+{ESC}", "IWannaQuit") Global $size = 100 Global $Left = MouseGetPos (0) - $size / 2 Global $Top = MouseGetPos (1) - $size / 2 $MouseShadow = GUICreate ("Click Through Me", $size, $size, $Left, $Top, $WS_POPUP, _ BitOR ($WS_EX_TRANSPARENT, $WS_EX_LAYERED, $WS_EX_TOPMOST)) Global $label = GUICtrlCreateLabel("", 0, 0, $size, $size) WinSetTrans ($MouseShadow, "", 150) GUISetBkColor(0xFFFF00, $MouseShadow) GuiRoundCorners($MouseShadow,10,10,270,270) GUISetState () While 1 Sleep (10) TheMouseMoved() WEnd Func TheMouseMoved() $WinPos = WinGetPos ($MouseShadow) WinMove ($MouseShadow, "", MouseGetPos (0) - $size/2, MouseGetPos (1) - $size/2) EndFunc Func IWannaQuit() Exit EndFunc ;=============================================================================== ; ; Function Name: GuiRoundCorners() ; Description: Rounds the corners of a window ; Parameter(s): $h_win ; $i_x1 ; $i_y1 ; $i_x3 ; $i_y3 ; Requirement(s): AutoIt3 ; Return Value(s): ; Author(s): gaFrost ; ;=============================================================================== Func GuiRoundCorners($h_win, $i_x1, $i_y1, $i_x3, $i_y3) Dim $pos, $ret, $ret2 $pos = WinGetPos($h_win) $ret = DllCall("gdi32.dll", "long", "CreateRoundRectRgn", "long", $i_x1, "long", $i_y1, "long", $pos[2], "long", $pos[3], "long", $i_x3, "long", $i_y3) If $ret[0] Then $ret2 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $ret[0], "int", 1) If $ret2[0] Then Return 1 Else Return 0 EndIf Else Return 0 EndIf EndFunc;==>_GuiRoundCorners Identify .NET controls by their design time namesLazyReader© could have read all this for you. Unit Testing for AutoItFolder WatcherWord Doc ComparisonThis here blog...
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