Tide Gu
Tide Gu

Reputation: 835

Global Hook for Window creation/maximise/minimise etc in C#

I want to monitor any window is created globally. The closest API I found is SetWinEventHook on EVENT_OBJECT_CREATE, however, it not only hooks window creation but also controls. I wonder if there is any way that does not cost too much, and can hook not only CBT windows.

I tried to use IsWindow() to detect if the callback hwnd is a window hwnd, but it seems always return true regardless if the hwnd is a window or control.

I would prefer using managed api rather than adding other dlls, although if it is absolute necessary it is still an open option.

Lastly, how can I hook the windows maximise, minimise and restore events? Tried EVENT_OBJECT_STATECHANGE but it seems not the correct one. Tried EVENT_SYSTEM_MOVESIZESTART and EVENT_SYSTEM_MOVESIZEEND but also not capturing the max/min/restore events.

Partial code can be seen as follows:

private List<IntPtr> _hooks;
private User32ex.WinEventDelegate _delegate;

private void StartService() {
    _delegate = WinEventProc;
    _hooks.Add(User32ex.SetWinEventHook(User32.WindowsEventHookType.EVENT_OBJECT_CREATE, User32.WindowsEventHookType.EVENT_OBJECT_DESTROY, IntPtr.Zero, _delegate, 0, 0, User32.WindowsEventHookFlags.WINEVENT_OUTOFCONTEXT));
    // Other hooks
}

private void WinEventProc(IntPtr hWinEventHook, User32.WindowsEventHookType eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) {
    if (hwnd == IntPtr.Zero || !User32.IsWindow(hwnd)) return;

    switch (eventType) {
        case User32.WindowsEventHookType.EVENT_OBJECT_CREATE:
            Debug.Print($"Create:  {hwnd}");
            // Do something - here captures all objects not only windows but also controls etc
            break;
        case User32.WindowsEventHookType.EVENT_OBJECT_STATECHANGE:
            Debug.Print($"State change: {hwnd}");
            // Do something
            break;
        // Other cases
    }
}

Many thanks in advance!

Upvotes: 2

Views: 1432

Answers (1)

rs232
rs232

Reputation: 1317

Welcome to the beautiful world of Windows API! The reason your hook hooks not only "windows", but also "controls" is that in Windows both "windows" and "controls" are just windows. There might be different kinds of windows they might look different and behave differently; controls are just windows with specific looks and specific behaviours.

Since all of them just windows, you can't just hook to "windows" not hooking to "controls" at the same time. However, when you already hooked to one, you may identify if the window you've hooked to is the kind of window you would like to hook. As suggested in the comments, you may use window styles:

// this is a pretty crude and basic way to sort out "controls"
BOOL isControl_KindOf = GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD;

Upvotes: 2

Related Questions