WNDPROC in a class... no idea--PART 2

Started by
15 comments, last by Verg 19 years, 9 months ago
Ok folks, thank you for those suggestions yesterday. I know there're lots of ways to get round this problem, but I'm very interested in to make it the simplest the possible, so let me explain here. I did some sorta to put the address of my WNDPROC to the WNDCLASSEX.lpfnWndProc. However, this time it gets an error message from CreateWindowEx which I use the GetLastError function that tell me it's an invalid window handle. I know sprintf and sscanf probably just some stupid idea since the window doesn't get the class pointer at all. But this time, any idea that why it's giving me the 1400 Error? http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1300-1699_.asp --------------- The class code below -------------------- #include "WinClzCtrl.h" const DWORD // Normal window extened style WIN_MODE_EX_SYL = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, // Full screen windwow extened sytle WIN_FULL_EX_SYL = WS_EX_APPWINDOW, // Normal window style WIN_MODE_SYL = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // Full screen style during active WIN_FULL_SYL_ACTIVE = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // Full screen style when inactive WIN_FULL_SYL_MIN = WIN_FULL_SYL_ACTIVE | WS_SYSMENU; WinClzCtrl::WinClzCtrl () { mySC.ReadCfgIniFile (); hInstance = NULL; lpCmdLine = NULL; nShowCmd = 0; wcEX.cbSize = sizeof (wcEX); wcEX.style = wcEX.cbClsExtra = wcEX.cbWndExtra = 0; wcEX.lpfnWndProc = NULL; wcEX.hInstance = NULL; wcEX.hIcon = wcEX.hIconSm = wcEX.hCursor = NULL; wcEX.hbrBackground = NULL; wcEX.lpszMenuName = wcEX.lpszClassName = NULL; hWnd = NULL; wndMsg.hwnd = NULL; wndMsg.message = wndMsg.wParam = wndMsg.lParam = wndMsg.time = wndMsg.pt.x = wndMsg.pt.y = 0; clzName = winName = NULL; bigIcon = smallIcon = NULL; thisWinRect.bottom = thisWinRect.left = thisWinRect.right = thisWinRect.top = 0; currentstyle = currentstyleEX = 0; currentstyle = WIN_MODE_SYL; currentstyleEX = WIN_MODE_EX_SYL; } // MessageBox (NULL, buf, ERROR, MB_OK); // sprintf (buf, "%d", wcEX.lpfnWndProc); // MessageBox (NULL, buf, ERROR, MB_OK); bool WinClzCtrl::OnlyReg (HINSTANCE deInst, HICON hBig, HICON hSmall, char* className) { char buf[12]; int i = 0; // Trying to obtain the physically address of the WndProc function. sprintf (buf, "%d", WndProc); sscanf (buf, "%d", &i); wcEX.cbSize = sizeof (wcEX); wcEX.style = CS_HREDRAW | CS_VREDRAW; wcEX.lpfnWndProc = (WNDPROC) i; wcEX.cbClsExtra = 0; wcEX.cbWndExtra = 0; wcEX.hInstance = deInst; wcEX.hIcon = hBig; wcEX.hCursor = LoadCursor (hInstance, IDC_ARROW); wcEX.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH); wcEX.lpszMenuName = NULL; wcEX.lpszClassName = className; wcEX.hIconSm = hSmall; if (RegisterClassEx (&wcEX) == false) { MessageBox (NULL, "reg has problem", ERROR, MB_OK); UnregisterClass (clzName, hInstance); return false; } else { return true; } } bool WinClzCtrl::RegNCreate (HINSTANCE deInst, LPSTR cmdLine, int showCmd, char* className, char* titleName, HICON hBig, HICON hSmall) { char buf[12]; OnlyReg (deInst, hBig, hSmall, className); if (mySC.GetDisplayMode()) { currentstyle = WIN_FULL_SYL_ACTIVE; currentstyleEX = WIN_FULL_EX_SYL; } else { currentstyle = WIN_MODE_SYL; currentstyleEX = WIN_MODE_EX_SYL; } hInstance = deInst; lpCmdLine = cmdLine; nShowCmd = showCmd; hWnd = NULL; wndMsg.hwnd = NULL; wndMsg.message = wndMsg.wParam = wndMsg.lParam = wndMsg.time = wndMsg.pt.x = wndMsg.pt.y = 0; winName = titleName; clzName = className; bigIcon = hBig; smallIcon = hSmall; thisWinRect.left = thisWinRect.top = 0; thisWinRect.right = thisWinRect.left + mySC.GetResolutionWidth (); thisWinRect.bottom = thisWinRect.top + mySC.GetResolutionHeight (); if ((AdjustWindowRectEx (&thisWinRect, currentstyle, FALSE, currentstyleEX) == FALSE) || (hWnd = CreateWindowEx (currentstyleEX, clzName, winName, currentstyle, 0 /* thisWinRect.left */, 0 /* thisWinRect.top */, thisWinRect.right - thisWinRect.left, thisWinRect.bottom - thisWinRect.top, NULL, NULL, hInstance, this)) == NULL) { int j = (int) GetLastError(); sprintf (buf, "%d", j); MessageBox (NULL, "create has problem", ERROR, MB_OK); sprintf (buf, "%d", j); MessageBox (NULL, buf, ERROR, MB_OK); return false; } else { // Show The Window, see the following URL for more info. ShowWindow (hWnd, nShowCmd); // Sets Keyboard Focus To The Window SetFocus (hWnd); // Draw and update the window UpdateWindow (hWnd); // This should be true for window mode, in full screen probably false. // It's optional anyway. ShowCursor (TRUE); return true; } } WPARAM WinClzCtrl::Run() { while (GetMessage (&wndMsg, NULL, 0, 0)) { TranslateMessage (&wndMsg); DispatchMessage (&wndMsg); } return (wndMsg.wParam); } void WinClzCtrl::ChangePstNSz (RECT deWinSz) { thisWinRect = deWinSz; // call functions to change it // if (!SetWindowPos(hWnd, HWND_TOP, thisWinRect.left, thisWinRect.top, // thisWinRect.right, thisWinRect.bottom, SWP_SHOWWINDOW)) // { /* do something */ } } bool WinClzCtrl::Changestyle (DWORD style, DWORD styleX) { if ((SetWindowLong(hWnd, GWL_EXstyle, style) == false) || (SetWindowLong(hWnd, GWL_style, styleX) == false)) { return false; } else { currentstyle = style; currentstyleEX = styleX; mySC.SetDisplayMode (!mySC.GetDisplayMode ()); return true; } } WinClzCtrl::~WinClzCtrl() { UnregisterClass (clzName, hInstance); wcEX.hInstance = hInstance = NULL; lpCmdLine = NULL; nShowCmd = 0; wcEX.cbSize = wcEX.style = wcEX.cbClsExtra = wcEX.cbWndExtra = 0; wcEX.lpfnWndProc = NULL; wcEX.hIcon = wcEX.hIconSm = wcEX.hCursor = NULL; wcEX.hbrBackground = NULL; wcEX.lpszMenuName = NULL; wcEX.lpszClassName = NULL; hWnd = NULL; wndMsg.hwnd = NULL; wndMsg.message = wndMsg.wParam = wndMsg.lParam = wndMsg.time = wndMsg.pt.x = wndMsg.pt.y = 0; winName = clzName = NULL; bigIcon = smallIcon = NULL; thisWinRect.bottom = thisWinRect.left = thisWinRect.right = thisWinRect.top = 0; mySC.~SysCtrl (); } void WinClzCtrl::Testing () { MessageBox (NULL, "Testing", ERROR, MB_OK); } LRESULT CALLBACK WinClzCtrl::WndProc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_CREATE: Testing (); return 0; case WM_DESTROY: // After that we need to destroy the window handle PostQuitMessage(0); return 0; default: return DefWindowProc (hWnd, msg, wp, lp); } }
Advertisement
Where do you handle WM_NCCREATE?

Oluseyi to the rescue ;)
LRESULT CALLBACK WinClzCtrl::WndProc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)

thjis isn't declared static.

Did you read that article about wrapping a window in a class?
To C-Junkie's question

I'm trying NOT to use as static!

To Tim Cowley's question

I don't what does it (WM_NCCREATE)really do to the program, could you explain to me?
This is why you need a static message router.

And WM_NCCREATE is the VERY FIRST message that is sent to a window. It's a good idea to set the class pointer in there.
Since I still don't quite understand his codes, I try to put it to my codes, but i got an error message

error C2039: 'lpCreateParams' : is not a member of 'WinClzCtrl'
There are few syntax errors in the article, one being on the line you're getting an error with. He forgets a pair of parenthesis, it should be:
wnd = reinterpret_cast<Window*>(((LPCREATESTRUCT)lparam)->lpCreateParams);
Ok, I can't even get my WM_NCCREATE message passed to the CALLBACK function since I did it very differently!

----- in my WinClzCtrl::OnlyReg function ------------

char buf[12];
int i = 0;

sprintf (buf, "%d", WndProc);
sscanf (buf, "%d", i);
...
...

wcEX.lpfnWndProc = (WNDPROC) i; // <---- I can obtain the address of the function--EVEN it's inside a class--please read my codes if you have time.

------ in my WinClzCtrl::RegNCreate function -----------

....

if ((AdjustWindowRectEx (&thisWinRect, currentstyle, FALSE,
currentstyleEX) == FALSE) || (hWnd = CreateWindowEx (currentstyleEX,
clzName, winName, currentstyle, 0 , 0,
thisWinRect.right - thisWinRect.left, thisWinRect.bottom - thisWinRect.top,
NULL, NULL, hInstance, this)) == NULL)
{
int j = (int) GetLastError();
sprintf (buf, "%d", j);
MessageBox (NULL, "create has problem", ERROR, MB_OK);
sprintf (buf, "%d", j);
MessageBox (NULL, buf, ERROR, MB_OK);
return false;
}
....

----- then I try to test my WinClzCtrl::WndProc function with WM_NCCREATE ----------

case WM_NCCREATE:

MessageBox (NULL, "WM_NCCREATE", ERROR, MB_OK);

return TRUE;

----------------------- end -----------------------------------

To a working window the MessageBox message in WM_NCCREATE should show up before any other messages show up... but it did NOT. Which I believe is the WM_NCCREATE was even passed to the WndProc function; in other words, the WndProc wasn't even called! There's no way I can store the pointer thing if it wasn't even called.

I guess that's probably I try to use the sprintf and sscanf functions to obtain the address of the WndProc--which works if it's not a class function. Yet, I'm pretty sure the both sprintf and sscanf works completely fine to get the address of the WndProc, but I'm not sure if the

wcEX.lpfnWndProc = (WNDPROC) i;

points to the correct WndProc address since it's inside a class. I've tested non-class function and it works fine to me. So, I'm trying to figure out WTH is going on here. Any ideas?
C++ member functions used a different calling convention than regular functions, known as thiscall. What you're doing is a terribly hack that is guaranteed to cause you more problems that it's worth, since you don't even emulate the full behavior of the thiscall convention, which is a bad idea and probably compiler-specific anyway.

Just accept the fact you can't use a member function as a WindowProc, and follow Oluseyi's article completely.
psae0001: How about reading some of the answers you get?

This topic is closed to new replies.

Advertisement