Quote:
>Hello-
>I need to subclass a window created within MFC. I have no
>problem subclassing "normal" (non-mfc) windows using SetWindowLong().
>Everything works fine in the "normal" case.
>In the MFC my subclass procedure doesn't get any window messages.
>Wandering through the MFC source, it would seem that they're re-subclassing
>the window for thier own purposes.
>My question:
>How do I either
>a) subclass an MFC window in such a way that I'm guaranteed to get all the
> messages first
> -- or --
>b) let MFC know that there are certain messages I want dropped through to
> my subclass, and it should let them go (it appears in the MFC source
>that
> most messages get filtered off).
>Thanks,
>Derek
Well, a *lot* of the window subclassing you want to do is intrinsic in
the MFC architecture. For example, if you have a window class that
you want to subclass, just declare a class
class MyWindow : public CWnd { ...}
and if you use ClassWizard to do it, you'll get much of what
subclassing normally buys you. A phrase I love to use about MFC is
that the C++ object model is almost, but not quite, totally unlike the
Windows object model; the subclassing Microsoft does is an amazing
tour-de-force that makes these two nearly disjoint object models
cooperate.
Another case, let's say you want to subclass a listbox. Use
classWizard to declare your new class, essentially
class MyListBox : public CListBox {...}
Now for most of the events, you just use the ClassWizard to build
handlers for the events. Let's say this is in a dialog which you've
derived from CDialog. Use the ClassWizard to declare a variable of
the type MyListBox, let's say 'whatever', which will put the
following declaration in your .h file:
MyListBox whatever;
Once your dialog has initialized, you can use the MyListBox:: methods
(and even add your own cool methods to this class), and you will get
just about everything you need.
This works well for *almost* everything. Unfortunately, it is
sometimes necessary to really subvert the MFC mechanisms for authentic
"Windows" subclassing. This is only moderately tricky. I do
something like this:
add to your class definition
DWORD m_oldproc;
then add this function
void CMyListBox::subclass(WNDPROC proc)
{
m_oldproc = ::GetWindowLong(m_hWnd,
GWL_WNDPROC);
::SetWindowLong(m_hWnd, GWL_WNDPROC,
(DWORD)proc);
::SetWindowLong(m_hWnd, GWL_USERDATA,
(LPARAM)this);
}
Now your callback works like you'd expect....
static CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
lParam)
{
CMyListBox * object = (CMyListBox *)GetWindowLong(hWnd,
GWL_USERDATA);
....// do your usual window stuff here
return ::CallWindowProc(object->m_oldproc, hWmd, msg, wParam,
lParam);
}
Note that because you've stored the 'this' pointer in GWL_USERDATA,
you can now call methods of the class to do whatever you want while
working within the MFC structure.
But before you go through all of this, make sure that the ordinary MFC
subclassing isn't adequate for the job. I can do probably 99% of the
subclassing I need.
(At the risk of sounding commercial, I recently completed a book on
Win32 programming that has a CDROM with 150K+ lines of MFC examples
just full of neat tricks)
joe