• Advertisement

Archived

This topic is now archived and is closed to further replies.

Problems storing this in GWL_USERDATA

This topic is 5811 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, I wrote a class CWindow and Im having no problems getting the this* to the static WndProc, what im having problems with is it wont let me store it using (I try to store it when processing the WM_NCCREATE message):
    
SetWindowLong(hwnd, GWL_USERDATA,(LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
			
    
Is there something I should set in the WNDCLASSEX struct? or when I call CreateWindowEx? And yes im already passing this in as the lpParam. When ever I try to retrieve it using:
  
 cWnd = (CWindow*)GetWindowLong(hWnd, GWL_USERDATA) 
  
to get my this pointer it just gives me a null value. If you need to see some code I can Post the basics for the class. "Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music." - Kristian Wilson, Nintendo, Inc, 1989 Edited by - xds4lx on February 24, 2002 11:27:19 PM

Share this post


Link to post
Share on other sites
Advertisement
Maybe try passing the address ...
      
SetWindowLong(hwnd, GWL_USERDATA,(LONG)&(((LPCREATESTRUCT)lParam)->lpCreateParams));



Share this post


Link to post
Share on other sites
That didnt work, it, compiled but made it crash, with an unhandled exception.

Share this post


Link to post
Share on other sites
when you do your creation of the window you set userdata, not in the message loop since you wont know for which object the window belongs to without doing some lookups. instead you should do the following in your window create funtion:

  
// PSUDEO code

// ...

hwnd = CreateWindow();
SetWindowLong(hwnd, GWL_USERDATA, (LONG)this);
// ...



you do the get as you have been within your message loop as needed. if that dont work, then you have something seriously wrong with your code. since i have used similar methods myself.

Share this post


Link to post
Share on other sites
I tried doing that also but it still doesnt work. Im going to pose the code here b/c this is really frustrating. Ive looked at NeHe's basecode and I seem to be doing everything the same, but it doesnt work.

    
//From CBWindow.h


class CBWindow{
public:

CBWindow(HINSTANCE hInstance, char* pszWindowName, int cXpos, int cYpos, int cXsize,
int cYsize);
//Pre:

//Post:


bool Create();
//Pre:

//Post:


virtual ~CBWindow();
//Pre:

//Post:


void Message(char* pszMessage, char* pszTitle, UINT uStyle = 0);
//Pre:

//Post:


void SetWindowName(char* pszName);
//Pre:

//Post:


protected:

WNDCLASSEX wndClass;
HINSTANCE hInst;
HWND hWnd;

char* pszCName;
char* pszWName;

bool bInitFail;

int cXPos;
int cYPos;
int cXSize;
int cYSize;

virtual LRESULT WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam);
//Pre:

//Post:


private:

bool RegisterWnd();
//Pre:

//Post:


bool BuildWin();
//Pre:

//Post:


static LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
//Pre:

//Post:

};

//From CBWindow.cpp

/* ******************************** Constructors *************************************** */
CBWindow::CBWindow(HINSTANCE hInstance, char* pszWindowName, int cXpos, int cYpos,
int cXsize, int cYsize)
: hInst(hInstance), pszCName("CBWindow"), pszWName(pszWindowName), cXPos(cXpos), cYPos(cYpos),
cXSize(cXsize), cYSize(cYsize), bInitFail(false)
{
}

CBWindow::~CBWindow()
{ UnregisterClass(pszCName,hInst);
}

/* ************************************************************************************** */

/* ******************************* Public Methods ************************************** */
bool CBWindow::Create()
{ if(!RegisterWnd())
{ bInitFail = true;
}

if(!bInitFail && !BuildWin())
{ bInitFail = true;
}
else
{ ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
bInitFail = false;
}
return(!bInitFail);
}

void CBWindow::Message(char* pszMessage, char* pszTitle, UINT uStyle)
{ MessageBox(NULL,pszMessage,pszTitle, MB_OK | uStyle);
}

void CBWindow::SetWindowName(char* pszName)
{ SetWindowText(hWnd,pszName);
pszWName = pszName;
}


/* ************************************************************************************** */

/* ***************************** Protected Methods ************************************** */
LRESULT CBWindow::WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{ default:
{ return(DefWindowProc(hwnd,Msg,wParam,lParam));
}
} // end of switch(Msg)
return(0);
}

/* ******************************* Private Methods ************************************** */
bool CBWindow::RegisterWnd()
{ ZeroMemory(&wndClass, sizeof(WNDCLASSEX));

wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.hCursor = (HCURSOR)LoadCursor(NULL,IDC_ARROW);
wndClass.hIconSm = (HICON)LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIcon = (HICON)LoadIcon(NULL,IDI_APPLICATION);
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wndClass.hInstance = hInst;
wndClass.lpszMenuName = NULL;
wndClass.lpfnWndProc = &(this->WindowProc);
wndClass.style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
//wndClass.cbClsExtra = 0;
//wndClass.cbWndExtra = 0;
wndClass.lpszClassName = pszCName;

if(!RegisterClassEx(&wndClass))
{ MessageBox(NULL,"Error Registering Window Class","ERROR IN APPLICATION STARTUP",MB_OK);
return(false);
}
return(true);
}

bool CBWindow::BuildWin()
{ if(!bInitFail)
{ hWnd = CreateWindowEx(WS_EX_APPWINDOW,
pszCName,
pszWName,
WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_VISIBLE,
cXPos, // X Position
cYPos, // Y Position
cXSize, // X Size
cYSize, // Y Size
NULL, // Handle to Parent
NULL, // Handle to Menu
hInst, // Application Instance
(void*)this);
}
if(!hWnd)
{ MessageBox(NULL,"Error Creating Window","ERROR IN APPLICATION STARTUP",MB_OK);
return(false);
}
return(true);
}

LRESULT CALLBACK CBWindow::WindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ CBWindow* cWnd ;//= (CBWindow*)GetWindowLong(hwnd, GWL_USERDATA);

switch(Msg)
{ case WM_NCCREATE:
{ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;

cWnd = (CBWindow*)lpcs->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA,(LONG)cWnd);
return(TRUE);
}
case WM_CLOSE:
{ DestroyWindow(hwnd);
break;
}
case WM_DESTROY:
{ PostQuitMessage(0);
break;
}
default:
{ cWnd = (CBWindow*)GetWindowLong(hwnd, GWL_USERDATA);
if(cWnd)
return(cWnd->WndProc(hwnd,Msg,wParam,lParam));
else
return(DefWindowProc(hwnd,Msg,wParam,lParam));
}
} // end of switch(Msg)
return(0);
}/* ******************************** Constructors *************************************** */
CBWindow::CBWindow(HINSTANCE hInstance, char* pszWindowName, int cXpos, int cYpos,
int cXsize, int cYsize)
: hInst(hInstance), pszCName("CBWindow"), pszWName(pszWindowName), cXPos(cXpos), cYPos(cYpos),
cXSize(cXsize), cYSize(cYsize), bInitFail(false)
{
}

CBWindow::~CBWindow()
{ UnregisterClass(pszCName,hInst);
}

/* ************************************************************************************** */

/* ******************************* Public Methods ************************************** */
bool CBWindow::Create()
{ if(!RegisterWnd())
{ bInitFail = true;
}

if(!bInitFail && !BuildWin())
{ bInitFail = true;
}
else
{ ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
bInitFail = false;
}
return(!bInitFail);
}

void CBWindow::Message(char* pszMessage, char* pszTitle, UINT uStyle)
{ MessageBox(NULL,pszMessage,pszTitle, MB_OK | uStyle);
}

void CBWindow::SetWindowName(char* pszName)
{ SetWindowText(hWnd,pszName);
pszWName = pszName;
}


/* ************************************************************************************** */

/* ***************************** Protected Methods ************************************** */
LRESULT CBWindow::WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{ default:
{ return(DefWindowProc(hwnd,Msg,wParam,lParam));
}
} // end of switch(Msg)
return(0);
}

/* ******************************* Private Methods ************************************** */

bool CBWindow::RegisterWnd()
{ ZeroMemory(&wndClass, sizeof(WNDCLASSEX));

wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.hCursor = (HCURSOR)LoadCursor(NULL,IDC_ARROW);
wndClass.hIconSm = (HICON)LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIcon = (HICON)LoadIcon(NULL,IDI_APPLICATION);
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wndClass.hInstance = hInst;
wndClass.lpszMenuName = NULL;
wndClass.lpfnWndProc = &(this->WindowProc);
wndClass.style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
//wndClass.cbClsExtra = 0;

//wndClass.cbWndExtra = 0;

wndClass.lpszClassName = pszCName;

if(!RegisterClassEx(&wndClass))
{ MessageBox(NULL,"Error Registering Window Class","ERROR IN APPLICATION STARTUP",MB_OK);
return(false);
}
return(true);
}

bool CBWindow::BuildWin()
{ if(!bInitFail)
{ hWnd = CreateWindowEx(WS_EX_APPWINDOW,
pszCName,
pszWName,
WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_VISIBLE,
cXPos, // X Position

cYPos, // Y Position

cXSize, // X Size

cYSize, // Y Size

NULL, // Handle to Parent

NULL, // Handle to Menu

hInst, // Application Instance

(void*)this);
}
if(!hWnd)
{ MessageBox(NULL,"Error Creating Window","ERROR IN APPLICATION STARTUP",MB_OK);
return(false);
}
return(true);
}

LRESULT CALLBACK CBWindow::WindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ CBWindow* cWnd ;//= (CBWindow*)GetWindowLong(hwnd, GWL_USERDATA);


switch(Msg)
{ case WM_NCCREATE:
{ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;

cWnd = (CBWindow*)lpcs->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA,(LONG)cWnd);
return(TRUE);
}
case WM_CLOSE:
{ DestroyWindow(hwnd);
break;
}
case WM_DESTROY:
{ PostQuitMessage(0);
break;
}
default:
{ cWnd = (CBWindow*)GetWindowLong(hwnd, GWL_USERDATA);
if(cWnd)
return(cWnd->WndProc(hwnd,Msg,wParam,lParam));
else
return(DefWindowProc(hwnd,Msg,wParam,lParam));
}
} // end of switch(Msg)

return(0);
}


Sorry about the length




"Computer games don't affect kids; I mean if Pac-Man affected us as kids, we'd all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music."
- Kristian Wilson, Nintendo, Inc, 1989


Edited by - xds4lx on February 24, 2002 12:04:47 AM

Share this post


Link to post
Share on other sites
quote:
Original post by a person
instead you should do the following in your window create funtion:

// PSUDEO code
// ...
hwnd = CreateWindow();
SetWindowLong(hwnd, GWL_USERDATA, (LONG)this);
// ...

Several messages are sent to the window before CreateWindow returns. To implement object association as you have outlined would require special handling in the message handler for WM_NCCREATE, WM_CALCSIZE and WM_CREATE. Not an elegant design.

xDSL4Lx, how are you passing this to CreateWindowEx? The following method works for me and many others:

Window::Create()
{
m_hwnd = CreateWindowEx(.., this); // this is the last parameter
// other init
}
...
LRESULT CALLBACK Window::MsgRouter(HWND hwnd, UINT msg, ...)
{
Window *wnd = NULL;
switch(msg)
{
case WM_NCCREATE:
SetWindowLong(GWL_USERDATA, (long)((LPCREATESTRUCT)lParam)->lpCreateparams);
return 0;
//
default:
wnd = (Window *)GetWindowLong(GWL_USERDATA);
if(wnd)
return wnd->WndProc(...);
break;
}
return DefWindowProc(...);
}


[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
quote:
Original post by xDS4Lx
cWnd = (CBWindow*)lpcs->lpCreateParams;

You're casting wrong, for one thing. You should wrap the entire right hand side in parentheses, because it's the lpCreateParams that you're casting, not lpcs.

[Edit: ie, cWnd = (CBWindow *)(lpcs->lpCreateParams);]

You also don't need to cast this to void *.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!


Edited by - Oluseyi on February 24, 2002 12:05:57 AM

Share this post


Link to post
Share on other sites
Is there something that I should set in the WNDCLASSEX struct? Or some specific parameters to use in CreatWindowEx?

Share this post


Link to post
Share on other sites
I dont know if this helps any but for some reason some function is causing an error, I find if I call GetLastError it returns 120, which acording to MSDN is: The Function Is Not Supported on this System. It returns this if i Call GetLast Error anywhere in my WndProc, how would I go about finding what is causing this?

Share this post


Link to post
Share on other sites
Tell you what, I''ll just send you some working code and let you go from there. Perhaps you''ll be able to find the difference between mine and yours. I''ll also send you an article I''ve written (it''s about 5 weeks from being posted here) about the technique (I should put it on my homepage - when I get my homepage up).

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
now i feel bad, sorry bout the flame It was nothing personal, just a lot of stress this week. First my gf of a year dumps me b/c she got diagnosed w/ cancer, second i get my credit card stolen, third my car died. what a great week

Share this post


Link to post
Share on other sites
quote:
Original post by xDS4Lx
now i feel bad, sorry bout the flame It was nothing personal, just a lot of stress this week. First my gf of a year dumps me b/c she got diagnosed w/ cancer, second i get my credit card stolen, third my car died. what a great week

Damn!

Don''t worry about it, though. I never take flames personally - especially those online. I''ve had some major flamewars on this site and ended up with respect for the opponent (see krez). Just glad I could make your life a bit easier.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
Thanx man good read! I dont know why, but I called SetLastError(0) right before calling SetWindowLong and now all of a sudden it works. Makes me wonder about what's really going on inside of windows b/c i dont see that in anyone else's code. The reason I know it works is b/c I put the WM_CLOSE and WM_DESTROY messages into my virtual window proc and had it output a message right before destroying the window and it sure does, but when I try to debug my program it always has GetWindowLong return null, is this just b/c I cant debug into the static WndProc?

Edited by - xds4lx on February 25, 2002 10:05:45 PM

Share this post


Link to post
Share on other sites

  • Advertisement