Tech Support > Microsoft Windows > Development Resources > subclassing of editbox-problem
subclassing of editbox-problem
Posted by Jugoslav Dujic on September 1st, 2004


Ekim wrote:
| hy,
| I tried to subclass my editbox to be able to handle WM_CHAR-messages.
| Unforunately, I think somewhere I made a big mistake, because now I cannot
| maku use of commands like SendMessage or GetWindowText anymore. That is, as
| far as I guess, maybe because of a "wrong" call to the old
| edit-window-procedure.
|
| So my code looks like this:
|
| myClass.h:
| // added WndProc for subclassing EditBox:
| static LRESULT CALLBACK NewEditProc (HWND hwnd, UINT message,
| WPARAM wParam, LPARAM lParam)

| // my subclassed-window-proc:
| LRESULT CALLBACK myClass::NewEditProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)

Here lie the dragons: you have a mismatch between declaration and definition
of NewEditProc. Your myClass::NewEditProc must be static as well. That
compiles?

If you need to access members the myClass itself, you have to store it
elsewhere than in myClass::NewEditProc::this. The most commonly used trick
is to store a pointer to an object of myClass into hWndEdit's private
window data (via SetWindowLong(GWL_USERDATA) or SetProp).

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Posted by Jugoslav Dujic on September 1st, 2004


Ekim wrote:
| "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
| news:2pldgmFlab2hU1@uni-berlin.de...
|| Ekim wrote:
||| hy,
||| I tried to subclass my editbox to be able to handle WM_CHAR-messages.
||| Unforunately, I think somewhere I made a big mistake, because now I cannot
||| maku use of commands like SendMessage or GetWindowText anymore. That is, as
||| far as I guess, maybe because of a "wrong" call to the old
||| edit-window-procedure.
|||
||| So my code looks like this:
|||
||| myClass.h:
||| // added WndProc for subclassing EditBox:
||| static LRESULT CALLBACK NewEditProc (HWND hwnd, UINT message,
||| WPARAM wParam, LPARAM lParam)
||
||| // my subclassed-window-proc:
||| LRESULT CALLBACK myClass::NewEditProc (HWND hwnd, UINT message,
|| WPARAM wParam, LPARAM lParam)
||
|| Here lie the dragons: you have a mismatch between declaration and definition
|| of NewEditProc. Your myClass::NewEditProc must be static as well. That
|| compiles?
||
|| If you need to access members the myClass itself, you have to store it
|| elsewhere than in myClass::NewEditProc::this. The most commonly used trick
|| is to store a pointer to an object of myClass into hWndEdit's private
|| window data (via SetWindowLong(GWL_USERDATA) or SetProp).
||
|
| ahm, your suggested solution may point into the right direction - but adding
| static in front of the defintion of myClass::NewEditProc is neither
| necessary nor allowed (as described in one of my books). The way I have
| written it compiles correctly, and what's more, the main-window-procedure is
| declared and defined exactly in the same way (that is in the declaration in
| myClass.h is declared as static, and in the myClass.cpp-file is not defined
| static).

Ahm, my bad... C++ is not really my mother tongue :-D. I routinely copy the
prototype from .h file to .cpp or vice versa. On the other hand, your symptoms
indicate some kind of stack corruption so I thought that was the culprit.
If you place a breakpoint in your NewEditProc, does it EVER get hit? I'd guess
no (GetWindowText just sends a WM_GETTEXT so I presume ANY message will
end up nowhere, resulting in access violation).

| But let me ask a stupid question - why should it be static at all? Or should
| only the main-window-procedure be static? However, if I delete the keyword
| static in front of the declaration, so that it is a normal
| non-static-member-function, I get the following error:

It's not stupid question at all (but it's a FAQ also, then). That's because
Windows is (as if) written in C, and on assembly level the signature of a static
or non-member wndproc routine is:

__stdcall(int hWnd, int, int, int)

while the signature of a member wndproc routine is:

__stdcall(myClass* this, int hWnd, int, int, int)

since in this case Windows calls you, it will "push" 4 arguments onto the
stack but you'd try to "pop" five, and in wrong order. Thus, you have to use
the static or non-member routine. SetProp or GWL_USERDATA associate "this"
by other means.

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Posted by Jugoslav Dujic on September 1st, 2004


Ekim wrote:
| "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
| news:2plhp7Fmkhp9U1@uni-berlin.de...
| and according to your debbuging-thing: unfortunately I work on a DLL (which
| is later on loaded into explorer.exe) and therefore it's not possible for me
| to set any breakpoints and debug it - that makes it all that difficult for
| me ;-(

Should be possible if you specify "Project/Settings/Debug/Executable for debug
session: Explorer.exe". If not, try "Debug/Attach to Process".

(Assuming MSVC6)

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Posted by Jugoslav Dujic on September 1st, 2004


Ekim wrote:
|
| thanks for all your efforts, problem solved.
| in fact it had nothing directly to do with subclassing, this works fine. the
| problem was that now I got an exception when I tried to access a
| member-variable like m_hEditWnd in the GetWindowText-function.
| The strange thing about it is that the compiler says no error, but when
| executing it comes to this access-violation. I cannot use other
| member-variables, too - I have no clue why, but anyhow, now that I avoid
| access to them, it works fine!

Because you're in a static function, which is common for all instances of
class' objects. The static function does not have an idea which object
it's invoked for, and does not have access to m_hEditWnd, which is shortcut
for this->m_hEditWnd, (because "this" is unknown).

I'd expect the compiler to bitch about access to non-static member variables
from a static member function. Anyone knows why it doesn't? (No, I won't
crosspost to comp.lang.c++, thank you, it would take a huge effort to convince
those guys that it's on-topic).

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Posted by Jugoslav Dujic on September 1st, 2004


Ekim wrote:
| "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
| news:2plnpmFl7qjvU1@uni-berlin.de...
|| Ekim wrote:
|||
||| thanks for all your efforts, problem solved.
||| in fact it had nothing directly to do with subclassing, this works fine. the
||| problem was that now I got an exception when I tried to access a
||| member-variable like m_hEditWnd in the GetWindowText-function.
||| The strange thing about it is that the compiler says no error, but when
||| executing it comes to this access-violation. I cannot use other
||| member-variables, too - I have no clue why, but anyhow, now that I avoid
||| access to them, it works fine!
||
|| Because you're in a static function, which is common for all instances of
|| class' objects. The static function does not have an idea which object
|| it's invoked for, and does not have access to m_hEditWnd, which is shortcut
|| for this->m_hEditWnd, (because "this" is unknown).
||
|
| hm, I don't right agree with you. First, if I want to access my
| member-variable, I tried using
| CDeskBand *pThis = (CDeskBand*)GetWindowLong(hwnd, GWL_USERDATA);
| and access members via pThis->m_hEditWnd for example, which works very fine
| in the "normal" window-procedure of the main-window, too (although it is
| static as well).

That's normal, fine & as expected, but I parsed your previous post:
||| "the problem was that now I got an exception when I tried to access a
||| member-variable like m_hEditWnd in the GetWindowText-function."
as "I call GetWindowText(m_hEditWnd) from MyEditProc directly", which seems
not to be the case.

On the other hand, if you DO call it as

CDeskBand *pThis = (CDeskBand*)GetWindowLong(hwnd, GWL_USERDATA);
pThis->OnChar();

that SHOULD work, as well as:

fprintf(hLogFile, "%9d", (int)pThis->m_hEditWnd);

| Second, I don't access members directly in the WindowProc of the editbox,
| but call OnChar()-function as response to WM_CHAR-message - and OnChar is a
| public member of my class CDeskband, and is NOT static, too.

Are you saying that (equivalent of) the code above does not work? I'd
attribute that to a bug somewhere rather than to failure of the method.

A sanity check: are you SURE that, at the time when you called:

SetWindowLong(hwndEdit, GWL_USERDATA, (LONG)&EditObject )

1) hwndEdit was a valid edit box handle and
2) CDeskBand EditObject was a valid and *non-local* object instance
(i.e. lifetime of the variable >= lifetime of the window)?

Now, if you could make that debugger work...

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Posted by Raymond Chen on September 1st, 2004


On Wed, 1 Sep 2004 10:14:17 -0700, "Ekim"
<the.newsletter@gmx.net> wrote:
The function you're passing is a nonstatic member function.
(Dust off your C++ reference. - myClass::* means pointer to
nonstatic member.) It needs to be static.

Posted by Ekim on September 1st, 2004


hy,
I tried to subclass my editbox to be able to handle WM_CHAR-messages.
Unforunately, I think somewhere I made a big mistake, because now I cannot
maku use of commands like SendMessage or GetWindowText anymore. That is, as
far as I guess, maybe because of a "wrong" call to the old
edit-window-procedure.

So my code looks like this:

myClass.h:
----------------------------------------------------------------------------
--
.........
// existing Main-WndProc of parent-window
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam,
LPARAM lParam);
// added WndProc for subclassing EditBox:
static LRESULT CALLBACK NewEditProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
..........
----------------------------------------------------------------------------
--

myClass.cpp:
----------------------------------------------------------------------------
--
// add a global/static WNDPROC variable that will store the address of the
edit control's Wnd Procedure:
static WNDPROC g_OldEdit;


// my subclassed-window-proc:
LRESULT CALLBACK myClass::NewEditProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CHAR:
// do something
break;
}

// call "old" standard window-proc of editbox
return CallWindowProc (g_OldEdit, hwnd, message, wParam, lParam);
}


// after creating the editbox-window (that is after calling
CreateWindowEx("Edit",...) in the WM_CREATE-handler of the parent-window), I
"replace" the standard-window-procedure with my own and store the old window
procedure like this:
g_OldEdit = (WNDPROC)SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG)
NewEditProc);
----------------------------------------------------------------------------
----------------------

So my assumption is that the old window-procedure is somehow not called
correctly, and therefore I cannot make use of commands like SendMessage,
GetWindowText and so on.
Unfortunately, I have no clue where I made a mistake. I hope I could
describe my problem to you detailled enough, and hope still more that one of
you is able to help me please!

thx in advance,
ekim!


Posted by Ekim on September 1st, 2004


"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
news:2pldgmFlab2hU1@uni-berlin.de...
ahm, your suggested solution may point into the right direction - but adding
static in front of the defintion of myClass::NewEditProc is neither
necessary nor allowed (as described in one of my books). The way I have
written it compiles correctly, and what's more, the main-window-procedure is
declared and defined exactly in the same way (that is in the declaration in
myClass.h is declared as static, and in the myClass.cpp-file is not defined
static).
But let me ask a stupid question - why should it be static at all? Or should
only the main-window-procedure be static? However, if I delete the keyword
static in front of the declaration, so that it is a normal
non-static-member-function, I get the following error:

//Replace the Window Procedure and Store the Old Window Procedure
g_OldEdit = (WNDPROC)SetWindowLong(m_hEditWnd, GWL_WNDPROC,
(LONG)NewEditProc);

// in the above line occurs this error:
"type cast: cannot convert from 'LRESULT (__stdcall
myClass::*)(HWND,UINT,WPARAM,LPARAM)' to 'LONG'"

do you have an idea how to avoid this error?
thx again,
ekim!



Posted by Ekim on September 1st, 2004


"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
news:2plhp7Fmkhp9U1@uni-berlin.de...
thanks for all your efforts, problem solved.
in fact it had nothing directly to do with subclassing, this works fine. the
problem was that now I got an exception when I tried to access a
member-variable like m_hEditWnd in the GetWindowText-function.
The strange thing about it is that the compiler says no error, but when
executing it comes to this access-violation. I cannot use other
member-variables, too - I have no clue why, but anyhow, now that I avoid
access to them, it works fine!

and according to your debbuging-thing: unfortunately I work on a DLL (which
is later on loaded into explorer.exe) and therefore it's not possible for me
to set any breakpoints and debug it - that makes it all that difficult for
me ;-(

nothingtheless, thx a lot,
by ekim



Posted by Ekim on September 1st, 2004


"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
news:2plnpmFl7qjvU1@uni-berlin.de...
hm, I don't right agree with you. First, if I want to access my
member-variable, I tried using
CDeskBand *pThis = (CDeskBand*)GetWindowLong(hwnd, GWL_USERDATA);
and access members via pThis->m_hEditWnd for example, which works very fine
in the "normal" window-procedure of the main-window, too (although it is
static as well).

Second, I don't access members directly in the WindowProc of the editbox,
but call OnChar()-function as response to WM_CHAR-message - and OnChar is a
public member of my class CDeskband, and is NOT static, too.

So I don't see why it shouldn't work ;-(

by ekim



Posted by Ekim on September 1st, 2004


"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
news:2plr4dFm2hujU1@uni-berlin.de...
many thx again,
no I still don't know what the problem was, but now it works -
according to 1) yes, my handle to the edit-box was valid
2) i hope so that is was valid and non-local - as I said I call
SetWindowLong immediately after CreateWindowEx for the editbox, and this I
do in the handler of WM_CREATE of the main-window.

anyway, thx,
by ekim




Similar Posts