MLeoDaalder
September 22nd, 2006, 07:51 AM
Hello and thank you in advance for your time.
I'm currently writing a Win32 API wrapper (first time doing this, I have read various articles on this in the past), and it was shaping up nice, up until I gave it a test run to test the Window class.
The CreateWindowEx returns a not valid handle (0), but it doesn't set the LastError.
After some googling I found out that this is caused by the WndProc not handling the WM_NCREATE (and consorts) correctly. So, I zip back to my code and go to my WndProc, which happend to be a simple WndProc that just returned the result of DefWindowProc, so that wasn't the problem.
I've tried various diffrent approaches to solve it, added DefWindowProc directly, moved the wndproc to the cpp file (from the window manager cpp).
I finally added a simple MessageBox to it.
I compile, and run it. And guess what, the wndproc is never called!
I have checked if the WndProc is changed (for whatever reason) and it isn't.
The Wrapper is a bit more extensive than just a window wrapper, it's designed to also wrap buttons and the like, but I've started on the Window (seemed like the best thing to do, wouldn't you agree?) after the basic abstract classes (Widget, Container, LayoutManager).
This is what happens in the Main function:
OOWin32::WindowManagerPtr winManager = OOWin32::WindowManager::getInstance();
OOWin32::Window* testwindow = winManager->createWindow();
testwindow->setBounds(10,10, 800, 600);
testwindow->setTitle("OOWin32 Test Window 1");
testwindow->setStyle(WS_OVERLAPPEDWINDOW);
testwindow->setExtendedStyle(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
testwindow->setVisible(true);
return winManager->PumpMessages();
The setVisible function does this:
Container::setVisible(isVisible);
if(isVisible)
{
HWND hWnd = reinterpret_cast<HWND>(getHandle());
if(hWnd)
{
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
}
}
Container::setVisible does some layout stuff (through the layoutmanager) and sets the children visible, if needed.
But it starts by calling the Widget::setVisible, which does this:
visible = isVisible;
if(!handle)
if(!this->initialize())
return;
if(wid_pimpl_->parent)
{
wid_pimpl_->parent->doLayout(wid_pimpl_->parent->getIterator(this));
}
Now, in initialize, my problems happen (it's a virtual function, if you hadn't deduced this already).
this->class_name = ("OOWin32Window@0x" + (boost::format("%#p")%this).str()).c_str();
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEXA wc;
ZeroMemory(&wc, sizeof(WNDCLASSEXA));
wc.cbSize = sizeof(WNDCLASSEXA);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &TestWndProc;//::DefWindowProcA;//Util::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, iIcon);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = this->class_name.c_str();
// Register the application
if(!RegisterClassExA(&wc))
{
MessageBoxA(NULL, boost::lexical_cast<std::string>(GetLastError()).c_str(), "Error in RegisterClass", MB_OK);
destroy();
WindowManager::getInstance()->removeWindow(this);
return false;
}
RECT WindowRect;
ZeroMemory(&WindowRect, sizeof(RECT));
WindowRect.left= rect.x;
WindowRect.top = rect.y;
WindowRect.right=rect.w+rect.x;
WindowRect.bottom = rect.h+rect.y;
SetLastError(0);
// Find a function that can directly adjust the window
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
this->handle = 0;
HWND hWnd = CreateWindowExA(
dwExStyle, // Extended Style For The Window
this->class_name.c_str(), // Class Name
title.c_str(), // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
WindowRect.left, WindowRect.top, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL); // Window Long, used to pass along for user data.
this->handle = (void*)hWnd;
if(!hWnd)
{
MessageBoxA(reinterpret_cast<HWND>(handle), ("ERROR!\n" + boost::lexical_cast<std::string>(GetLastError())).c_str(), "Window::initialize", MB_OK);
destroy();
WindowManager::getInstance()->removeWindow(this, false);
return false;
}
return true;
This function goes right all the way up untill the CreateWindowEx, which, as I've said, returns 0, but does not set the LastError to something else than the value already set (which in the current code is 0, but I could just as well have set it to 9999 or -1 and it would happily report it in the MessageBox).
This is the WndProc I'm currently using:
LRESULT CALLBACK TestWndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
MessageBoxA(hWnd, "Test WndProc", "TEST!", MB_OK);
return DefWindowProc(hWnd, msg, wparam, lparam);
}
It has a breakpoint on the MessageBox.
I hope you can help me with this, it's seriously questioning my sanity (if I ever had any.:P).
Thank you again for your time.
MLeoDaalder
I'm currently writing a Win32 API wrapper (first time doing this, I have read various articles on this in the past), and it was shaping up nice, up until I gave it a test run to test the Window class.
The CreateWindowEx returns a not valid handle (0), but it doesn't set the LastError.
After some googling I found out that this is caused by the WndProc not handling the WM_NCREATE (and consorts) correctly. So, I zip back to my code and go to my WndProc, which happend to be a simple WndProc that just returned the result of DefWindowProc, so that wasn't the problem.
I've tried various diffrent approaches to solve it, added DefWindowProc directly, moved the wndproc to the cpp file (from the window manager cpp).
I finally added a simple MessageBox to it.
I compile, and run it. And guess what, the wndproc is never called!
I have checked if the WndProc is changed (for whatever reason) and it isn't.
The Wrapper is a bit more extensive than just a window wrapper, it's designed to also wrap buttons and the like, but I've started on the Window (seemed like the best thing to do, wouldn't you agree?) after the basic abstract classes (Widget, Container, LayoutManager).
This is what happens in the Main function:
OOWin32::WindowManagerPtr winManager = OOWin32::WindowManager::getInstance();
OOWin32::Window* testwindow = winManager->createWindow();
testwindow->setBounds(10,10, 800, 600);
testwindow->setTitle("OOWin32 Test Window 1");
testwindow->setStyle(WS_OVERLAPPEDWINDOW);
testwindow->setExtendedStyle(WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
testwindow->setVisible(true);
return winManager->PumpMessages();
The setVisible function does this:
Container::setVisible(isVisible);
if(isVisible)
{
HWND hWnd = reinterpret_cast<HWND>(getHandle());
if(hWnd)
{
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
}
}
Container::setVisible does some layout stuff (through the layoutmanager) and sets the children visible, if needed.
But it starts by calling the Widget::setVisible, which does this:
visible = isVisible;
if(!handle)
if(!this->initialize())
return;
if(wid_pimpl_->parent)
{
wid_pimpl_->parent->doLayout(wid_pimpl_->parent->getIterator(this));
}
Now, in initialize, my problems happen (it's a virtual function, if you hadn't deduced this already).
this->class_name = ("OOWin32Window@0x" + (boost::format("%#p")%this).str()).c_str();
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEXA wc;
ZeroMemory(&wc, sizeof(WNDCLASSEXA));
wc.cbSize = sizeof(WNDCLASSEXA);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &TestWndProc;//::DefWindowProcA;//Util::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, iIcon);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = this->class_name.c_str();
// Register the application
if(!RegisterClassExA(&wc))
{
MessageBoxA(NULL, boost::lexical_cast<std::string>(GetLastError()).c_str(), "Error in RegisterClass", MB_OK);
destroy();
WindowManager::getInstance()->removeWindow(this);
return false;
}
RECT WindowRect;
ZeroMemory(&WindowRect, sizeof(RECT));
WindowRect.left= rect.x;
WindowRect.top = rect.y;
WindowRect.right=rect.w+rect.x;
WindowRect.bottom = rect.h+rect.y;
SetLastError(0);
// Find a function that can directly adjust the window
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
this->handle = 0;
HWND hWnd = CreateWindowExA(
dwExStyle, // Extended Style For The Window
this->class_name.c_str(), // Class Name
title.c_str(), // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
WindowRect.left, WindowRect.top, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL); // Window Long, used to pass along for user data.
this->handle = (void*)hWnd;
if(!hWnd)
{
MessageBoxA(reinterpret_cast<HWND>(handle), ("ERROR!\n" + boost::lexical_cast<std::string>(GetLastError())).c_str(), "Window::initialize", MB_OK);
destroy();
WindowManager::getInstance()->removeWindow(this, false);
return false;
}
return true;
This function goes right all the way up untill the CreateWindowEx, which, as I've said, returns 0, but does not set the LastError to something else than the value already set (which in the current code is 0, but I could just as well have set it to 9999 or -1 and it would happily report it in the MessageBox).
This is the WndProc I'm currently using:
LRESULT CALLBACK TestWndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
MessageBoxA(hWnd, "Test WndProc", "TEST!", MB_OK);
return DefWindowProc(hWnd, msg, wparam, lparam);
}
It has a breakpoint on the MessageBox.
I hope you can help me with this, it's seriously questioning my sanity (if I ever had any.:P).
Thank you again for your time.
MLeoDaalder