tatane Posted March 16, 2015 Share Posted March 16, 2015 Hi, The title is not totally true. I'm getting trouble to intercept close message on external GUI before execution. I mean, I can detect it with _WinAPI_RegisterWindowMessage and $HSHELL_WINDOWDESTROYED (snippet below) but the Message is already gone and proceed. Because of that, I can't get the ClassName of the external GUI closed. I would like to check the ClassName before executing my code to be sure my function is proceeded on the right GUI. The GUIs i'm watching are all from the same exe (uvnc.exe) but they can be child of my GUI or not. How can I get the ClassName of the closing GUI ? expandcollapse popup#include <WinAPIProc.au3> #include <WinAPI.au3> #include <WinAPISys.au3> #include <Array.au3> #include <GUIConstants.au3> #include <APISysConstants.au3> $gui = GUICreate("test", 1024, 768, 0, 0, BitOR($WS_MINIMIZEBOX, $WS_SYSMENU, $WS_CAPTION, $WS_EX_COMPOSITED)) $pos_x = 0 GUIRegisterMsg(_WinAPI_RegisterWindowMessage('SHELLHOOK'), 'WM_SHELLHOOK') _WinAPI_RegisterShellHookWindow($gui) GUISetState(@SW_SHOW, $gui) For $i = 1 To 3 $run = Run("notepad.exe") $hwnd_array = _WinAPI_EnumProcessWindows($run, False) If Not @error Then _WinAPI_SetWindowLong($hwnd_array[1][0], $GWL_EXSTYLE , $WS_EX_MDICHILD) _WinAPI_SetParent($hwnd_array[1][0],$gui) _WinAPI_SetWindowLong($hwnd_array[1][0], $GWL_HWNDPARENT, $gui) _WinAPI_SetWindowPos($hwnd_array[1][0], $HWND_TOP, $pos_x, 0, 200, 200, $SWP_FRAMECHANGED) $pos_x = 210 * $i EndIf Next Run("notepad.exe") While 1 $nMsg = GUIGetMsg() Select Case $nMsg = $GUI_EVENT_CLOSE _WinAPI_DeregisterShellHookWindow($gui) Exit EndSelect Sleep(100) WEnd Func WM_SHELLHOOK($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg Switch $wParam Case $HSHELL_WINDOWDESTROYED ConsoleWrite('Destroyed: ' & @CRLF & _ @TAB & 'PID: ' & WinGetProcess($lParam) & @CRLF & _ ; This will be -1. @TAB & 'ClassName: ' & _WinAPI_GetClassName($lParam) & @CRLF & _ ; This will be empty. @TAB & 'hWnd: ' & $lParam & @CRLF) ; This will be the handle of the window closed. EndSwitch EndFunc ;==>WM_SHELLHOOK Link to comment Share on other sites More sharing options...
mpower Posted March 16, 2015 Share Posted March 16, 2015 (edited) Just an idea but you can also intercept $HSHELL_WINDOWCREATED or $HSHELL_WINDOWACTIVATED and store the Class as well as the $lParam in an array. When the window is destroyed you can do an array lookup based on $lParam of the destroyed window and match to a class. That's how I would go about it. Edited March 16, 2015 by mpower Link to comment Share on other sites More sharing options...
binhnx Posted March 16, 2015 Share Posted March 16, 2015 You should not want to use RegisterShellHookWindow because: [This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.] - From MSDN The callback function is called when everything with your window is done. Your callback function is called also when the window is hidden but not destroyed. You may want to use a CBT Hook 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code! Link to comment Share on other sites More sharing options...
tatane Posted March 16, 2015 Author Share Posted March 16, 2015 (edited) Thanks for your answers. Both are interesting. I would like to test CBT Hook but it seems after some research on the forum that I have to use a dll (hook.dll). Is there a way to use this function without a dll (for global hook) ? EDIT : The explication of the required dll : https://msdn.microsoft.com/en-us/library/ms644960%28v=vs.85%29.aspx Edited March 16, 2015 by tatane Link to comment Share on other sites More sharing options...
binhnx Posted March 16, 2015 Share Posted March 16, 2015 Ah sorry, I forget your question is about an external process so a dll is required. I have no other idea now. Maybe some kind of WMI query may help, but I don't know anything about those. Maybe a WMI guru in this forum? btw, if you can accept a dll, then a small one which only catch event and dispatch it to your AutoIt app (send message to your window so you can intercept it) should be the most simple solution 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code! Link to comment Share on other sites More sharing options...
LarsJ Posted March 17, 2015 Share Posted March 17, 2015 You may do it with the UI Automation framework. See first example in post 112. binhnx 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
binhnx Posted March 17, 2015 Share Posted March 17, 2015 Aaaahhhhhh, so great LarsJ. I totally have no idea about this framework! Its just awesome. 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code! Link to comment Share on other sites More sharing options...
tatane Posted March 17, 2015 Author Share Posted March 17, 2015 (edited) Your work is impressive !!! It detects the close event but I don't get the handle/pid of the closed window even if I remove the If $iEventId <> $UIA_Window_WindowClosedEventId Then. I suppose it can't because the window is already closed ? Edited March 17, 2015 by tatane Link to comment Share on other sites More sharing options...
LarsJ Posted March 17, 2015 Share Posted March 17, 2015 You are probably right. Then you simply have to keep track (including ClassName) of your open uvnc-windows. When you receive a windows close event, you have to figure out, if it's one of your uvnc-windows. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
tatane Posted March 17, 2015 Author Share Posted March 17, 2015 So do you think it's "better" to use "RegisterShellHookWindow" or your UI Automation Framework ? Link to comment Share on other sites More sharing options...
LarsJ Posted March 17, 2015 Share Posted March 17, 2015 Definitely RegisterShellHookWindow Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
mpower Posted March 17, 2015 Share Posted March 17, 2015 Basically the best way is: Link to comment Share on other sites More sharing options...
tatane Posted March 18, 2015 Author Share Posted March 18, 2015 Actually, I'm already storing the PID and handle of uvnc windows I open in an array. And I check if the PIDs in my array exists as soon as I detect a $HSHELL_WINDOWDESTROYED. The only (small) problem is that my checking function is called each time a window is destroyed that's why I wanted to check the CLASS before. But it's not a big deal, my array is small. Anyway, thanks for your time. 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