- 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