- Control Subclassing in C++
- Posted by Bill Holt on November 26th, 2003
Hi,
I'm currently building up my own framework for generic Win32 applications in
C++. It was based on the KWindow class in the book "Windows Graphics
Programming by Feng Yuan". I'm writing subclassing classes for the toolbar
control which is derived from KWindow.
Okay, here is the deal. C++ doesn't accept a non-static member function as a
callback window procedure. So, I used a little trick to store "this pointer"
by calling SetWindowLongPtr (m_hWnd, GWLP_USERDATA, (LONG_PTR) this); . Then
create a static DispatchProc which behaves like a callback procedure to
retrieve the pointer and calls the non-static WndProc to handle messages.
For subclassing controls, I used SetWindowLongPtr(m_hWnd,GWLP_WNDPROC,
(LONG_PTR) DispatchProc); to point the window to another callback procedure.
It worked fine for application defined windows. However when came to
controls, it won't work. If I do not set a new window procedure for the
control, it looks fine but with no message handling. If I set a new window
procedure, the message handling worked but the control looks empty(no
toolbar items are displayed).
I suspect whether the usage of SetWindowLong is correct. Could anyone help
me look into this problem?
Here is what KWindow look like:
class KWindow {
public:
HWND m_hWnd;
MWindow (void);
virtual bool CreateEx ( DWORD dwExStyle, LPCTSTR lpszClass,
LPCTSTR lpszName, DWORD dwStyle, int x, int y, int nWidth,
int nHeight, HWND hParent, HMENU hMenu, HINSTANCE hInst );
virtual LRESULT WndProc ( HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam );
static LRESULT CALLBACK DispatchProc ( HWND hWnd, UINT uMsg, WPARAM
wParam,
LPARAM lParam );
}
And the derived KToolbar
void KToolbar::CreateEx(......)
{
m_hWnd = CreateEx(.......)
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR) this);
SetWindowLongPtr(m_hWnd,GWLP_WNDPROC, (LONG_PTR) DispatchProc);
}
LRESULT CALLBACK KToolbar:
ispatchProc(...)
{
KToolbar* pToolbar;
pToolbar = ( KToolbar *) GetWindowLongPtr (hWnd, GWL_USERDATA);
return pToolbar->WndProc(...);
}
Any help will be appreciated.
Bill
- Posted by John Carson on November 26th, 2003
"Bill Holt" <mailbill@21cn.com> wrote in message
news:74e0d43f.0311260138.698ec43e@posting.google.c om
In calling
SetWindowLongPtr(m_hWnd,GWLP_WNDPROC, (LONG_PTR) DispatchProc);
you need to store the return value, which gives a pointer to the old window
procedure. You use this for default processing. Something like:
oldToolbarProc =
(WNDPROC)SetWindowLongPtr(m_hWnd,GWLP_WNDPROC, (LONG_PTR) DispatchProc);
Then in KToolbar::WndProc you need to call
CallWindowProc(oldToolbarProc...)
for those messages for which you want default processing. Essentially,
CallWindowProc plays the role that DefWindowProc plays in a regular window.
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)
- Posted by Bill Holt on November 26th, 2003
Well thank you very much, problem solved. I was probably confused with
a "DefaultProc" and a "OldProc".
"John Carson" <donaldquixote@datafast.net.au> wrote in message news:<3fc48340@usenet.per.paradox.net.au>...
- Posted by Ralf Buschmann on November 27th, 2003
On 26 Nov 2003 01:38:36 -0800, mailbill@21cn.com (Bill Holt) wrote:
Better use window properties (SetProp(), GetProp()) for such purposes.
For a window/common control you didn't create entirely yourself, you
can't be sure GWL_USERDATA isn't already used by the control.
Ralf.
- Posted by Thomas Hansen on November 27th, 2003
On 26 Nov 2003 01:38:36 -0800, there came a drop of sanity from
mailbill@21cn.com (Bill Holt) containing:
[snip]
Off course you should DROP your project and rather help me out on
http://smartwin.sourceforge.net
It's a (beggining to become mature) library that is trying to do the
same as you are...
But if you DON'T want to become a developer on SmartWin you could
probably read the code to get lots of good ideas...
--
http://smartwin.sourceforge.net THE template based Windows API GUI Library
My email:
"john.johnson@theJohnsons.com"
* Replace "john" with "thomas", replace "johnson" with "hansen", replace "theJohnsons" with "adramatch"
- Posted by Bill Holt on November 27th, 2003
Thanks Ralf, I went over to SetProp() and it worked fine.
To Thomas:
Well I'm flattered, but it's just I don't seem to be capable of such
projects. I've been reading the codings of SmartWin++ though, it helps
a lot, thanks.
- Posted by r_z_aret@pen_fact.com on December 2nd, 2003
On Thu, 27 Nov 2003 08:35:13 +0100, Ralf Buschmann
<caranthir2@dev_null.ge_em_iks.de> wrote:
The following comment from my code might provide a bit more info:
// TODO: Use extra window data, rather than user data (GWL_USERDATA)
to avoid
// clashes with users (see Tim Robinson,
comp.os.ms-windows.programmer.win32,
// 8 Aug 2001, "GWL_USERDATA or extra window memory?")
(This TODO: has been on my list since August 2001. It is low priority
because I'm the only programmer who "uses" my code, so clashes are
unlikely.)
-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).
Robert E. Zaret
PenFact, Inc.
500 Harrison Ave., Suite 3R
Boston, MA 02118
www.penfact.com
- Posted by Tim Robinson on December 2nd, 2003
<r_z_aret@pen_fact.com> wrote in message
news:3fcb5ddf.8698137@nntp.theworld.com...
Hurray! I'm famous! 
--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/