Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to set a C++ member function as the WndProc?

59 views
Skip to first unread message

Allan Bruce

unread,
Mar 31, 2004, 12:32:38 PM3/31/04
to
How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a member
function, so that each instance of my class will have its own WndProc?
Thanks
Allan


Sten Westerback

unread,
Mar 31, 2004, 12:40:55 PM3/31/04
to

"Allan Bruce" <all...@TAKEAWAYf2s.com> wrote in message
news:c4evbk$mh3$1...@news.freedom2surf.net...

> How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a member
> function, so that each instance of my class will have its own WndProc?

By defining them in different processes. Why would you
like different functions for the class? Instead, after
creating a window using the class you can modify it's
wndproc pointer to your liking (called subclassing).

- Sten

Tim Robinson

unread,
Mar 31, 2004, 12:55:41 PM3/31/04
to

Use a static member function.

'But the compiler won't let me access this!' You need to stash the pointer
to the particular object (aka this) somewhere that you can retrieve it
later.

Or save yourself time and effort and use ATL's CWindow class.

For example: (there are other ways to do this, but this is simple, and
sufficient for most cases)

HWND Window::Create()
{
HWND hwnd = CreateWindow(..., this);
if (hwnd == NULL)
return NULL;

assert(hwnd == m_hWnd);
return hwnd;
}


/*static*/ LRESULT Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
Window *This;

if (msg == WM_NCCREATE)
{
CREATESTRUCT *cs = (CREATESTRUCT*) lParam;
This = cs->lpCreateParams;
SetProp(hwnd, "WindowInstancePointer", (HANDLE) This);
This->m_hWnd = hwnd;
}
else
This = (Window*) GetProp(hwnd, "WindowInstancePointer");

if (This == NULL)
{
// This can happen for messages such as WM_GETMINMAXINFO
// which are received before WM_NCCREATE.
// If you want to handle these properly, you'll need some other
// way of communicating 'this' to Window::WndProc
return DefWindowProc(hwnd, msg, wParam, lParam);
}
else
return This->WndProc(msg, wParam, lParam);
}


/*virtual*/ LRESULT Window::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
/* ... */
}

return DefWindowProc(m_hWnd, msg, wParam, lParam);
}


--
Tim Robinson (MVP, Windows SDK)
http://mobius.sourceforge.net/


Allan Bruce

unread,
Mar 31, 2004, 2:54:16 PM3/31/04
to

"Sten Westerback" <sten.westerback@NO_SPAMnokia.com> wrote in message
news:HoDac.12900$k4.2...@news1.nokia.com...

If you see the post I made just previous to this one - you will see what my
problem is.
Could you give me a pointer or two to look up in MSDN to get sublcalssing
working?
Thanks
Allan


Allan Bruce

unread,
Mar 31, 2004, 2:55:41 PM3/31/04
to

"Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message
news:c4f0mt$2i56ak$1...@ID-103400.news.uni-berlin.de...

> Allan Bruce wrote:
> > How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a
> > member function, so that each instance of my class will have its own
> > WndProc? Thanks
>
> Use a static member function.

I cant have a static member function - see me previous post to see my
problem.

>
> 'But the compiler won't let me access this!' You need to stash the pointer
> to the particular object (aka this) somewhere that you can retrieve it
> later.
>
> Or save yourself time and effort and use ATL's CWindow class.

even though I`m using C++, I am just using the basic win32 C calls, i.e.
RegisterClassEx(), CreateWindowEx(). Do you know of a solution using this
method?

Thanks
Allan


Tim Robinson

unread,
Mar 31, 2004, 3:04:32 PM3/31/04
to
Allan Bruce wrote:
>>> How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a
>>> member function, so that each instance of my class will have its own
>>> WndProc? Thanks
>>
>> Use a static member function.
>
> I cant have a static member function - see me previous post to see my
> problem.
[...]

From your other post:
>>> but the global gCW appears to be static so this doesnt work.

Read my last post in some more detail...

Jakob Bieling

unread,
Mar 31, 2004, 3:10:05 PM3/31/04
to
"Allan Bruce" <all...@TAKEAWAYf2s.com> wrote in message
news:c4f7nr$pkt$1...@news.freedom2surf.net...

>
> "Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message
> news:c4f0mt$2i56ak$1...@ID-103400.news.uni-berlin.de...
> > Allan Bruce wrote:
> > > How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a
> > > member function, so that each instance of my class will have its own
> > > WndProc? Thanks
> >
> > Use a static member function.
>
> I cant have a static member function - see me previous post to see my
> problem.

You can! Because:

> > 'But the compiler won't let me access this!' You need to stash the
pointer
> > to the particular object (aka this) somewhere that you can retrieve it
> > later.

In other words, the static function needs to find out for which window
the call is and forward it to the approriate class:

static LRESULT ChatWindow::WndProc_ (HWNd h, ...)
{
ChatWindow* cw = from_hwnd (h);
cw->WndProc (h, ...);
}

WndProc_ is static (and yes, you *can* use this) and forwards the call
to the correct non-static member function. This is pretty much what Tim
said.

hth
--
jb

(replace y with x if you want to reply by e-mail)


Allan Bruce

unread,
Mar 31, 2004, 4:22:09 PM3/31/04
to
> HWND Window::Create()
> {
> HWND hwnd = CreateWindow(..., this);
> if (hwnd == NULL)
> return NULL;
>
> assert(hwnd == m_hWnd);

what does the assert() do?

> return hwnd;
> }
>
>
> /*static*/ LRESULT Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam,
> LPARAM lParam)
> {
> Window *This;
>
> if (msg == WM_NCCREATE)
> {
> CREATESTRUCT *cs = (CREATESTRUCT*) lParam;
> This = cs->lpCreateParams;
> SetProp(hwnd, "WindowInstancePointer", (HANDLE) This);
> This->m_hWnd = hwnd;
> }
> else
> This = (Window*) GetProp(hwnd, "WindowInstancePointer");
>
> if (This == NULL)
> {
> // This can happen for messages such as WM_GETMINMAXINFO
> // which are received before WM_NCCREATE.
> // If you want to handle these properly, you'll need some other
> // way of communicating 'this' to Window::WndProc
> return DefWindowProc(hwnd, msg, wParam, lParam);
> }
> else
> return This->WndProc(msg, wParam, lParam);
> }
>
>
> /*virtual*/ LRESULT Window::WndProc(UINT msg, WPARAM wParam, LPARAM
lParam)

why does this need to be virtual?
Thanks
Allan


Allan Bruce

unread,
Mar 31, 2004, 4:22:42 PM3/31/04
to

"Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message
news:c4f88g$2hoqf6$1...@ID-103400.news.uni-berlin.de...

> Allan Bruce wrote:
> >>> How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a
> >>> member function, so that each instance of my class will have its own
> >>> WndProc? Thanks
> >>
> >> Use a static member function.
> >
> > I cant have a static member function - see me previous post to see my
> > problem.
> [...]
>
> From your other post:
> >>> but the global gCW appears to be static so this doesnt work.
>
> Read my last post in some more detail...
>

I have read it and almost understand what you are doing. I replied to it
again.
Thanks
Allan


Tim Robinson

unread,
Mar 31, 2004, 4:51:27 PM3/31/04
to
Allan Bruce wrote:
>> HWND Window::Create()
>> {
>> HWND hwnd = CreateWindow(..., this);
>> if (hwnd == NULL)
>> return NULL;
>>
>> assert(hwnd == m_hWnd);
>
> what does the assert() do?

An assert is a way of documenting an assumption in a program's logic. If
that assumption is violated, you see a big message at run time.

For example:

int i = 3;
assert(i == 3);
i++;
assert(i == 4);

Assert statements are generally only compiled into debug builds, the
assumption being that any bug which results in an assert being fired would
have been discovered in a debug build, and that you don't want a release
build popping up messages saying that the program's broken.

[...]


>> /*virtual*/ LRESULT Window::WndProc(UINT msg, WPARAM wParam, LPARAM
>> lParam)
>
> why does this need to be virtual?

So that subclasses of the Window class can handle their own messages.
Window::WndProc would contain default processing which is shared by all
classes that derive from Window -- probably just a call to DefWindowProc.

You could implement a MyCrazyButton class, derived from Window, which
overrides WndProc. In there you might want to handle WM_PAINT,
WM_LBUTTONDOWN, etc. If Window::WndProc(UINT,WPARAM,LPARAM) was not virtual
then the static Window::WndProc(HWND,UINT,WPARAM,LPARAM) (note: two
functions with the same name but different parameters) would only ever call
Window's implementation of the function.

Allan Bruce

unread,
Mar 31, 2004, 4:57:37 PM3/31/04
to

"Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message
news:c4fegu$2if6rd$1...@ID-103400.news.uni-berlin.de...

Thanks Tim,
It is all working now.
Allan


Pete Vidler

unread,
Apr 1, 2004, 6:08:39 AM4/1/04
to
Allan Bruce wrote:
> How do I set my lpfnWndProc in a WNDCLASSEX structure to point to a member
> function, so that each instance of my class will have its own WndProc?
[snip]

Just FYI, there's a discussion of this issue that I have found very
useful here:

http://www.rpi.edu/~pudeyo/articles/wndproc/index.html

-- Pete

Jussi Jumppanen

unread,
Apr 2, 2004, 6:40:50 AM4/2/04
to
Allan Bruce wrote:

> > Use a static member function.
>
> I cant have a static member function - see me previous post to
> see my problem.

Tim is 100% correct. To do what you require WILL need to make
the member function static.

> > 'But the compiler won't let me access this!'

There is a reason for this, no pung intended :)

Consider the following simple class:

class example {
void dynamic_member(void);
static void static_member(void);
};

In the case of the dynamic_member() function what the compiler
is actually compiling is not the obvious:

void dynamic_member(void)
{
}

but instead it is coding something closer to the following:

void dynamic_member(example *this);
{
}

where it adds a hidden 'this' pointer.

In the case of the static_member() what you see is what you
get so in fact:

void static_member(void)
{
}

is coded exactly as expected.

But this explains why the compiler will generate a 'this'
error message for static functions.

> even though I`m using C++, I am just using the basic win32 C
> calls, i.e. RegisterClassEx(), CreateWindowEx(). Do you know
> of a solution using this method?

The problem has nothing to do with Win32 and everything todo
with how the c++ compiler handles static and non-static member
functions. The end result is for the code to compiler the
member function MUST be static.

Jussi Jumppanen
Author of: Zeus for Windows (All new version 3.92 out now)
"The C/C++, Cobol, Java, HTML, Python, PHP, Perl programmer's editor"
Home Page: http://www.zeusedit.com

0 new messages