Discussion:
HOWTO req: subclassing multiple controls with same function
(too old to reply)
Jack
2008-03-30 17:22:35 UTC
Permalink
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).

I use the handle returned by the subclassing SetWindowLong() in the
subclassed procedure.

But when I create a second subclass on another editbox the returned handle
is different so the subclassed procedure gets confused (I presume).

How can I set things up so that I can use the same subclass procedure code?
I thought about saving each WNDPROC and passing it in each time the
subclass is called via a Sendmessage() return code but I presume there is a
cleaner way.

Will someone let me in on the secret? :) TIA.

PS do I have to unhook the procedure for each subclassed editbox when I exit
the popup dialog on which it resides or will things be cleaned-up
automatically on dialog exit?


~~~~~~~~~


With the first control I do this:

WNDPROC lpfnOrigEBGenericAmount ;

lpfnOrigEBGenericAmount = (WNDPROC) SetWindowLong (hWndEdit1, GWL_WNDPROC,
(LONG) EBSubclassGenericProcAmount);


LRESULT CALLBACK EBSubclassGenericProcAmount(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam){

switch (uMsg)

{

####

}

return CallWindowProc(lpfnOrigEBGenericAmount , hWnd, uMsg, wParam,
lParam);

}
Christian ASTOR
2008-03-30 17:39:21 UTC
Permalink
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
Use Superclassing.
Jack
2008-03-30 18:32:19 UTC
Permalink
Post by Christian ASTOR
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
Use Superclassing.
Hi,

Maybe a stupid question, but...

I create the edit controls using the dialog editor, not createwindow, how do
I superclass them? All the examples I have seen use createwindow() and
superclass there.
Norman Bullen
2008-03-30 19:33:56 UTC
Permalink
Post by Jack
Post by Christian ASTOR
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
Use Superclassing.
Hi,
Maybe a stupid question, but...
I create the edit controls using the dialog editor, not createwindow, how do
I superclass them? All the examples I have seen use createwindow() and
superclass there.
Superclassing means making a new class based on an existing class.

Use GetClassInfoEx() to fill a WNDCLASSEX structure and modify some of
the structure members so that they describe your new super class. (You
must modify at least lpszClassName and probably lpfnWndProc as well.)
After making necessary changes, register your super class with
RegisterClassEx(). Save the original value of lpfnWndProc so that your
window procedure can use it in a call to CallWindowProc() to handle
messages that you do not handle.

You can use the name of your super class in CONTROL statement in your
dialog script. Note that you must register your super class before
creating a dialog that uses it.
--
Norm

To reply, change domain to an adult feline.
Christian ASTOR
2008-03-30 19:35:58 UTC
Permalink
Post by Jack
Post by Christian ASTOR
Use Superclassing.
Hi,
Maybe a stupid question, but...
I create the edit controls using the dialog editor, not createwindow, how do
I superclass them? All the examples I have seen use createwindow() and
superclass there.
Use a "Custom Control" in Dialog Editor with a given class name.
Then GetClassInfo() - RegisterClass() with the same class name and your
new WndProc
Jack
2008-03-30 19:34:34 UTC
Permalink
Post by Christian ASTOR
Post by Jack
Post by Christian ASTOR
Use Superclassing.
Hi,
Maybe a stupid question, but...
I create the edit controls using the dialog editor, not createwindow, how
do I superclass them? All the examples I have seen use createwindow() and
superclass there.
Use a "Custom Control" in Dialog Editor with a given class name.
Then GetClassInfo() - RegisterClass() with the same class name and your
new WndProc
Thanks. I'll remember that.

However, I made a mistake in my code as it seems you can subclass multiple
controls with the same subclass function.
Norman Bullen
2008-03-30 20:21:50 UTC
Permalink
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
I use the handle returned by the subclassing SetWindowLong() in the
subclassed procedure.
But when I create a second subclass on another editbox the returned handle
is different so the subclassed procedure gets confused (I presume).
How can I set things up so that I can use the same subclass procedure code?
I thought about saving each WNDPROC and passing it in each time the
subclass is called via a Sendmessage() return code but I presume there is a
cleaner way.
Will someone let me in on the secret? :) TIA.
PS do I have to unhook the procedure for each subclassed editbox when I exit
the popup dialog on which it resides or will things be cleaned-up
automatically on dialog exit?
~~~~~~~~~
WNDPROC lpfnOrigEBGenericAmount ;
lpfnOrigEBGenericAmount = (WNDPROC) SetWindowLong (hWndEdit1, GWL_WNDPROC,
(LONG) EBSubclassGenericProcAmount);
LRESULT CALLBACK EBSubclassGenericProcAmount(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam){
switch (uMsg)
{
####
}
return CallWindowProc(lpfnOrigEBGenericAmount , hWnd, uMsg, wParam,
lParam);
}
Just to be sure that we're talking about the same thing, the value that
you are getting from the call to SetWindowLong() is a _pointer_ to a
function, not a handle.

Normally, every window created from the window class EDIT will have the
same window procedure pointer. If you're getting different values, it
means that some or all of the windows have already been subclassed.

Since your subclass procedure does need to call the correct window
procedure that was in placed before you subclassed it, you need to save
the pointer to the previous procedure on a per-window basis. There are
several way to do this:
- use SetProp() and GetProp(). You can cast the pointer that you got
from GetWindowLong() to a HANDLE. Remember to call RemoveProp() when you
get a WM_DESTROY message.
- Create your own static array that contains the the HWND and the
lpfnWndProc for each window that you subclass. Search that array when
you pass unhandled messages to the previous window procedure.
- Use SetWindowLong(hWnd, GWL_USERDATA, (LONG)lpfnWndProc) to save
the original lpfnWndProc value and get it back with GetWindowLong(hWnd,
GWL_USERDATA). Note that if the window has been subclassed, it's
possible that that subclassing routine is using the GWL_USERDATA value.
--
Norm

To reply, change domain to an adult feline.
Jack
2008-03-30 20:50:38 UTC
Permalink
Post by Norman Bullen
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
I use the handle returned by the subclassing SetWindowLong() in the
subclassed procedure.
But when I create a second subclass on another editbox the returned handle
is different so the subclassed procedure gets confused (I presume).
How can I set things up so that I can use the same subclass procedure code?
I thought about saving each WNDPROC and passing it in each time the
subclass is called via a Sendmessage() return code but I presume there is a
cleaner way.
Will someone let me in on the secret? :) TIA.
PS do I have to unhook the procedure for each subclassed editbox when I exit
the popup dialog on which it resides or will things be cleaned-up
automatically on dialog exit?
~~~~~~~~~
WNDPROC lpfnOrigEBGenericAmount ;
lpfnOrigEBGenericAmount = (WNDPROC) SetWindowLong (hWndEdit1,
GWL_WNDPROC,
(LONG) EBSubclassGenericProcAmount);
LRESULT CALLBACK EBSubclassGenericProcAmount(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam){
switch (uMsg)
{
####
}
return CallWindowProc(lpfnOrigEBGenericAmount , hWnd, uMsg, wParam,
lParam);
}
Just to be sure that we're talking about the same thing, the value that
you are getting from the call to SetWindowLong() is a _pointer_ to a
function, not a handle.
That's what I meant :)
Post by Norman Bullen
Normally, every window created from the window class EDIT will have the
same window procedure pointer. If you're getting different values, it
means that some or all of the windows have already been subclassed.
Yes it was, I made a mistake.
Post by Norman Bullen
Since your subclass procedure does need to call the correct window
procedure that was in placed before you subclassed it, you need to save
the pointer to the previous procedure on a per-window basis. There are
- use SetProp() and GetProp(). You can cast the pointer that you got
from GetWindowLong() to a HANDLE. Remember to call RemoveProp() when you
get a WM_DESTROY message.
- Create your own static array that contains the the HWND and the
lpfnWndProc for each window that you subclass. Search that array when you
pass unhandled messages to the previous window procedure.
- Use SetWindowLong(hWnd, GWL_USERDATA, (LONG)lpfnWndProc) to save the
original lpfnWndProc value and get it back with GetWindowLong(hWnd,
GWL_USERDATA). Note that if the window has been subclassed, it's possible
that that subclassing routine is using the GWL_USERDATA value.
Thanks for that, but if I just have the one subclass per window (edit
control) then can I use the simplistic version and just call the "default"
original procedure ie the Windows default returned when the first edit
control is subclassed?

Thats what I'm doing now and it seems to work OK.

Cheers.

PS As I'm only subclassing each control ar most once in a dialog can I
forget about unsubclassing them on dialog exit?
Norman Bullen
2008-03-30 21:21:22 UTC
Permalink
Post by Jack
Post by Norman Bullen
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
I use the handle returned by the subclassing SetWindowLong() in the
subclassed procedure.
But when I create a second subclass on another editbox the returned handle
is different so the subclassed procedure gets confused (I presume).
How can I set things up so that I can use the same subclass procedure code?
I thought about saving each WNDPROC and passing it in each time the
subclass is called via a Sendmessage() return code but I presume there is a
cleaner way.
Will someone let me in on the secret? :) TIA.
PS do I have to unhook the procedure for each subclassed editbox when I exit
the popup dialog on which it resides or will things be cleaned-up
automatically on dialog exit?
~~~~~~~~~
WNDPROC lpfnOrigEBGenericAmount ;
lpfnOrigEBGenericAmount = (WNDPROC) SetWindowLong (hWndEdit1,
GWL_WNDPROC,
(LONG) EBSubclassGenericProcAmount);
LRESULT CALLBACK EBSubclassGenericProcAmount(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam){
switch (uMsg)
{
####
}
return CallWindowProc(lpfnOrigEBGenericAmount , hWnd, uMsg, wParam,
lParam);
}
Just to be sure that we're talking about the same thing, the value that
you are getting from the call to SetWindowLong() is a _pointer_ to a
function, not a handle.
That's what I meant :)
Post by Norman Bullen
Normally, every window created from the window class EDIT will have the
same window procedure pointer. If you're getting different values, it
means that some or all of the windows have already been subclassed.
Yes it was, I made a mistake.
Post by Norman Bullen
Since your subclass procedure does need to call the correct window
procedure that was in placed before you subclassed it, you need to save
the pointer to the previous procedure on a per-window basis. There are
- use SetProp() and GetProp(). You can cast the pointer that you got
from GetWindowLong() to a HANDLE. Remember to call RemoveProp() when you
get a WM_DESTROY message.
- Create your own static array that contains the the HWND and the
lpfnWndProc for each window that you subclass. Search that array when you
pass unhandled messages to the previous window procedure.
- Use SetWindowLong(hWnd, GWL_USERDATA, (LONG)lpfnWndProc) to save the
original lpfnWndProc value and get it back with GetWindowLong(hWnd,
GWL_USERDATA). Note that if the window has been subclassed, it's possible
that that subclassing routine is using the GWL_USERDATA value.
Thanks for that, but if I just have the one subclass per window (edit
control) then can I use the simplistic version and just call the "default"
original procedure ie the Windows default returned when the first edit
control is subclassed?
Thats what I'm doing now and it seems to work OK.
Cheers.
PS As I'm only subclassing each control ar most once in a dialog can I
forget about unsubclassing them on dialog exit?
As long as you're not allocating any resource in your subclass
procedure, you can simply pass the WM_DESTROY message on to the original
window procedure and everything will be taken care of.
--
Norm

To reply, change domain to an adult feline.
Ron Francis
2008-03-31 14:25:59 UTC
Permalink
Post by Jack
Hi, I have a subclassed editbox which works fine. I want to run the same
code on several editboxes in the dialog (code below).
I use the handle returned by the subclassing SetWindowLong() in the
subclassed procedure.
But when I create a second subclass on another editbox the returned handle
is different so the subclassed procedure gets confused (I presume).
How can I set things up so that I can use the same subclass procedure code?
I thought about saving each WNDPROC and passing it in each time the
subclass is called via a Sendmessage() return code but I presume there is a
cleaner way.
Will someone let me in on the secret? :) TIA.
PS do I have to unhook the procedure for each subclassed editbox when I exit
the popup dialog on which it resides or will things be cleaned-up
automatically on dialog exit?
~~~~~~~~~
WNDPROC lpfnOrigEBGenericAmount ;
lpfnOrigEBGenericAmount = (WNDPROC) SetWindowLong (hWndEdit1,
GWL_WNDPROC,
(LONG) EBSubclassGenericProcAmount);
LRESULT CALLBACK EBSubclassGenericProcAmount(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam){
switch (uMsg)
{
####
}
return CallWindowProc(lpfnOrigEBGenericAmount , hWnd, uMsg, wParam,
lParam);
}
For Windows XP and above, you can use SetWindowSubclass( ).
Also, SetWindowLong( ) has been superseded by SetWindowLongPtr( )

Regards,
Ron Francis
www.RonaldFrancis.com

Loading...