Re: Why does this cause "data abort" ?
"Lisa Pearlson" <no@spam.plz> ha scritto nel messaggio
news:OrgRWwmFIHA.4196@TK2MSFTNGP04.phx.gbl...
I'm using the SetWindowLong and GetWindowLong like so:
class MyWnd
{
BOOL Create(..)
m_hWnd = CreateWindow( .... );
SetWindowLong(hWnd, GWL_USERDATA, (LONG) hWnd);
It does not make sense to store the hWnd as a parameter for GWL_USERDATA,
you should store the "this" instance pointer into GWL_USERDATA slot, so you
can retrieve "this" instance in later calls.
You may define a pair of static member functions like these
(Get/SetInstancePtr):
<code>
---- [header] ----
class MyWnd
{
...
// Retrieve class instance
static MyWnd * GetInstancePtr( HWND hwnd );
// Set class instance
static void SetInstancePtr( HWND hwnd, MyWnd * pThisWnd );
};
---- [implementation] ----
/* static */ MyWnd * MyWnd::GetInstancePtr( HWND hwnd )
{
_ASSERTE( hwnd != NULL );
return (MyWnd *) ::GetWindowLong( hwnd, GWL_USERDATA );
}
/* static */ void MyWnd::SetInstancePtr( HWND hwnd, MyWnd * pThisWnd )
{
_ASSERTE( hwnd != NULL );
_ASSERTE( pThisWnd != NULL );
::SetWindowLong( hwnd, GWL_USERDATA, (LONG)pThisWnd );
}
</code>
Note that, as I wrote in my previous post, there are other options different
from GWL_USERDATA. For example, you can use window extra bytes (in
WNDCLASSEX.cbWndExtra) to store the "this" pointer.
e.g.
<code>
// When you register window class
// WNDCLASSEX wndClass;
...
wndClass.cbWndExtra = sizeof( MyWnd * );
</code>
And you should accordingly change the implementations of Get/SetInstancePtr
like so (note that the 0-offset accesses the extra window bytes with
::Get/SetWindowLong):
<code>
/* static */ MyWnd * MyWnd::GetInstancePtr( HWND hwnd )
{
_ASSERTE( hwnd != NULL );
return (MyWnd *) ::GetWindowLong( hwnd, 0 );
}
/* static */ void MyWnd::SetInstancePtr( HWND hwnd, MyWnd * pThisWnd )
{
_ASSERTE( hwnd != NULL );
_ASSERTE( pThisWnd != NULL );
::SetWindowLong( hwnd, 0, (LONG)pThisWnd );
}
</code>
Then you can have the following static window proc, which routes the
messages to proper class methods. The "this" pointer is extracted from the
HWND (using GWL_USERDATA or extra bytes):
<code>
/* static */ LRESULT CALLBACK MyWnd::Proc(
HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
// Retrieve the C++ this pointer for this window
MyWnd * pWnd = GetInstancePtr( hwnd );
switch(msg)
{
// Setup
case WM_NCCREATE:
// Create a new window object onto the heap
pWnd = new MyWnd();
// Set the "this" pointer, so we can retrieve it back from HWND
SetInstancePtr( hwnd, pWnd );
// Continue with the window creation process
return TRUE;
// Release resources when the window is destroyed
case WM_NCDESTROY:
delete pWnd;
break;
...
...
// Can handle other messages here, routing to class specific methods,
// e.g.:
case WM_SOME_MESSAGE:
pWnd->OnSomeMessage(...);
break;
// or:
// return pWnd->OnSomeMessage(...);
...
...
// or you can implement a "local" *non-static* window proc, and just
call it:
// return pWnd->WndProc( hwnd, msg, wParam, lParam );
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
</code>
Note that I used WM_NCCREATE and WM_NCDESTROY to get kind of the "very
first" and the "very last" window messages.
Giovanni