Madza91 Posted July 3, 2009 Share Posted July 3, 2009 (edited) Hello, I know this question is asked many many times, but all answers on that questions aren't right solution for this... I have several example scripts for detecting click on TrayTip, but it's all bad solutions... Example 1: expandcollapse popup#include <Constants.au3> #include <GuiToolTip.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> Dim $iInterval = 8, $iInit Dim $iMSInterval = $iInterval * 1000 Dim $aWindows, $hShell_TrayWnd TrayTip('Title', 'Text', $iInterval) $aWindows = WinList('[CLASS:tooltips_class32]') $hShell_TrayWnd = WinGetHandle('[CLASS:Shell_TrayWnd]') For $i = 1 To $aWindows[0][0] If _WinAPI_GetParent($aWindows[$i][1]) = $hShell_TrayWnd And _ BitAND(_WinAPI_GetWindowLong($aWindows[$i][1], $GWL_STYLE), $WS_VISIBLE) Then ExitLoop EndIf Next $iInit = TimerInit() While TimerDiff($iInit) <= $iMSInterval If Not _GUIToolTip_ToolExists($aWindows[$i][1]) Then MsgBox(64, 'Notification', 'ToolTip was clicked') ExitLoop EndIf Sleep(50) WEndoÝ÷ ØLZ^Õ×yËlrXÓ¬î·^ÉbrJ'^Ú¶¶²¶*m«Z¨§±¬¬Ýý±ÉbrGnëpyÚ'ßÛgyçm«DÅ©©íºÚ"µÍYÕ^UØZ] ][ÝÕÝ ][ÝË ][ÝÐÛXÚÈYI][ÝË LJH[ÙÐÞ ][ÝÔÝ[ ][ÝË ][ÝÖ[ÝHÛXÚÙY] ÌÌÎÉ][ÝÊBQ^][ÙBÙÐÞ ][ÝÔÝ[ ][ÝË ][ÝÕ[YIÌÎNÜÈ ÌÌÎÉ][ÝÊB[YÚ[HBTÛY L BÑ[[ÈÕ^UØZ] ÌÍÜ×Õ^U]K ÌÍÜ×Õ^U^ ÌÍÚWÕ[YSÝ] ÌÍÚWÓÜ[ÛH BØØ[ ÌÍÚWÔ]X]Ú[ÙHHÜ ][ÝÕÚ[]SX]Ú[ÙI][ÝË BØØ[ ÌÍÚWÔÝ[Y ÌÍØUÚ[ÝÜË ÌÍÚÕ^U ÌÍØÐÛXÚÙYHY ÌÍÜ×Õ^U^H ][ÝÉ][ÝÈ[^U ][ÝÉ][ÝË ][ÝÉ][ÝËÌ B[ÙB ÌÍÚWÔÝ[YH[Y[] B^U ÌÍÜ×Õ^U]K ÌÍÜ×Õ^U^Ì ÌÍÚWÓÜ[ÛB ÌÍØUÚ[ÝÜÈHÚ[Ý ][ÝÖÐÓTÔÎÛÛ×ØÛÜÌÌI][ÝÊBÜ ÌÍÚVHHÈ ÌÍØUÚ[ÝÜÖÌVÌBY]S Ú[Ù]Ý]J ÌÍØUÚ[ÝÜÖÉÌÍÚVVÌWJKH[ ÌÍÚÕ^UH ÌÍØUÚ[ÝÜÖÉÌÍÚVVÌWB^]ÛÜ[Y^Ú[H]S Ú[Ù]Ý]J ÌÍÚÕ^U KH[ [YY ÌÍÚWÔÝ[YH È L ÌÍÚWÕ[YSÝ] JBÛY L BÑ[Y[YY ÌÍÚWÔÝ[YH È L ÌÍÚWÕ[YSÝ] H[ÛÛÛÛUÜ]J ][ÝÐÛXÚÙY] ][ÝÈ [È[YY ÌÍÚWÔÝ[YH [ÈÔB ÌÍØÐÛXÚÙYHB[ÙBÛÛÛÛUÜ]J ][ÝÓÝÛXÚÙY[ÙY ][ÝÈ [È[YY ÌÍÚWÔÝ[YH [ÈÔB^U ][ÝÉ][ÝË ][ÝÉ][ÝËL B ÌÍØÐÛXÚÙYH[Y[YÜ ][ÝÕÚ[]SX]Ú[ÙI][ÝË ÌÍÚWÔ]X]Ú[ÙJB] ÌÍØÐÛXÚÙY[[ÈÏOIÝ×Õ^UØZ] Very ugly way and has same mistake like Example 1 & 2... Edited July 6, 2009 by n3nE [quote name='dbzfanatic' post='609696' date='Nov 26 2008, 08:46 AM']This is a help forum not a "write this for me" forum.[/quote](Sorry for bad English) :) Link to comment Share on other sites More sharing options...
rover Posted July 5, 2009 Share Posted July 5, 2009 (edited) Hello, I know this question is asked many many times, but all answers on that questions aren't right solution for this... I have several example scripts for detecting click on TrayTip, but it's all bad solutions...n3ne you need to subclass the hidden parent window 'AutoIt v3' to get the custom WM_USER+1 callback message registered with the Notification Area toolbar for tray icon events. you want the NIN_BALLOONUSERCLICK and NIN_BALLOONTIMEOUT notifications (NIN_BALLOONTIMEOUT also sent if traytip close icon clicked). the drawback is subclassing... the SetWindowLong call can occasionally fails to subclass the AutoIt v3 hidden window. on one slow machine (old 1.4gig Athlon running XP) SetWindowLong will occasionally give 'Access is denied.' error. on my faster machines (2.2G Athlon, 2.6G P4) I can't get it to error at all, even running multiple instances. (multiple instances to check that subclassing worked for every instance) YMMV so test away see example script notes *** I see there is a problem with the traytip not appearing again when an instance sets a TrayTip when another instance is already displaying a traytip but that would have to be a windows issue. you could also use the messages TTM_ACTIVATE or WM_ACTIVATEAPP = True and WM_LBUTTONUP with Hi/Lo word lparam tooltip coordinates hittest to discriminate between a click on tooltip or close button (using GuiRegisterMsg or subclassing tooltip). but again, more workarounds... an alternative to subclassing the AutoIt v3 gui is to create your own tray icon with Shell_NotifyIconW API, handle the WM_USER+1 callback message with GuiRegisterMsg and check for the NIN_BALLOONUSERCLICK and NIN_BALLOONTIMEOUT notifications. Holgers ModernMenu UDF does this, but like customdrawn/ownerdrawn controls its more work. Cheers Edit: with further testing launching multiple instances I get 1 access denied in 20 to 30 instances on P4 and 3 or 4 access denied in 20 instances on Athlon creating a tray icon with Shell_NotifyIconW is best approach... Edit2: typos Edit3: found problem: example updated with ProgAndys AutoItWinGetHandle function Access denied error caused by using AutoItWinGetTitle with WinGetHandle to retrieve the AutoIt v3 window handle without first editing the title. sometimes you overlook the obvious... Edit4: added Return SetError(0, 0, 1) to _SubclassWin(), another typo expandcollapse popup;Author: rover 07/04/09 ;MSDN reference: ;Shell_NotifyIcon Function ;http://msdn.microsoft.com/en-us/library/bb762159(VS.85).aspx #include <GUIConstantsEX.au3> #include <Constants.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> #include <StaticConstants.au3> Global Const $NIN_BALLOONTIMEOUT = $WM_USER + 4 Global Const $NIN_BALLOONUSERCLICK = $WM_USER + 5 ;Global Const $GWLP_WNDPROC = -4; for SetWindowLongPtr Global $wProcNew = 0, $wProcOld = 0, $iMsg, $iError = 0 ;get handle to AutoIt v3 hidden gui Global $hGUI1 = _AutoItWinGetHandle() ;$hGUI1 = WinGetHandle(AutoItWinGetTitle()) ;will work without GUICreate but global vars must be set in WndProc instead of GUICtrlCreateDummy/GUICtrlSendToDummy ;NOTE: _WinAPI_SetWindowLong() in WinAPI.au3 consistently returns 'The specified procedure could not be found' error 127 ;error is due to the call being SetWindowLong instead of SetWindowLongW, ;using SetWindowLongW the error message is 'The operation completed successfully. Global $hGUI2 = GUICreate("Traytip click detect", 260, 150, @DesktopWidth - 400, @DesktopHeight - 300) Global $cTooltipClose = GUICtrlCreateDummy() Global $cTooltipClick = GUICtrlCreateDummy() Global $cLabel1 = GUICtrlCreateLabel("Traytip area clicked", 70, 80, 120, 16, $SS_CENTER) Global $cLabel2 = GUICtrlCreateLabel("", 10, 110, 240, 16, $SS_CENTER) GUICtrlSetBkColor(-1, 0xFFFFFF) Global $cButton = GUICtrlCreateButton("Create Traytip", 70, 30, 120, 25) GUISetState() ;subclass AutoIt v3 gui to get tray icon/traytip notifications _SubclassWin($hGUI1, $wProcNew, $wProcOld) Global $sLastError = _WinAPI_GetLastErrorMessage() ConsoleWrite('- GetLastErrorMessage ' & $sLastError & "- Error: " & _WinAPI_GetLastError() & @CRLF) ConsoleWrite('+$wProcOld = ' & $wProcOld & @CRLF) GUICtrlSetData($cLabel2, $sLastError) If StringInStr($sLastError, "Access is denied.") <> 0 Then GUICtrlSetBkColor($cLabel2, 0xFF0000) EndIf While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $cButton TrayTip("Clear", "", 1) TrayTip("I'm a title", "I'm the message", 5, 1) Case $cTooltipClick GUICtrlSetData($cLabel2, "") GUICtrlSetColor($cLabel2, 0x0000FF) Sleep(100) GUICtrlSetData($cLabel2, "Tooltip clicked") ConsoleWrite("!NIN_BALLOONUSERCLICK" & @CRLF) Case $cTooltipClose GUICtrlSetData($cLabel2, "") GUICtrlSetColor($cLabel2, 0xFF0000) Sleep(100) GUICtrlSetData($cLabel2, "Tooltip closed") ConsoleWrite("-NIN_BALLOONTIMEOUT" & @CRLF) Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _SubclassWin($hWnd, ByRef $hProcNew, ByRef $hProcOld) If $hProcNew <> 0 Or $hProcOld <> 0 Then Return SetError(1, 0, 0) $hProcNew = DllCallbackRegister("_AutoItWndProc", "int", "hwnd;uint;wparam;lparam") If @error Or $hProcNew = 0 Then Return SetError(2, 0, 0) $hProcOld = DllCall("User32.dll", "int", "SetWindowLongW", "hwnd", _ $hWnd, "int", $GWL_WNDPROC, "ptr", DllCallbackGetPtr($hProcNew)) If @error Or $hProcOld[0] = 0 Then $hProcOld = 0 Return SetError(3, 0, 0) EndIf $hProcOld = $hProcOld[0] Return SetError(0, 0, 1) EndFunc;==>_SubclassWin Func _RestoreWndProc($hWnd, ByRef $hProcNew, ByRef $hProcOld) If $hProcOld <> 0 Then _WinAPI_SetWindowLong($hWnd, $GWL_WNDPROC, $hProcOld) If $hProcNew <> 0 Then DllCallbackFree($hProcNew) $hProcNew = 0 $hProcOld = 0 EndFunc;==>_RestoreWndProc Func OnAutoItExit() _RestoreWndProc($hGUI1, $wProcNew, $wProcOld) EndFunc;==>OnAutoItExit Func _AutoItWndProc($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $iwParam, $ilParam Switch $iMsg Case $WM_USER + 1;AutoIt callback message value for tray icon (1025), can be retrieved with ReadProcessMemory and TRAYDATA struct Switch $ilParam Case $NIN_BALLOONTIMEOUT; timeout and by tooltip close icon GUICtrlSendToDummy($cTooltipClose) Case $NIN_BALLOONUSERCLICK GUICtrlSendToDummy($cTooltipClick) EndSwitch EndSwitch ; pass the unhandled messages to default WindowProc Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $iMsg, $iwParam, $ilParam) EndFunc;==>_AutoItWndProc ;=============================================================================== ; ; Function Name: _AutoItWinGetHandle ; Description:: Returns the Windowhandle of AutoIT-Window ; Parameter(s): -- ; Requirement(s): -- ; Return Value(s): Autoitwindow Handle ; Author(s): Prog@ndy ; ;=============================================================================== ; Func _AutoItWinGetHandle() Local $oldTitle = AutoItWinGetTitle() Local $x = Random(1248578, 1249780) AutoItWinSetTitle("qwrzu" & $x) Local $x = WinGetHandle("qwrzu" & $x) AutoItWinSetTitle($oldTitle) Return $x EndFunc;==>_AutoItWinGetHandle Edited July 5, 2009 by rover krasnoshtan 1 I see fascists... Link to comment Share on other sites More sharing options...
Madza91 Posted July 5, 2009 Author Share Posted July 5, 2009 Hello... This is good, but it doesn't work every time, I don't know why... It doesn't send notifications sometimes... I will see TTM_ACTIVATE notification tomorrow... Or some other solution, if you know something more, please post it... Thank you Rover! [quote name='dbzfanatic' post='609696' date='Nov 26 2008, 08:46 AM']This is a help forum not a "write this for me" forum.[/quote](Sorry for bad English) :) Link to comment Share on other sites More sharing options...
rover Posted July 5, 2009 Share Posted July 5, 2009 Hello... This is good, but it doesn't work every time, I don't know why... It doesn't send notifications sometimes...I will see TTM_ACTIVATE notification tomorrow... Or some other solution, if you know something more, please post it...Thank you Rover! problem solvedexample updatedIt's not a good idea to retrieve a handle from an unedited AutoIt v3 window titleas it will occasionally get the AutoIt v3 window of another AutoIt process with an unedited title.the thing is, I know this.but I don't often use it. cheers I see fascists... Link to comment Share on other sites More sharing options...
Madza91 Posted July 5, 2009 Author Share Posted July 5, 2009 (edited) I think this is right answer, rover fast as always, thank you Edited July 5, 2009 by n3nE [quote name='dbzfanatic' post='609696' date='Nov 26 2008, 08:46 AM']This is a help forum not a "write this for me" forum.[/quote](Sorry for bad English) :) Link to comment Share on other sites More sharing options...
rover Posted July 5, 2009 Share Posted July 5, 2009 I think this is right answer, rover fast as always, thank you Who? Me? I slept on this and got back to it this afternoonand it finally clicked.your welcome I see fascists... Link to comment Share on other sites More sharing options...
binarydigit0101 Posted November 1, 2010 Share Posted November 1, 2010 how can do i get the really code removing controls and form which appear? thank you! :-) ehi ehi ehi, what is your name? Link to comment Share on other sites More sharing options...
Kilmatead Posted July 19, 2012 Share Posted July 19, 2012 I realise resurrecting old threads is somewhat frowned upon, but Rover's code is still relevant, and this thread always appears prominent in search results.I'm having trouble getting this to run as an x64 EXE - it works fine when compiled to x86. For x64 all that was necessary (at least at first glance) was the use of SetWindowLongPtrW rather than the outdated SetWindowLongW, but AutoIt's _WinAPI_SetWindowLong() automatically takes care of this. (I rewrote some of the original code for my own sense of simplicity, but essentially its the same thing...)expandcollapse popup#include <Constants.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> Global Const $NIN_BALLOONTIMEOUT = $WM_USER + 4 Global Const $NIN_BALLOONUSERCLICK = $WM_USER + 5 TrayTip("To Click or Not to Click", "That is not the question", 12, 1) Global $Clicked = False Global $hGUI = _AutoItWinGetHandle() Global $hProcNew = DllCallbackRegister("_AutoItWndProc", "int", "hwnd;uint;wparam;lparam") Global $hProcOld = _WinAPI_SetWindowLong($hGUI, $GWL_WNDPROC, DllCallbackGetPtr($hProcNew)) While $hProcNew Sleep(100) WEnd MsgBox(0, "", "Death by Click = " & $Clicked) Func _AutoItWndProc($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $iwParam, $ilParam Switch $iMsg Case $WM_USER + 1 Switch $ilParam Case $NIN_BALLOONUSERCLICK $Clicked = True ContinueCase Case $NIN_BALLOONTIMEOUT _WinAPI_SetWindowLong($hGUI, $GWL_WNDPROC, $hProcOld) DllCallbackFree($hProcNew) $hProcNew = 0 EndSwitch EndSwitch Return _WinAPI_CallWindowProc($hProcOld, $hWnd, $iMsg, $iwParam, $ilParam) EndFunc Func _AutoItWinGetHandle() ; Author: Prog@ndy Local $oldTitle = AutoItWinGetTitle() Local $x = Random(1248578, 1249780) AutoItWinSetTitle("qwrzu" & $x) Local $y = WinGetHandle("qwrzu" & $x) AutoItWinSetTitle($oldTitle) Return $y EndFuncLike I said, compiled to x86 it works perfectly, but under x64 the "restore" call to _WinAPI_SetWindowLong (just before the DllCallbackFree) causes AutoIt to crash with Windows offering to close the programme. Up to that point, the subclassing works perfectly (the mouse-click event is detected fine), it's just the cleanup call that fails.I noticed that the current beta (3.3.9.4) has a crash-fix related to this ("Fixed #2176: DllCallbackRegister crash on x64") - except it continues to crash even when compiled using the beta, which leads me to think I may have missed something else.And, yes, I am aware that other solutions such as exist, but when adopting other people's code I prefer to at least have a snowball's chance of understanding how it works - for which Rover's simpler solution becomes self-evident. Ideas? Link to comment Share on other sites More sharing options...
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