What's new

.NET Hooking Another Windows WndProc

Status
Not open for further replies.
Cakes

Cakes

お前はもう死んでいる
VIP
Retired
Mythical Veteran Platinum Record End of the Year 2017
Messages
20,705
Reaction score
20,272
Points
3,870
Sin$
-7
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 lowpro S7 Pro

Edit: there is some more information in this post.
 
Last edited:
lowpro

lowpro

Professional Abecedarian
Programmer Mythical Veteran Mr. Nice Guy
Messages
4,528
Reaction score
2,041
Points
725
Sin$
0
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.
 
Cakes

Cakes

お前はもう死んでいる
VIP
Retired
Mythical Veteran Platinum Record End of the Year 2017
Messages
20,705
Reaction score
20,272
Points
3,870
Sin$
-7
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.
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
 
XeClutch

XeClutch

Raised on 7S
Mythical Veteran Programmer Modder
Messages
3,690
Reaction score
2,459
Points
690
Sin$
7
If you say what you're trying to do it might be easier on us to come up with a solution.
 
Cakes

Cakes

お前はもう死んでいる
VIP
Retired
Mythical Veteran Platinum Record End of the Year 2017
Messages
20,705
Reaction score
20,272
Points
3,870
Sin$
-7
If you say what you're trying to do it might be easier on us to come up with a solution.
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:.
 
Last edited:
XeClutch

XeClutch

Raised on 7S
Mythical Veteran Programmer Modder
Messages
3,690
Reaction score
2,459
Points
690
Sin$
7
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:.
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.
 
Last edited:
Cakes

Cakes

お前はもう死んでいる
VIP
Retired
Mythical Veteran Platinum Record End of the Year 2017
Messages
20,705
Reaction score
20,272
Points
3,870
Sin$
-7
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.
Yeah, I feel you man. Gotta stay safe out here.
EDIT: I'll do some more research Thursday if you haven't figured it out by then. I'm just busy with work atm.
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.
 
WildeThing

WildeThing

Enthusiast
Messages
212
Reaction score
63
Points
130
Sin$
7
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:
2OaVVXD.png


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).
 
Cakes

Cakes

お前はもう死んでいる
VIP
Retired
Mythical Veteran Platinum Record End of the Year 2017
Messages
20,705
Reaction score
20,272
Points
3,870
Sin$
-7
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:
2OaVVXD.png


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).
Yeah, I was not able to get anywhere in regards to intercepting the Window messages. Thanks for the reply :smile:.
 
Status
Not open for further replies.
Top Bottom
Login
Register