I'm trying to make a simple C++ wrapper around the Windows UI library but I'm getting some weird crashes that I can't seem to debug.
I have a base class Widget that does all the RegisterClassEx()/CreateWindowEx()/window subclassing in the class constructor.
Window is derived from Widget which sets up a top level window,
allows you to add a child, etc.
Now the library code is in a DLL, and my test app is linking against it.
So in the test app I add a button to the Window. The button is displayed, sized correctly,
etc, BUT when I close the window the test app crashes. I've traced it to deleting the child widget in the Window destructor, but I have no idea WHY this is causing the test app to crash...
Second thing, since my library lives in a DLL, I can't use GetModuleHandle(0), for when I need a HINSTANCE correct? Because that would return the exe's address space??
Widget.cpp
Code:// I think this is the correct way of doing this... HMODULE GetInstance() { HMODULE hModule; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&GetInstance, &hModule); return hModule; } Widget::Widget() { CreateWidget("MyClassName"); } Widget::Widget(LPCTSTR className) { CreateWidget(className); } Widget::~Widget() { } void Widget::CreateWidget(LPCTSTR className) { static bool registered = false; if (!registered) { WNDCLASSEX wcx; wcx.cbSize = sizeof(wcx); wcx.style = 0; wcx.lpfnWndProc = DefWindowProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.hInstance = GetInstance(); wcx.hIcon = NULL; wcx.hCursor = static_cast<HCURSOR>(LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE)); wcx.hbrBackground = NULL; wcx.lpszMenuName = NULL; wcx.lpszClassName = "MyClassName"; wcx.hIconSm = NULL; if (!RegisterClassEx(&wcx)) throw Exception("The window class could not be registered."); registered = true; } m_handle = CreateWindowEx(0, // extended styles className, // class name "", // window name 0, // window styles 0, // x 0, // y CW_USEDEFAULT, // width CW_USEDEFAULT, // height NULL, // parent window NULL, // menu handle GetInstance(), // instance handle NULL); // create params if (m_handle == NULL) throw Exception("The widget could not be created."); SetWindowLongPtr(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); // subclass the window m_oldWndProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(m_handle, GWLP_WNDPROC)); SetWindowLongPtr(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WindowProc)); } // ... other code snipped LRESULT CALLBACK Widget::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return CallWindowProc(m_oldWndProc, hwnd, uMsg, wParam, lParam); } LRESULT CALLBACK Widget::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { Widget* widget = reinterpret_cast<Widget* >(GetWindowLongPtr(hwnd, GWLP_USERDATA)); if (widget) return widget->ProcessMessage(hwnd, uMsg, wParam, lParam); return DefWindowProc(hwnd, uMsg, wParam, lParam); }
Window.cpp
Code:Window::Window() { // change the window style to a top level window SetWindowLongPtr(GetHandle(), GWL_STYLE, WS_OVERLAPPEDWINDOW); m_child = nullptr; } Window::Window(LPCTSTR className) : Widget(className) { // change the window style to a top level window SetWindowLongPtr(GetHandle(), GWL_STYLE, WS_OVERLAPPEDWINDOW); m_child = nullptr; } Window::~Window() { // with this in it's a guaranteed crash... //delete m_child; } void Window::SetChild(Widget* child) { if (child == nullptr) return; delete m_child; m_child = nullptr; m_child = child; m_child->SetParent(this); // layout the window Layout(); } LRESULT CALLBACK Window::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_SIZE: Layout(); break; default: return Widget::ProcessMessage(hwnd, uMsg, wParam, lParam); } return 0; }
Test.cpp
So once I click the close button on the window everything blows up.Code:int main(int argc, char* argv[]) { Window win; Button* btn = new Button(); btn->Show(); win.SetChild(btn); win.Show(); // Init common controls // Run windows event loop... Application::Run(); return 0; }
Also if I derive a C++ class from the Window object in my test app I get a crash on
startup...
I'm probably doing something insanely stupid somewhere, but I can't seem to find it....
EDIT:
I forgot to mention that my test app *still* crashes even if I don't do "delete m_child;". It just crashes less consistently.



LinkBack URL
About LinkBacks




