如何在Win32上创建新窗口时收到通知?

时间:2009-06-21 21:08:45

标签: winapi user32

有没有办法使用Win32,在创建新窗口时注册通知。我正在尝试保留当前打开的窗口列表,但现在只使用EnumWindows()轮询当前窗口列表。

有人做过类似的事吗?

由于


我不确定我是否正确行事,但我无法启动SetWindowsHookEx方法。

有什么想到的吗?

这是我的剪辑

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll")]
private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
const int HSHELL_WINDOWCREATED = 1;

private static HookProc winDelegate = ShellHookProcDelegate;
internal static void RegisterWindowCreatedEvent()
{
    SetWindowsHookEx(HookType.WH_SHELL, winDelegate, IntPtr.Zero, 0);
}

private static int ShellHookProcDelegate(int code, IntPtr wParam, IntPtr lParam)
{
    if (code != HSHELL_WINDOWCREATED)
    {
        return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
    }

    //App specific code here

    return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}

5 个答案:

答案 0 :(得分:12)

使用SetWindowsHookEx设置WH_SHELL挂钩并查找HSHELL_WINDOWCREATED事件。

答案 1 :(得分:2)

当然 - 你可以写a CBT hook并注意HCBT_CREATEWND。另见SetWindowsHookEx()


请注意,这将允许您在创建的窗口甚至完全初始化之前收到所有窗口创建的通知。如果你所需要的只是无主,那么顶级窗口,RichieHindle's suggestion可能会更好......

答案 2 :(得分:0)

Detours将允许您将钩子附加到任意Win32函数。但是,轮询可能是解决问题的一种更可靠的方法:您不必担心是否错过了特定的窗口创建方法(Win32中有多少个?我打赌不止一个!),当然,你不会在运行时重写Windows功能的机器代码

但是,你知道,你的电话。

答案 3 :(得分:0)

您可以尝试使用WinEventHook库来获取autohotkey。 尝试使用以下内容修改记事本弹出窗口阻止程序example

HookProc( hWinEventHook, Event, hWnd, idObject, idChild, dwEventThread, dwmsEventTime ) { if Event ; EVENT_SYSTEM_FOREGROUND = 0x3 {
WinGetTitle, title, ahk_id %hWnd% If (title = "your_window_name" msgbox, your window has been created } }

答案 4 :(得分:0)

以下是一些基于UI automation events的代码。它提供了打开,关闭和集中显示事件的窗口。

C#

[STAThread]
public static void Main(string[] args)
{
    Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, (sender, e) =>
    {
        var element = (AutomationElement)sender;
        var name = element.Current.Name;
        Console.WriteLine("open: " + name + " hwnd:" + element.Current.NativeWindowHandle);
        Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, element, TreeScope.Element, (s, e2) =>
        {
            Console.WriteLine("close: " + name + " hwnd:" + element.Current.NativeWindowHandle);
        });
    });

    Automation.AddAutomationFocusChangedEventHandler((sender, e) =>
    {
        var element = (AutomationElement)sender;
        var name = element.Current.Name;
        Console.WriteLine("focused: " + name + " hwnd:" + element.Current.NativeWindowHandle);
    });
    Console.ReadLine();
    Automation.RemoveAllEventHandlers();
}

相当于C ++:

#include <windows.h>
#include <stdio.h>
#include <uiautomation.h>

// some useful macros
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)

#define SBTRACE wprintf
#define CHECKHR(expr) {hr=(expr);if(FAILED(hr)){ SBTRACE(L"HR FAILED line:%u file:%s\n", __LINE__, __WFILE__); goto cleanup; } }  
#define CHECKWIN32(expr) {if(!(expr)){hr = HRESULT_FROM_WIN32(GetLastError()); SBTRACE(L"WIN32 FAILED line:%u file:%s\n", __LINE__, __WFILE__); goto cleanup; } }  
#define CHECKARG(expr) {if(!(expr)){ SBTRACE(L"ARG FAILED line:%u file:%s\n", __LINE__, __WFILE__); hr = E_INVALIDARG; goto cleanup; } }  
#define CHECKMEM(expr) {if(!(expr)){ SBTRACE(L"MEM FAILED line:%u file:%s\n", __LINE__, __WFILE__); hr = E_OUTOFMEMORY; goto cleanup; } } 
#define CORELEASE(expr) {if(expr){ expr->Release(); expr = NULL; } } 
#define HR HRESULT hr=S_OK;

class EventHandler :
  public IUIAutomationEventHandler,
  public IUIAutomationFocusChangedEventHandler
{
private:
  LONG _ref;
  IUIAutomation* _automation;
  HWND _hwnd;
  IUIAutomationElement* _sender;

public:
  EventHandler(IUIAutomation* automation, IUIAutomationElement* sender, HWND hwnd) :
    _ref(1),
    _automation(automation),
    _sender(sender),
    _hwnd(hwnd)
  {
    if (sender)
    {
      sender->AddRef();
    }
  }

  ~EventHandler()
  {
    CORELEASE(_sender);
  }

  // IUnknown
  ULONG STDMETHODCALLTYPE AddRef() { ULONG ret = InterlockedIncrement(&_ref); return ret; }
  ULONG STDMETHODCALLTYPE Release() { ULONG ret = InterlockedDecrement(&_ref); if (!ret) { delete this; return 0; } return ret; }
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppInterface)
  {
    if (riid == __uuidof(IUnknown))
    {
      *ppInterface = (IUIAutomationEventHandler*)this;
    }
    else if (riid == __uuidof(IUIAutomationEventHandler))
    {
      *ppInterface = (IUIAutomationEventHandler*)this;
    }
    else if (riid == __uuidof(IUIAutomationFocusChangedEventHandler))
    {
      *ppInterface = (IUIAutomationFocusChangedEventHandler*)this;
    }
    else
    {
      *ppInterface = NULL;
      return E_NOINTERFACE;
    }

    AddRef();
    return S_OK;
  }

  // IUIAutomationFocusChangedEventHandler
  HRESULT STDMETHODCALLTYPE HandleFocusChangedEvent(IUIAutomationElement* sender)
  {
    HWND hwnd = NULL;
    sender->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
    wprintf(L"Window focused hwnd:%p'\n", hwnd);
    return S_OK;
  }

  // IUIAutomationEventHandler
  HRESULT STDMETHODCALLTYPE HandleAutomationEvent(IUIAutomationElement* sender, EVENTID eventID)
  {
    HR;
    HWND hwnd = NULL;
    EventHandler* windowHandler;

    switch (eventID)
    {
    case UIA_Window_WindowOpenedEventId:
      sender->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
      wprintf(L"Window opened hwnd:%p\n", hwnd);

      // register for close on this window
      // we build a new handler, this is the only way to remember the hwnd (the close event doesn't have anything)
      windowHandler = new EventHandler(_automation, sender, hwnd); // implicit addref
      CHECKMEM(windowHandler);
      CHECKHR(_automation->AddAutomationEventHandler(UIA_Window_WindowClosedEventId, sender, TreeScope_Element, NULL, windowHandler));
      break;

    case UIA_Window_WindowClosedEventId:
      wprintf(L"Window closed hwnd:%p\n", _hwnd);
      CHECKHR(_automation->RemoveAutomationEventHandler(UIA_Window_WindowClosedEventId, _sender, this));
      Release(); // we release our own reference, 'this' we be deleted sometime when all COM references are gone. don't do 'delete this'!
      break;
    }

  cleanup:
    return hr;
  }
};

int main()
{
  HR;
  IUIAutomationElement* root = NULL;
  EventHandler* handler = NULL;
  IUIAutomation* automation = NULL;

  CoInitializeEx(NULL, COINIT_MULTITHREADED);
  CHECKHR(CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&automation));

  CHECKHR(automation->GetRootElement(&root));

  handler = new EventHandler(automation, NULL, NULL);
  CHECKMEM(handler);

  CHECKHR(automation->AddAutomationEventHandler(UIA_Window_WindowOpenedEventId, root, TreeScope_Subtree, NULL, handler));
  CHECKHR(automation->AddFocusChangedEventHandler(NULL, handler));

  wprintf(L"Press any key to stop listening for events.\n");
  getchar();

cleanup:
  if (automation != NULL)
  {
    automation->RemoveAllEventHandlers();
    CORELEASE(automation);
  }

  CORELEASE(handler);
  CORELEASE(root);
  CoUninitialize();
  return hr;
}