You are on page 1of 3

Q) What is sub classing?

Subclassing describes the notion of providing an extra message handling routine for a particular
instance of a window. That extra message processing function is called in lieu of the normal message
handling function. Often, the normal function is actually a part of Windows itself. The new message
handler can delegate messages it isn't interested in to the original handler - in this way, you can use
subclassing very easily to make slight modifications to the functionality of a window.
Subclassing also mean writing your own derived classes when you're dispatching messages. Just
declare your message map appropriately and get on with it.
Subclassing is useful when you know that some part of Windows has the user interface you want,
but the Windows implementation doesn't quite do everything you'd like it to. You should subclass an
MFC class when you know it covers most of the task you set, but that some of its functionality needs
expanding or even, sometimes, eliminating.
It would be wonderful if you could intercept the Windows WM_CHAR, WM_KEYDOWN or
WM_KEYUP messages to snag the keys offered to the control before the control itself saw them. If
you saw a character you didn't like, you simply wouldn't offer it to the edit control. It's subclassing
that provides the capability of seeing messages destined for a window before the window sees them
itself.
Q) How to Sub class a control?
Ans) Derive a class from the control which needs to be subclassed. Using the Class Wizard add the
relevant messages which you want to give new behavior. Now got to the implementation file of the
new sub control and add the required behavior.

For example: Subclassing a Edit control to accept only inter values in the specified format ###-####-
##

// the following code in the WM_CHAR message.
// Make sure to add the code for accepting backspace and delete keys also.
void CSSNEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if((nChar >= '0' && nChar <= '9') || nChar == VK_BACK || nChar == VK_DELETE)
CEdit::OnChar(nChar, nRepCnt, nFlags);
}

Now in the dialogs OnInitDialog(...) function add the following code.

CEdit* pEdit = (CEdit*)GetDlgItem(IDC_SSN);
m_SSNEdit.SubclassWindow(pEdit->GetSafeHwnd());


Q) How to sub class in the SDK way?
All of the messages sent to a window are handed to the window procedure; there, they are either
handled directly or passed on to the default window procedure. The idea behind subclassing a
window, then, is to place your own function in between Windows and the normal window
procedure. You can watch for messages that interest you and react appropriately, while ignoring
messages that don't interest you at all.
To subclass a window, you'll need to get Windows to call your own message handling function,
instead of letting it call the window procedure normally associated with the window. Back in the old
SDK days, this was usually accomplished by using the Windows GetWindowLong() API. That function
would allow you to retrieve a pointer to the window procedure - a pointer to a function - for the
window you were interested in subclassing.
FARPROC pfnOldProc;
pfnOldProc = (FARPROC) ::GetWindowLong(hWnd, GWL_WNDPROC);
The first parameter to GetWindowLong() is the handle for the window which you'd like to subclass.
The GWL_WNDPROC constant identifies the window procedure. Now that you have a copy of the old
pointer for safe keeping, you can wire up your new procedure, which needs to be defined with the
appropriate parameters and return values so that Windows can both pass it the message data it
needs and obtain the return value it expects.
LRESULT CALLBACK MySubclasser(HWND hwnd, UINT msg, WPARAM wParam, LPA
RAM lParam)
{
switch (msg)
{
case WM_PAINT:
// painting code here
break;
default:
return (*pfnOldProc)(hwnd, msg, wParam, lParam);
}
return 0L;
}
You can set things up so that MySubClasser() is called for messages to the window by making a call
to ::SetWindowLong(), like this
::SetWindowLong(hWnd, GWL_WNDPROC, (LONG) MySubClasser);
::SetWindowLong() sets the window procedure for only one window instance, the subclassing
function is called only for a particular instance of the window, not for all windows of that class. You
can, on the other hand, really subclass things by using ::SetClassLong()in place of ::SetWindowLong().
::SetClassLong() uses GCL_WNDPROC instead of GWL_WNDPROC to identify the window procedure
pointer. Using this function means that every window of the class that you've identified will have its
behavior modified.
Whatever the quirks of the language, the semantics of using ::SetClassLong() are still slightly
different from the C++ definition of subclassing. In C++, subclassing means that you've created a
class that can be reused by any other part of your code. Windows SDK subclassing, either with
::SetWindowLong() or ::SetClassLong(), still means that you're changing a window or an existing class
- not basing a new class on an existing one.
Unsubclassing
When the window you've subclassed is destroyed, your subclass function won't be called anymore. It
should be able to perform its duty throughout the life of the window. If you've used::SetClassLong(),
your function will be called when any window of the subclassed type is called. This means that your
function must live forever - someone, someplace, might create such a window. If you can't figure out
how to code a function which lives forever, you'll need to unsubclass the object with a call to
::SetClassLong(). It's as simple as undoing what you did with ::SetClassLong() in the first place.
::SetClassLong(hWnd, GWL_WNDPROC, (LONG) pfnOldProc);

You might also like