tags:

views:

324

answers:

5

Is there a way using Win32, to register for notifications when a new window is created. I'm trying to keep a list of current open windows, but am now just polling the list of current windows using EnumWindows().

Anyone done something similar?

Thanks

+2  A: 

Use SetWindowsHookEx to set up a WH_SHELL hook and look for the HSHELL_WINDOWCREATED event.

RichieHindle
+1  A: 

Sure - you can write a CBT hook and watch for HCBT_CREATEWND. See also SetWindowsHookEx().


Note that this will allow you to be notified of all window creation, before the windows being created are even fully initialized. If all you need are unowned, top-level windows, RichieHindle's suggestion may work better...

Shog9
A: 

Detours will permit you to attach hooks to arbitrary Win32 functions. However, polling is probably a more reliable way to approach the problem: you don't have to worry about whether you've missed a particular window-creation method (how many are there in Win32? I bet more than one!), and, of course, you won't be rewriting the machine code for windows functions at runtime.

But, you know, your call.

David Seiler
James would have to inject his Detours code into every GUI process, including new ones that were started. Windows hooks (via SetWindowsHookEx) are designed to do exactly what he wants, and are an official part of the Windows API.
RichieHindle
A: 

I'm not sure if I'm doing this right, but I'm not able to get the SetWindowsHookEx method to fire.

anything come to mind?

here is my snip

[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);
        }
James Hollister
Read the docs for SetWindowsHookEx() - you'll need to pass in a valid module handle for the DLL containing your hook procedure and of course your hook procedure will need to be implemented IN a DLL, as that DLL will then be injected automatically into all running threads on the desktop.
Shog9
There are whole bunch of requirements for getting hooks to work: your code has to live in a DLL (which will be injected into all GUI process by Windows itself) and will run in the context of the process creating the event. You need to store the handle returned by SetWindowsHookEx in a shared memory segment (which makes it visible to all processes) and pass it to CallNextHookEx. Whether it's even possible to do these things with C# I don't know - the CLR would need to be injected, which sounds very dodgy. This might be useful: http://stackoverflow.com/questions/820804
RichieHindle
And... It looks like you're using C# for this. Please see: http://stackoverflow.com/questions/24241/code-injection-with-c
Shog9
Hmmm, yea didn't realize that was how it worked. I'm thinking I'll just stick with my polling approach. Seems like a lot of added complexity to get the kind of effect I'm looking for.
James Hollister
A: 

You could try WinEventHook library for autohotkey. Try modifying the notepad popup blocker example with the following:

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 } }

Naveen