Search the Community
Showing results for tags 'ControlHover'.
-
Version 3: Ops, you may ask, where's the version 2? The answer is, you will never see it. I skipped it to jump to version 3 directly. Why? Actually, I didn't learn M$ about that versioning The reason is, I planed to write version 2, using the new window/control handle indexing technique to eliminate all the ugly and slow loop. But when nearly finish, I feel so tired, tired of using a lots of all workaround. And finally, I decided to rewrite entire the UDF, using the direct solution, the way all other languages used, and should use. I late some day, because of some machine code (it's actually not so necessary, but if the control is doing an expensive task, like heavy drawing then passing all the Window Message to AutoIt is not a so good idea because its slow speed may result in some annoying-small-but-easy-to-figure-out problems, (like tearing as example). So I use machine code directly to pass over it. Now you have not a Stupid but a Smart UDF And it's still simple. API change: Remove a parameter from _SSCtrlHover_Register. You nolonger can attach other controls to the registered control. Use another method to do it and when you delete the control be sure to delete all the attached controls yourself. This breaks your old script. Add double click event (last 2 parameters of _SSCtrlHover_Register) Remove the _SSCtrlHover_Delete. You must manually delete yourself. It's easy with GUICtrlDelete and I decide not to duplicate this function to my UDF (be sure to delete your attached control too) This version eliminate all the odd limit of old version, include: No:longer use timer/adlib to test the control is on mouse event. Now it directly use native WinAPI method to provide a truly event-driven way. Every click is detected, every mouse hover/left, is handled perfectly. Fast and very fast. All the loop is eliminated. Machine code. Execute speed is much much improved. (read as: nano seconds instead of milliseconds ) I documented it quite well so if you want you can easily browse it and change it the way you want. Now you can use in both GUIGetMsg() loop mode or event mode. No longer setting constants like before because it works perfectly in both mode. Cheer Remark: I don't include <WinAPI.au3> and <WinAPIShellEx.au3> in my UDF, because those UDF is very large and it will consume much more memory when you run (not matter you run the 'compiled' exe, the au3 file, or the .a3x file). In the CtrlHover UDF, i included a small subset of those UDF with the same name, so if you have already included <WinAPI.au3> or <WinAPIShell.au3>, be sure to edit the UDF and comment out the corresponding region. Edit 2: Reorganize script. Fix some issues when drag too fast. Add ability to handle "click" (work RIGHT as normal button, will not fire if you only release the mouse button upon the control as some UDF use MouseUp event) Add a helper method to check if MouseUp event is click event or not. Add compability function to call as normal UDF (with first letter is underscore). Edit 1: Add some function descriptions as JS's advice. Thank you I also changed script name (shorter) and modify the register function so it may be called with less parameter. From now on, the function name and calling syntax will be fixed. OK, I know there is the famous "GUICtrlOnHover" UDF already in this forum, and many people have used it and enjoyed it! But the UDF didn't work as I expected . So I wrote an UDF myself, as much simple as possible, and it works out of the box It has some advantages compare to the old GUICtrlOnHover.au3 It creates the normal button behavior. When you press primary mouse button in the control and begin to drag, it do not set other controls to "hover" state. Faster. I try to add 2k controls. When mouse change from one control to another, it only take about 25ms to handle. In idle state (mouse cursor is not over any control), the cost is ignorable with < 0.1ms. Compare with GUICtrlOnHover UDF takes about 3ms when mouse cursor is over the control, but in idle state, it takes about 35ms. (I do not know why) (That is, because I tested script with overlapped controls. GUICtrlOnHover rely on WinAPI function WindowFromPoint(), which return the first created control (the control with is overlapped any others), but my script rely on GUIGetCursorInfo() which return the last created control - which is the most nested control in Windows). So my script need to check entire 2k control, but GUICtrlOnHover return the first element. I will wait for information about GUIGetCursorInfo() to decide that my UDF should use WinAPI function instead of the native function. In the normal usecase and controls is not overlapped, my UDF is far faster. Edit: Add a setting constant, make you ability to choose use WindowFromPoint() or GUIGetCursorInfo(). Default to the WinAPI function) Faster time to create/ register control. Native AutoIt. No Callback. The only DllCall I use is to get parent window of a control. Wonder why AutoIt do not have a similar function. Found a new bug #2899. If someone can ad more functinal to WinGetHandle("[LAST]"), it should be great Edit: Use some other WinAPI call to provide workaround for issue with GUIGetCursorInfo. Smaller size, about 280 lines compare with about 400 lines of GUICtrlOnHover. More simple, more easy to use. No more than 120 characters in one line. No annoying jumping when scroll the UDF Support event mode to detect mouse down event. But it doesn't work with overlay control. So you cannot have a control (with event) over another control. (use $_BGUIGETCURSORINFOFIX const setting to get rid of this). It seems that it's a AutoIt bug, the GUIGetCursorInfo return a useless control id when controls overlapped. Its not the same with the control received with WindowFromPoint(), or the control which fire event (anyone can confirm it's a bug? Or it's a special feature? ) ( I open a new Trac Ticket here: #2900) Current limit: Mouse down Almost all mouse event is currently detected by timeout (this is why the script called Simple and Stupid, but every UDF I found in this forum also use this method). You can set a smaller timeout to catch the mouse, but sometimes its annoying. Edit: Default changed to 30ms timeout, it should be fast enough to detect any click! You can also change to use event mode to detect click better! Otherwise, it works like a charm. Try it and happy with it Example: Callback function #include "SSCtrlHover.au3" GUICreate(@AutoItVersion) $idLbl1 = GUICtrlCreateLabel("Label 1", 5, 5) SSCtrlHover_Register($idLbl1, "FnNormal", 0, "FnHover", 0, "FnActive", 0, "FnClick", 0) $idLbl2 =GUICtrlCreateLabel("Label 2", 5, 35) SSCtrlHover_Register($idLbl2, "FnNormal", 0, "FnHover", 0, "FnActive", 0, "FnClick", 5) GUISetState() While GUIGetMsg() <> -3 Sleep(10) WEnd Func FnNormal($idCtrl, $hWnd, $vData) ConsoleWrite(@CRLF & "Normal/Leave " & $idCtrl) EndFunc Func FnHover($idCtrl, $hWnd, $vData) ConsoleWrite(@CRLF & "Hover " & $idCtrl) EndFunc Func FnActive($idCtrl, $hWnd, $vData) ConsoleWrite(@CRLF & "Active " & $idCtrl) EndFunc Func FnClick($idCtrl, $hWnd, $vData) ConsoleWrite(@CRLF & "CLICK! " & $idCtrl & " - " & $hWnd & " - " & $vData) EndFunc You can use it with GUICtrlSetImage to provide a "hover button" effect Version 1: SSCtrlHover.au3 Version 3: SSCtrlHover.zip