Why does debugging not end when I close the application?
When I change the last parameter in CreateWindow from this, to NULL, debugging doesn't end, and I have to manually close it.
On the other hand, if I set the last parameter to this, and destroy and recreate the window, the window immediately closes after being created.
I'm trying to recreate a window after loading opengl extensions.
Changing the last parameter to NULL gets me the window, but I have to manually stop debugging.
Why does this happen?
C++
-
David Lowndes • 2,615 Reputation points • MVP
2023-08-26T15:35:09.0333333+00:00 The final parameter to CreateWindow is optional, so what does the code for your window do with it?
-
CDev-8220 • 300 Reputation points
2023-08-26T15:47:03.6166667+00:00 The final parameter to CreateWindow is optional, so what does the code for your window do with it?
I have no idea.
I thought setting it to NULL would be fine, but when I do, and close the window, debugging continues running. I'm trying to find out why.
-
David Lowndes • 2,615 Reputation points • MVP
2023-08-26T15:51:04.3233333+00:00 Presumably passing NULL is preventing something from operating as its designed to do, you need to find out what the window you're creating expects you to pass.
-
CDev-8220 • 300 Reputation points
2023-08-26T16:39:04.7333333+00:00 Presumably passing NULL is preventing something from operating as its designed to do, you need to find out what the window you're creating expects you to pass.
I don't understand.
How would I find out what it's expecting to be passed?
-
David Lowndes • 2,615 Reputation points • MVP
2023-08-26T16:42:44.12+00:00 What type/class of window are you creating?
Show your code that calls CreateWindow for starters. -
CDev-8220 • 300 Reputation points
2023-08-26T17:48:23.9966667+00:00 HRESULT Main::Register_Class(const HINSTANCE& hInstance) { HRESULT hr = S_OK; WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wcex.lpfnWndProc = Main::WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = hInstance; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION); wcex.lpszClassName = m_appName; wcex.cbSize = sizeof(WNDCLASSEX); RegisterClassEx(&wcex); return hr; } HRESULT Main::Create_Window( const HINSTANCE& hInstance, const int& x, const int& y, const int& w, const int& h) { HRESULT hr = S_OK; //m_hwnd = CreateWindow( // m_appName, // m_appName, // WS_OVERLAPPEDWINDOW, // x, // y, // w, // h, // NULL, // NULL, // HINST_THISCOMPONENT, // this //); m_hwnd = CreateWindowEx( WS_EX_OVERLAPPEDWINDOW, app_appName, app_appName, WS_OVERLAPPEDWINDOW, x, y, w, h, NULL, NULL, hInstance, // HINST_THISCOMPONENT NULL ); return hr; } hr = Register_Class(m_hinstance); if (SUCCEEDED(hr)) { hr = Create_Window(m_hinstance, m_X, m_Y, m_Width, m_Height); if (SUCCEEDED(hr)) { ShowWindow(m_hwnd, SW_HIDE); res = InitExtensions(m_hwnd); if (res) { DestroyWindow(m_hwnd); m_hwnd = nullptr; hr = Create_Window(m_hinstance, m_X, m_Y, m_Width, m_Height); if (SUCCEEDED(hr)) { } } } }
-
David Lowndes • 2,615 Reputation points • MVP
2023-08-26T18:12:49.2766667+00:00 OK, so in your Main::WndProc handler, for the WM_CREATE message handler, what does the code do with the passed lParam value (which is passed in the CREATESTRUCT lpCreateParams)? See the documentation.
FWIW, here's the documentation of that last parameter to CreateWindow:[in, optional] lpParam
Type: LPVOID
A pointer to a value to be passed to the window through the CREATESTRUCT structure (lpCreateParams member) pointed to by the lParam param of the WM_CREATE message. This message is sent to the created window by this function before it returns.
-
CDev-8220 • 300 Reputation points
2023-08-26T20:26:42.7233333+00:00 OK, so in your Main::WndProc handler, for the WM_CREATE message handler, what does the code do with the passed lParam value (which is passed in the CREATESTRUCT lpCreateParams)? See the documentation.
Oh. I see.
I don't recall where I got this code, but some things hurt my head, so I leave understanding them till later.
if (message == WM_CREATE) { LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam; Main* pMain = (Main*)pcs->lpCreateParams; ::SetWindowLongPtrW( hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pMain) ); result = 1; }
I read the documentation a number of times, but I don't yet get it. In time, I believe I will.
So what really is CreateWindow looking for?
-
RLWA32 • 48,391 Reputation points
2023-08-26T20:56:32.8266667+00:00 Passing a class instance this pointer to CreateWindow and the WM_CREATE handler saves the pointer to be retrieved later for calling member functions of the class to handle other messages and generally make member functions accessible.
There should be other code that calls GetWindowLongPtr to retrieve the stored this pointer for use in handling other windows messages and calling member functions of the class. It is common for the static WNDPROC that was registered to delegate message handling to a member function after the class instance this pointer has been retrieved.
-
CDev-8220 • 300 Reputation points
2023-08-27T20:44:46.9733333+00:00 Thanks for pointing me in the right direction.
I changed the WinProc, removing WM_CREATE, and it's working correctly now.
Thanks.
-
David Lowndes • 2,615 Reputation points • MVP
2023-08-27T23:06:36.69+00:00 I changed the WinProc, removing WM_CREATE, and it's working correctly now.
I'd be suspicious that removing that will be the end of your problems without hearing why.
-
RLWA32 • 48,391 Reputation points
2023-08-28T02:01:13.19+00:00 @David Lowndes, My guess is that because the Questioner creates a hidden window, destroys it and then immediately creates another window the following happens -
Valid this pointer is passed to CreateWindow
First window is created.
DestroyWindow is called. WM_DESTROY handler calls PostQuitMessage. Window is destroyed.
Second window is created but WM_QUIT is sitting in the queue.
Message loop exited and process terminates.
NULL is passed to CreateWindow
First Window is created.
Because NULL is stored and retrieved from GWLP_USERDATA all messages are handled by DefWindowProc.
DestroyWindow is called. DefWindowProc destroys the window.
Second window is created.
Second window is destroyed by DefWindowProc. No calls to PostQuitMessage are made, no WM_QUIT is in the queue.
Message loop waits in GetMessage until process is manually terminated by the debugger.
-
CDev-8220 • 300 Reputation points
2023-08-28T18:34:27.0166667+00:00 @David Lowndes I suspect the code in WinProc was isolated from accompanying code, and since I separated it, something broke.
Thanks for that explanation @RLWA32
-
CDev-8220 • 300 Reputation points
2023-08-28T18:39:00+00:00 There should be other code that calls GetWindowLongPtr to retrieve the stored this pointer for use in handling other windows messages and calling member functions of the class. It is common for the static WNDPROC that was registered to delegate message handling to a member function after the class instance this pointer has been retrieved.
So, removing the MessageHandler function was a ad move then.
I'll utilize it, later, and see what happens. Thanks.
-
RLWA32 • 48,391 Reputation points
2023-08-28T19:24:55.1533333+00:00 @CDev-8220, My comments have been based on the small bit of code that you have posted and are my best guess. If you want feedback and guidance that consists of more than guesses you will need to provide more information about your code.
-
CDev-8220 • 300 Reputation points
2023-08-30T14:35:58.9766667+00:00 @CDev-8220, My comments have been based on the small bit of code that you have posted and are my best guess. If you want feedback and guidance that consists of more than guesses you will need to provide more information about your code.
It's okay. Under normal conditions the problem does not exist.
The problem was using code from somewhere, which I did not need to have for my purposes.
Best to start simple, and with code I understand, and know what I am doing.
Sign in to comment