.NET Hooking Another Windows WndProc

Discussion in 'Programming & Scripting' started by Cakes, Mar 21, 2017 with 8 replies and 1,347 views.

Thread Status:
Not open for further replies.
  1. Cakes

    Cakes Administrator Administrator

    Messages:
    20,664
    Ratings:
    17,717
    I'm working on a little application for fun, and have come to a standstill. Due to my limited experience with the Windows API and system-wide hooks in C#, I'm not entirely sure what steps to take next.

    My application can currently retrieve the hWnd (the window handle) of whatever window you focus on. When a window is maximized or minimized, that window's WndProc will send a WM_SYSCOMMAND (0x0112) Message with a WParam of SC_MAXIMIZE (0xF030). This indicates that the window was maximized. What I need to do is somehow hook the focused window's WndProc, and intercept messages that are sent and fire my callback when the expected messages arrive.

    I can currently monitor the WndProc messages for the above of my own application by overriding its default WndProc method:
    PHP:
    protected override void WndProc(ref Message message)
    {
        if (
    message.Msg == 0x0112// WM_SYSCOMMAND
        
    {
            if ((
    uint)message.WParam == 0xF030// SC_MAXIMIZE
            
    {
                
    // the window was maximized
            
    }
        }
        
    base.WndProc(ref message);
    }
    I believe hooking the foreign window's WndProc will be the way to go. However, I also believe I can use SetWindowsHookEx or SetWinEventHook from user32 to also achieve this. I currently am already using SetWinEventHook to capture the hWnd of a window when it becomes focused. I tried to use SetWindowsHookEx to do the same, but it seemed to be really hard to do in C#, so I went with SetWinEventHook instead.

    Any help would be appreciated.
    lowpro S7 Pro

    Edit: there is some more information in this post.
     
    Last edited: Mar 21, 2017
  2. lowpro

    lowpro Professional Abecedarian

    Messages:
    4,589
    Ratings:
    1,892
    Hmm haven't dealt much with Win API outside of specific instances,. But looking at SetWinEventHook, it looks like it's only C++ really, it might be easier just to reference a C++ file (see http://stackoverflow.com/questions/2211867/how-do-i-call-native-c-from-c). Using SetWinEventHook you should be able to use the Process ID as well, which might be easier, and could be a good replacement for the hack of hijacking your own WndProc haha.

    Also I honestly have only used python and debian this past year so I'm unfortunately a bit rusty, so let me know if I didn't read this right and am just talking out the *** lol.
     
    • Like Like x 2
  3. OP
    Cakes

    Cakes Administrator Administrator

    Messages:
    20,664
    Ratings:
    17,717
    They're supposed to be used in C++ for the "best" results, I guess, but you can use DLLImport to work with them in C#. For the most part anyway. SetWinEventHook worked for what I had tested it with, but SetWindowsHookEx was not working very well in C#, and all research I did on it said it would be very hard to use it in C#.

    I will look into that link you dropped though, maybe I can hack something together with SetWinEventHook after getting hWnd. I appreciate the response :3
     
    • Like Like x 1
  4. XeClutch

    XeClutch Contingency Dev

    Messages:
    3,676
    Ratings:
    2,131
    If you say what you're trying to do it might be easier on us to come up with a solution.
     
    • Informative Informative x 1
  5. OP
    Cakes

    Cakes Administrator Administrator

    Messages:
    20,664
    Ratings:
    17,717
    Apologies if I was unclear. I'll put some more detail below.

    Currently my application works like so. Upon clicking a button that starts the initial hook, this is fired (hhook is a global IntPtr so that I can unhook it on Form_Closing):
    Code:
    hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, procDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
    This allows my application to know whenever my foreground window has changed; when I've focused on a new window.

    SetWinEventHook is firing the following:
    Code:
    public static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        IntPtr wndProc = GetWindowLongPtr(hwnd, GWL.GWL_WNDPROC);
        if (IsZoomed(hwnd))
        {
            f1.log.Items.Add(string.Format("Hide: {0:x8}", hwnd.ToInt32()));
        }
        else
        {
            f1.log.Items.Add(string.Format("Restore: {0:x8}", hwnd.ToInt32()));
        }
    }
    IsZoomed is returning true if the hWnd is already maximized at the time of it being focused.

    According to what I read on P/Invoke, GetWindowLongPtr should be returning the pointer for the WndProc that belongs to the hWnd that was captured by SetWinEventHook. My issue now is that I don't know if this WndProc from GetWindowLongPtr is actually of any use. I couldn't really find anything that gave me a clear answer on how to hook that WndProc to read the messages being passed through it. As I said in my original post, I need to be able to fire a callback when WM_SYSCOMMAND is sent w/ a WParam of SC_MAXIMIZE (from that window's WndProc); I need to know when the focused window is being maximized.

    Hopefully this can bring some more light. Also, nice to see that you're still around :biggrin:.
     
    • Like Like x 1
    Last edited: Mar 21, 2017
  6. XeClutch

    XeClutch Contingency Dev

    Messages:
    3,676
    Ratings:
    2,131
    Code:
    IntPtr wndProc = GetWindowLongPtr(hwnd, GWL.GWL_WNDPROC);
    f1.log.Items.Add(string.Format((IsZoomed(hwnd) ? "Hide" : "Restore") + ": {0:x8}", hwnd.ToInt32()));
    Not quite what you're looking for but yeah, missed you too buddy lol. I try not to stick around for too long. Reminds me of some of the cringey 360 days. I try to stick to the hardware and software sections nowadays.

    EDIT: I'll do some more research Thursday if you haven't figured it out by then. I'm just busy with work atm.
     
    • Like Like x 1
    Last edited: Mar 22, 2017
  7. OP
    Cakes

    Cakes Administrator Administrator

    Messages:
    20,664
    Ratings:
    17,717
    Yeah, I feel you man. Gotta stay safe out here.
    Cool, I appreciate it. I'm going to work on it a little more tomorrow and see if I can figure anything out. You should check out www.pinvoke.net, it's got most of the documentation for working with the Windows API. Everything I've used so far is from user32.
     
  8. WildeThing

    WildeThing Enthusiast

    Messages:
    211
    Ratings:
    59
    I'm not 100% convinced this is actually possible.

    I was working on a small program that would change the WindowProc callback for target windows so that I could repaint the non-client area (window decorations) but the issue tends to be: I don't think Windows allows you to specify callbacks for Windows that your process doesn't own (and/or is in another thread context).
    I believe Windows refers to this type of hooking as "subclassing" a window, hence Windows allows you to subclass by creating a new callback and then, to manage ignored messages, handle them by returning Def(ault)WindowProc from your hook.

    Either way, MSDN is kinda idiotic when it comes to some of its documentation. For example, it replaced SetWindowLong w/ SetWindowLongPtr to support both architectures and, yet, failed to retain this information in the latter's documentation:
    [​IMG]

    I think you'll perhaps have to inject into the target process to do this.

    EDIT: I keep seeing you guys talking about C++, there is little C++ here. It's WinAPI (C).
     
  9. OP
    Cakes

    Cakes Administrator Administrator

    Messages:
    20,664
    Ratings:
    17,717
    Yeah, I was not able to get anywhere in regards to intercepting the Window messages. Thanks for the reply :smile:.
     

Share This Page

Thread Status:
Not open for further replies.