How to subclass Windows Explorer's window - windows

I want to change color of listview of explorer.exe like this
I got the handle of listview window by GetTopWindow function and his family.
To subclass listview window of explorer.exe, I injected my dll code to explorer by following code.
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll,
dwExplorerListviewThreadId);
My dll is loaed by explorer.exe well.
And I subclassed the window procedure by SetClassLongPtr(for global subclass) in injected code.
SetClassLongPtr returns success but my subclass function(SubclassProc) receives only WM_CREATE WM_DESTROY and WM_MOVE messages. What's wrong? I expected to get WM_NOTIFY and NM_CUSTOMDRAW.

The problem is that this is not a ListView in the first place; it's instead using Microsoft's internal "DirectlUI" framework, which is used in several places in explorer. It doesn't use any of the Common Control messages such as NM_CUSTOMDRAW. There's pretty much no reasonable way to change the colors it uses.
(Also, generally it's best to use SetWindowLongPtr instead of SetClassLongPtr for subclassing a HWND: SetClassLong only changes the underlying template that is used for creating new windows, but may not end up changing any instances that were based on that. And you should not be using the same function - GetMsgProc - for both the hook callback and the subclass proc; they need to handle the message in different ways, the hook callback needs to call CallNextHookEx while the subclass proc needs to call CallWindowProc with the original wndproc. But none of this really matters since the control isn't a ListView in the first place...)

I think and suppose that the OS has special protections for the explorer.exe process, because otherwise it would be an easy target for malicious code or just applications that think they are more important than they actually are (if some people insist on putting back a shortcut on their desktop every time you start the application, imagine what they would do when they had this sort of access to explorer.exe - everything in the shell).
EDIT: I was intrigued by the question and did some more research, I think there is a more mundane reason, see http://blogs.msdn.com/b/oldnewthing/archive/2005/09/07/461912.aspx. (basically: explorer.exe is the window manager so doesn't know about message routing yet when it receives certain messages, which is why they can't be intercepted with message hooks).

Related

CPropertySheet app lauched with CreateProcess steals focus [duplicate]

I was investigating an issue related to losing focus and changing activation of windows. What I found was that if I create an invisible property sheet, the active/foreground window changes and so does the focus window. Here is some sample MFC code:
// ignore CAutoDeleter, just a template that calls "delete this " in PostNcDestroy()
CPropertySheet* pSheet = new CAutoDeleter<CPropertySheet>(_T("Test Sheet"));
CTestPage* pPage = new CAutoDeleter<CTestPage>();
pSheet->AddPage(pPage);
DWORD style = WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | DS_CONTEXTHELP;
// style |= WS_DISABLED; //does nothing to help
DWORD exStyle = 0;
//exStyle = WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE; // does nothing to help
pSheet->Create(AfxGetMainWnd(), style, exStyle); // adding
After the call to pSheet->Create(), the active/foreground/focus window has changed and the application window is on top. If I use Spy++ and look at the window that is created, it turns out that a property sheet is a DIALOG window class. I am assuming it has a different WNDPROC, of course. What is interesting, is if I create an invisible modeless dialog using, it does not exhibit the problem. If I create the invisible modeless dialog, the active/foreground/focus window remains the same.
I tried setting various flags as in the code snippet, but alas they did not have any discernible effect--I still had the flashing and activation non-sense.
I could get some improvement by setting and clearing a hook (WH_CBT) before and after pSheet->Create()--and then eating the activation messages. When I do that, I don't have the horrible flashing and my application window does not come to the top. However, the focus (and caret for windows that have carets) does go away from whichever window had it before the Create().
Does anyone know a way to keep the focus and activation unchanged when creating an invisible property sheet? (At some point, the property sheet may or may not be set visible. And, if the property sheet is invisible when being destroyed, it also causes the blinking and activation changes.)
I tried using the values returned in GetUIThreadInfo() to try and restore things after the call to Create(), but it causes some flashing as well.
I just want to know how to create an invisible Property Sheet which won't cause the active, foreground, and focus window to change.
Unfortunately the underlying API function PropertySheet calls SetForegroundWindow on the main property sheet dialog after creation. There's no easy way around this - your kludge with the WH_CBT hook is probably your best option.
Edit: As suggested by #stephen in the comments on this duplicate question, you may be able to prevent the activation/focus change using LockSetForegroundWindow.
I have been struggling with this same issue for weeks, with a similar project, where my main application launches a secondary EXE process to act as a server in an audio application (which needs to be a separate process to shield the application from plugin faults, and so it can be high priority for real-time audio processing).
My secondary EXE is a modeless CPropertySheet, for status and diagnostic display, but is intended to be launched hidden and in the background. However it was always stealing the activation from the main application on launch, regardless of what workarounds I tried (such as overriding OnWindowPosChanging).
I thought I was going to go mad, so I was very happy to find this question. The WH_CBT trick is useful, but I found while it prevented activation of the secondary EXE, it did not prevent deactivation of the main application.
But then I discovered an excellent solution, in the LockSetForegroundWindow API (available since Win2K) which I had never heard of before. Looks like it is intended for exactly this purpose, to disable the change of foreground activation and prevent peer processes from stealing it.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
It works very well to nullify the internal call to SetForegroundWindow that happens deep within the property sheet common control, and works equally well whether used in the main application before CreateProcess or in the secondary EXE. I chose the latter case, to wrap the property sheet creation:
LockSetForegroundWindow(LSFW_LOCK);
pSheet->Create(NULL, dwStyle, dwExStyle);
LockSetForegroundWindow(LSFW_UNLOCK);
This minimises the scope of the intervention and keeps the fix localised to the process that is the source of the problem. I hope this will save others from wasting as much time on this tedious issue as I did.

How do I test if my custom callback is set as the current procedure for a given window?

We have a kiosk mode application for Windows Mobile 5 that was going strong for a year at least in production. It uses window subclassing through the SetWindowLong windows API function to override the behavior of the taskbar to prevent users from ever leaving our application or other explicitly allowed applications.
My callback overrides the handling of a few window messages and calls the default handler for other messages. This is done by storing the previous function pointer returned by SetWindowLong, and using it inside of the new function by calling CallWindowProc on it.
Then we had to update the application to be compatible with Windows Mobile 6.5.3, and started having a bunch of problems. I followed this article to disable the bottom menu buttons which are new on 6.5. On a single application, it works fine and the menu respects my callback. As soon as the user opens up another application through ours, that window seems to be recreated, and I had to devise a mechanism to detect foreground window changes and then "resubclass" the window again.
In my code, I don't have control of when exactly this window is recreated, so my first attempt was to use the GetWindowLong function to obtain the current callback address and test it against my own function address. I learned the hard way that I can't just compare the values like that, since it does not always return the function pointer.
Because I'm not able to test if my method is the current handler that way, I end up sometimes setting my method as the handler, and the previous handler is also my own method (in this case, the window was not recreated and thus already had my method set). This results in an infinite loop, since my callback ends up calling itself indefinitely.
How can I know if my custom function is the one being used by a certain window, so that I can avoid this infinite recursion?
Don't use SetWindowLong(GWL_WNDPROC) to subclass a window. Use SetWindowSubClass() instead (like Raymond Chen said):
Subclassing Controls
Safer subclassing
Amongst providing safer subclassing semantics (such as allowing multiple subclasses at a time), it also allows you to associate user-defined data with each subclass. So you could use GetWindowSubclass() to check if you have already subclassed the window or not.
Or, you could simply keep track of whether or not you have already subclassed the window. A simple boolean variable will suffice. Once your subclass is in place, you MUST remove the subclass before the window is fully destroyed. So, for instance, when the subclass receives the WM_NCDESTROY message, you can remove the subclass and clear your boolean at the same time, and then the next time you see the window again your boolean will tell you that you need to subclass the window.
Send the custom message to window. Handle this message in your custom function to return some value that will indicate that it was your custom handler.. and so on.
if(SendMessage(hwnd, mymsg, 0, 0) != myvalue)
;// It's not your handler

How does DispatchMessage decide which WndProc to use?

I'm going through some code for an open source project and this is my first time dealing with a Win32 app (mostly did console stuff). I see that several functions within the code are windows procedures because they return LRESULT CALLBACK.
Is there something the programmer has to do to make sure DispatchMessage invokes the right WndProc or is DispatchMessage coded in a way that it can determine the right WndProc all on its own?
EDIT:
I'm guessing that the way DispatchMessage(const MSG*) chooses between different WndProc's in an application is based on the window handle member (HWND) of the MSG object passed to it.[Hope previous sentence wasn't too confusing.] If the message was for the edit window for an application, for example, (and not for its main window,) then DispatchMessage will choose the WndProc member function for the particular class for which the edit window is an object of. If the message was for the main window, then it would choose the WndProc member function for the class that the main window is an object of (for me, this class would be the Notepad_plus_Window class). This is only a thought, though. I haven't found much to back it up so I'd be glad if anyone could confirm this.
Yes you are right, it uses MSG.hwnd to send the message to the correct window. One thing to be noted, it will use the WndProc associated with the window, not the window class. A window is an instance of a window class.
This article of Microsoft's "Under The Hood" illustrates this with rather detailed pseudo-code of DispatchMessage() that might be worth taking a look as well )

Is it possible to tell Scintilla to ignore certain keystrokes and pass them to the parent window?

I would like Scintilla to ignore certain key combinations like, Ctrl+Enter or Ctrl+D, and to notify the parent window when they are entered. I read through the documentation and could not figure out how to do this. Is this possible?
Well, if all else fails you could subclass the Scintilla control's window procedure. It would be fairly straightforward to intercept the WM_KEYDOWN and WM_KEYUP messages, filter them, and then pass them either to the main Scintilla window proc or to your parent window.
There are two options, really. Hooking into WM_KEYDOWN, as suggested, is one. The other is to use an accelerator table (see http://msdn.microsoft.com/en-us/library/ms645526(VS.85).aspx) to translate the keypresses into higher-level command IDs and process the command IDs in your WM_COMMAND handler.
Using the accelerator table is undoubtedly the "right" way, but WM_KEYDOWN seems to work just as well, and doesn't require changing the message loop code/tracking down the magic framework function that needs to be overridden/etc.
(If using MFC, the magic framework function for window-specific accelerator tables is CWnd::PreTranslateMessage. Override it, call TranslateAccelerator in there (passing in the accelerator table that is loaded in the constructor/OnCreate/etc.) and return FALSE -- if TranslateAccelerator returned 0 -- or TRUE -- if it returned something else. This allows the use of keyboard shortcuts that are specific to Scintilla windows.)
By the way, both these methods coexist quite happily, so some keypresses can be handled with accelerators and some with WM_KEYDOWN. My last Scintilla program did this; I totally can't remember why, I'm afraid, but it certainly worked fine.

Win32 , WndProc, and parent-child windows

I'm developing in C code that uses the Win32 Api to create multiple windows.
I used createWindow twice - to create parent and child windows.
I have a message loop
while ( GetMssage (&msg, NULL,0,0)){
.
translate
dispatch
.
}
But I only get the WND_Proc function called once, instead of twice for each of the windows.
What am I doing wrong?
If I'm understanding your question correctly, you should expect your WndProc to receive a single WM_CREATE message for each window created of the window class for which the WndProc is registered.
Your WndProc will not receive a WM_CREATE for a window you create of a different class (like the standard Windows UI controls, for example), even if it is a direct child of a window of the WndProc's class. If you gave us some more specifics on what you are trying to accomplish we could provide suggestions or workarounds.
This question may also shed some more light on your situation.

Resources