Jump to content
  • Advertisement
Sign in to follow this  
dbrink

Window class (C++/Win32 API)

This topic is 2600 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

Hello,

I've been trying to create a Window class, just for learning purposes (I'm quite new to both C++ and the Win32 API).

I created a StaticWndProc which uses SetWindowLongPtr and GetWindowLongPtr to store the window. The problem is that wnd->WndProc(message, wParam, lParam) never gets called, because wnd is always NULL. I'm not sure if i'm just missing something or if my code is just plain wrong.

The program compiles fine, I do receive the WM_NCCREATE message, GetLastError always returns 0 and I do see the window when the running program. The messages just don't get through to WndProc.


Window.h

#include <windows.h>
#include <iostream>

class Window {
private:
HWND hWnd;
public:
~Window();
void create();
void show();
private:
static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(UINT message, WPARAM wParam, LPARAM lParam);
};


Window.cpp

#include "Window.h"

void Window::create() {
WNDCLASSEX wndClass;

HINSTANCE hInstance = GetModuleHandle(NULL);

wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = 0;
wndClass.lpfnWndProc = (WNDPROC) StaticWndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "MyWindow";
wndClass.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION);

if (!::RegisterClassEx(&wndClass)) {
::MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
}

hWnd = ::CreateWindowEx(WS_EX_STATICEDGE, "MyWindow", "MyWindow", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT, 320, 240, NULL, NULL, hInstance, NULL);

if (hWnd == NULL) {
::MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
}
}

void Window::show() {
::ShowWindow(hWnd, SW_SHOW);
::UpdateWindow(hWnd);
}

LRESULT CALLBACK Window::StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
Window *wnd;

if(message == WM_NCCREATE) {
wnd = reinterpret_cast<Window *>(((LPCREATESTRUCT)lParam)->lpCreateParams);
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(wnd));
} else {
wnd = reinterpret_cast<Window *>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
}

if (wnd) {
return wnd->WndProc(message, wParam, lParam);
} else {
::DefWindowProc(hWnd, message, wParam, lParam);
}
}

LRESULT CALLBACK Window::WndProc(UINT message, WPARAM wParam, LPARAM lParam) {
std::cout << "WndProc" << std::endl;
return ::DefWindowProc(hWnd, message, wParam, lParam);
}

Window::~Window() {
if (hWnd != NULL) {
::DestroyWindow(hWnd);
}
}


main.cpp

#include "Window.h"

int main(int argc, char **argv) {
Window wnd;

wnd.create();
wnd.show();

MSG msg;
while (GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

Share this post


Link to post
Share on other sites
Advertisement
If you ever intend for wnd not to be NULL, you shall have to pass a value other than NULL to CreateWindowEx() in the last parameter.


L. Spiro

Share this post


Link to post
Share on other sites
Read MSDN
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632603%28v=vs.85%29.aspx

Why do you think lParam->lpCreateParams is your object?
NO.

You need to store your Window object in a global variable and in first call of wndproc set window long ptr with the value.
That's why many GUI framework requires the window widgets should be created from main thread.

Share this post


Link to post
Share on other sites
It is absolutely not necessary to use a global for this.
Once he passes his this pointer to CreateWindowEx() it will work fine, and it is the proper way to do this.
Using a global would completely defeat the object-oriented design for which he is striving.


L. Spiro

Share this post


Link to post
Share on other sites

It is absolutely not necessary to use a global for this.
Once he passes his this pointer to CreateWindowEx() it will work fine, and it is the proper way to do this.
Using a global would completely defeat the object-oriented design for which he is striving.


L. Spiro


But that's not guaranteed to be the Window object.

Seems for MDI it's an issue.

http://msdn.microsoft.com/en-us/library/ms632680.aspx

lpParam [in, optional] Type: LPVOID

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.

If an application calls CreateWindow to create a MDI client window, lpParam should point to a CLIENTCREATESTRUCT structure. If an MDI client window calls CreateWindow to create an MDI child window, lpParam should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed.

Share this post


Link to post
Share on other sites
He isn’t creating an MDI window. He is creating a window of class type “MyWindow”.
For the code he is using, reinterpret_cast<LPCREATESTRUCT>(_lParam)->lpCreateParams will absolutely be a Window * once he starts passing his this to CreateWindowEx().


L. Spiro

Share this post


Link to post
Share on other sites
Ah, I knew it had to be such an obvious mistake, turns out I also forgot to set the window handle after setting the windowLongPtr.

Thanks for the help!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!