Window Enumeration and Tracking Via Events lazarus / 34-Windows ---------------------------------------------------------------------- guest60499 · 2017-06-19 16:39 Hello, I'm asking here mostly because this is one of the best places I know of to ask WinAPI questions. I'm doing this in C++ but I can provide FreePascal code if it is imperative (I was considering switching because it might be easier to prototype with, anyway). Basically the issues I am having have to do with the poorly documented behavior of EnumWindows and the accessibility window event hooks (SetWinEventHook). For example when using EnumWindows with the checks below, I can (for the most part) enumerate all windows on the desktop that have some visible presence, whether or not they are minimized: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i LStyle := GetWindowLong(HWnd, GWL_STYLE);if LStyle and (WS_BORDER or WS_VISIBLE) <> (WS_BORDER or WS_VISIBLE) then  exit;Unfortunately with the advent of Windows 10 there are "background applications" which are most commonly Windows Store apps. If a compatible application is closed they will be suspended similar to an Android application's lifecycle. They will sometimes show up in the EnumWindows listing and match the given criteria despite having no interactable desktop presence (they are not minimized nor are they in the tray). I attempted to figure out if I could cross reference the process list and check for suspended applications (Task Manager seems to be able to tell) but wasn't able to find anything. Does anyone have any suggestions? With the accessibility hooks, I am interested in updates of the desktop, so I decided to hook the event range EVENT_OBJECT_CREATE to EVENT_OBJECT_DESTROY using SetWinEventHook. There are similar problems with this as with EnumWindows. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if not (event = EVENT_OBJECT_CREATE and        idObject = OBJID_WINDOW and      idChild = INDEXID_CONTAINER) then  exit; LStyle := GetWindowLong(HWnd, GWL_STYLE);if LStyle and (WS_BORDER) <> (WS_BORDER) then  exit;WS_VISIBLE is never set, even though it should be as far as I know, but this difference mostly doesn't matter. What does matter is that while simple applications like File Explorer windows will send EVENT_OBJECT_CREATE and EVENT_OBJECT_DESTROY lots of other applications do not, e.g. an already opened Windows Store app does not send these events when resumed or suspended, and multiwindow applications like Firefox do not send them when creating new windows. Does anyone have any suggestions? As far as I know the only relevant documentation is the documentation for the functions I am using, so any pointers are welcome. I've started Spy++ to try to investigate window properties that I could select based on, and this got me the values to use with EnumWindows, but the current issues are a nonstarter that I can't get around. If sample code would be helpful I can whip something up. Since I was mostly planning to do it anyway I will edit this when I get it done. Thanks in advance,      guest. ---------------------------------------------------------------------- guest60499 · 2017-06-22 15:37 Here is complete FreePascal compatible code. Run the program and launch e.g. a file explorer, you will see "File Explorer" printed. Per the original post some windows do not trigger an event. Does anyone know why? What should I be looking for? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program PTile; {$mode objfpc}{$H+}{$calling stdcall} uses  Classes, Windows; type  HWINEVENTHOOK = HANDLE;  WINEVENTPROC = procedure(    EventHook: HWINEVENTHOOK;    Event: DWORD;    HWnd: HWND;    IDObject, IDChild: LONG;    EventThread, EventTime: DWORD); const  WINEVENT_OUTOFCONTEXT = $0000;  EVENT_OBJECT_CREATE   = $8000;  EVENT_OBJECT_DESTROY  = $8001;  OBJID_WINDOW          = $0000;  INDEXID_CONTAINER     = $0000; function SetWinEventHook(  EventMin, EventMax: UINT;  HMod: HMODULE;  EventProc: WINEVENTPROC;  IDProcess, IDThread: DWORD;  Flags: UINT): HWINEVENTHOOK; external 'User32.dll'; function UnhookWinEvent(  EventHook: HWINEVENTHOOK): LongBool; external 'User32.dll'; function {%H-}EnumWindowsCallback(  {%H-}HWnd: HWND;  {%H-}LParam: LPARAM): LongBool;begin  Result := True;  WriteLn('.');end; procedure WinEventCallback(  {%H-}EventHook: HWINEVENTHOOK;  {%H-}Event: DWORD;  {%H-}HWnd: HWND;  {%H-}IDObject, {%H-}IDChild: LONG;  {%H-}EventThread, {%H-}EventTime: DWORD);var  Len: LongInt;  Title: array of WideChar;  LStyle: LONG;begin  if not ((Event = EVENT_OBJECT_CREATE) and          (IDObject = OBJID_WINDOW) and          (IDChild = INDEXID_CONTAINER)) then    exit;   Len := GetWindowTextLengthW(HWnd) + 1;  if Len - 1 = 0 then    exit;   SetLength(Title, Len);  GetWindowTextW(HWnd, @Title[0], Len);   LStyle := GetWindowLong(HWnd, GWL_STYLE);  if LStyle = 0 then    exit;   if (LStyle and WS_BORDER) <> WS_BORDER then    exit;   WriteLn(WideCharToString(@Title[0]));end; var  Message: TMsg;  EventHook: HWINEVENTHOOK;begin  Message := Default(TMsg);  EventHook := SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, 0,    @WinEventCallback, 0, 0, WINEVENT_OUTOFCONTEXT);   while GetMessage(Message, 0, 0, 0) do    DispatchMessage(Message);   if EventHook <> 0 then    UnhookWinEvent(EventHook);end.