tags:

views:

269

answers:

2

Hi all

I am implementing a small application (observer) that needs to "attach" itself to the bottom of another window (observed). The latter is not a window inside the application.

At this moment I solved by getting the hWnd of the window and querying periodically in a thread the location of the observed window, moving the observer window accordingly.

However this is a very inelegant solution. What I would like to do is to listen to the resize event of the observed window so that the observer will react only when necessary.

I assume I should use a hook, and I found plenty of ways of doing it, but my lack of knowledge of the C WinAPI is blocking me in understanding which hook I need to create and how (pinvoke/parameters/etc).

I'm pretty sure this is quite trivial, and some of you familiar with C/C++ and WinAPI will have the answer ready at hand ;)

Thanks

+1  A: 

A WH_CALLWNDPROC hook would probably suffice, this will allow you to monitor all messages destined for the window of interest.

Are you asking how to create a global hook using C# or are you happy to create the hook in C++ and then interop with that from .NET? The second option is the route I would go.

Basically off the top of my head, what I would do is the following

1- Create global hook in C, and export functions to InstallHook and UninstallHook, which can be called from your C# app using Interop. InstallHook take an hwnd of the window in your C# application.

2- Have the installed hook function post a custom message to the C# window provided in the call to InstallHook when ever there is a message you are interested in like WM_SIZE in your case.

3- In the C# application your window that receives the posted messages from the hook will override WndProc to handle the custom message.

That is an outline of one approach.

Chris Taylor
+2  A: 

Expanding on Chris Taylor's answer: Instead of doing the native interop yourself, you can use ManagedWinApi, which contains a Hook class.

EDIT: To use ManagedWinApi. Somewhere in your code:

Hook MyHook = new Hook(HookType.WH_CALLWNDPROC, false, false);
MyHook.Callback += MyHookCallback;
MyHook StartHook();

For the callback, reference CallWndProc and CWPSTRUCT:

private static int MyHookCallback(int code, IntPtr wParam, IntPtr lParam, ref bool callNext)
{
    if (code >= 0)
    {
        // You will need to define the struct
        var message = (CWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPSTRUCT));
        // Do something with the data
    }
    return 0; // Return value is ignored unless you set callNext to false
}
Daniel Rose
Indeed I stumbled upon ManagedWinAPi but the docs are not as self-explaining as I'd love too, seen my incompetence in the WinAPI. I am looking into the examples to get it.As far as I have understood, I do not really need a global system hoow as a direct hook to the window is sufficient. I just need to be notified about the resize/move events. Ideally this should happen in a C# event.What I need to figure out is how to connect the dots, therefore any suggestion is more than welcome, especially from people familiar with the ManagedWinApi.
Steve Vedovelli
@Daniel Thanks! That is very much clarifying. I will test it asap. For reference, CWPSTRUCT is here http://www.pinvoke.net/default.aspx/Structures/CWPSTRUCT.html
Steve Vedovelli
@Daniel, your suggested code hooks only to windows inside the C# project. I need to hook to an external window. Googling around I understood that this seems not possible in C#, unless Magadewinapi has a way to do this. I tried to set the global param in the Hook constructor to true, but I banged my session. Any suggestion?
Steve Vedovelli
@Steve The hook is for windows in the same application (they don't have to be C#-windows). As for cross-process hooks, I'm not sure exactly how this works together with "global" (didn't need it so far). You might also have problems in newer Windows-versions due to security...
Daniel Rose