I am thankfull to Jim Barry and Brian Ross. Both helped me in writing this
article. Actually the solution provide by me is the Solution provided by Jim Barry.
Jeffrey Richter in his book Windows 95 A Developer's Guide says:
Microsoft Windows supplies a number of ready-to-use window classes, including
listboxes, comboboxes, and scrollbars. These controls are intended to be general
and feature-laden enough for use in any application. Sometimes, however, you may
wish that these controls had slightly different behavior.
One solution to this problem is to design your own control from scratch. This
task is usually significant; however, it would be nice if the source code to the
Windows built-in controls was freely available. Unfortunately, Microsoft does
not distribute these sources. So we must take a different approach to this problem. Window subclassing and superclassing come to the rescue here and save us
from reinventing the wheel.
Subclassing and superclassing can also be used on your own window classes,
including application windows and custom controls that you create. However,
using subclassing and superclassing on your own code is usually not necessary
because you have easy access to your own source code and you can easily modify
your own source code to do exactly what you desire.
We achieve subclassing by replacing the address of that window's
that we must be a part of the process that created the window. There are numerous
method to get in to any process address space, like the
\HKLM\Software\Microsoft\Windows\AppInit_Dll (for NT only) or Hooks.
At this time most of the API functions have ANSI and UNICODE versions. For
#define GetWindowTextLength GetWindowTextLengthW
#define GetWindowTextLength GetWindowTextLengthA
So if our application is ANSI
GetWindowTextLenghtA will be used otherwise
GetwindowTextLengthW will serve us.
Once we get into address space of our desire process. We use
replace the original WndProc, that will return us original
WndProc address in
response. Latter we can use that address to pass messages to original WndProc
with the help of
Kyle Marsh in his article Safe subclassing in Win32 says:
The value returned from
GetClassLong may not be a pointer
to the previous window procedure at all. Win32 may return a pointer to a data
structure that it can use to call the actual window procedure. This occurs in
Windows NT™ when an application subclasses a Unicode™ window with a
non-Unicode window procedure, or a non-Unicode window with a Unicode window
procedure. In this case, the operating system must perform a translation between
Unicode and ANSI for the messages the window receives.
CallWindowProc() is supposed to help us with ANSI/UNICODE. But
it never does.
From here begins my story.
For some reason I came to the decision that I should subclass the Windows
Explorer window. I did that with the help of
I use same code over Win9x and NT/2k. On NT/2K I faced a strange problem of
having the wrong window title. After subclassing that subclassed explorer window
display its title is single letter i.e. "Exploring System (C:)" is
"E". I checked the
WM_SETTEXT message it receives correct text in lParam.
I start searching for help as I could not figure it out by myself. I posted
questions to Microsoft news groups. A guy name Jim Barry helped me by saying:
This is a Unicode issue. There seems to be a bug in Explorer that prevents
mixed ANSI/Unicode subclassing from working properly. Having spent many long
hours solving this problem, I can tell you there is only one solution. When
subclassing the Explorer window, first check if the window is Unicode by
IsWindowUnicode. If it is Unicode, then install a Unicode wndproc
SetWindowLongW. If it is ANSI, then install an ANSI wndproc using
SetWindowLongA. You need to have your ANSI wndproc forward to Explorer's
CallWindowProcA, whereas your Unicode wndproc should use
CallWindowProcW. It's a right pain having to provide two wndprocs, but there
So I change my code to
pfnWndProc = (WNDPROC)SetWindowLongW(hwndToExplorer, GWL_WNDPROC,
pfnWndProc = (WNDPROC)SetWindowLongA(hwndToExplorer, GWL_WNDPROC,
lResult = CallWindowProcW((WNDPROC) (DWORD)pfnWndProc, hwnd,
uMsg, wParam, lParam);
lResult = CallWindowProcA((WNDPROC) (DWORD)pfnWndProc, hwnd,
uMsg, wParam, lParam);
Hence I got the what I want to.
Errors and Omissions are expected/accepted :)
Mumtaz Zaheer is working as Senior System Analyst with Information Architects, Pakistan (http://www.info-architects.com/).