Win32 Windows and classes again. Something wrong...

Started by
23 comments, last by ANSI2000 22 years, 1 month ago
We talked about this a while back... I have managed to wrap the win32 code that wraps up the window creation within classes.. But i thought I should give it a try to clean it up a bit a or rearange things they way "I think" they should be.... Of course this failed miserably, can some one look and tell me what is wrong? I want to implement the constructor and create() function as I have them shown, of course this might not be possible... It doesnt seem that the WM_CREATE ever happens....

// g3dgui.h
#ifndef G3DGUI_H
#define G3DGUI_H

// Required include files.
#include <windows.h>
#include <windowsx.h>

namespace G3DGUI
{
	class Object
	{
	public:

		Object(HINSTANCE pInstance, HWND pParent) : instance(pInstance), parent(pParent) {}
		virtual ~Object() {}

		const HINSTANCE getInstance() const { return(instance); }
		const HWND getParent() const { return(parent); }
		const HWND getHandle() const { return(handle); }
		const char* getClassName() const { return(className); }
		const getX() const { return(x); }		
		const getY() const { return(y); }		
		const getWidth() const { return(width); }		
		const getHeight() const { return(height); }		
		const unsigned int getStyleEx() const { return(styleEx); }
		const unsigned int getStyle() const { return(style); }
		const char* getCaption() const { return(caption); }			

		void create(const char *pClassName, int pX, int pY, int pWidth, int pHeight, unsigned int pStyle, unsigned int pStyleEx, const char *pCaption)
		{
			setClassName(pClassName);
			setX(pX);
			setY(pY);
			setWidth(pWidth);
			setHeight(pHeight);
			setStyle(pStyle);
			setStyleEx(pStyleEx);
			setCaption(pCaption);

			windowClass.lpfnWndProc = defaultProc;
			windowClass.hInstance = getInstance();
			windowClass.lpszClassName = getClassName();
			windowClass.cbSize = sizeof(WNDCLASSEX);
			windowClass.cbClsExtra = 0;
			windowClass.cbWndExtra = 0;
			windowClass.style = 0;
			windowClass.hCursor = LoadCursor(0, IDC_ARROW);
			windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
			windowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
			windowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
			windowClass.lpszMenuName = 0;

			registerClass();
			
			handle = CreateWindowEx(getStyleEx(), getClassName(), getCaption(), getStyle(), 
									getX(), getY(), getWidth(), getHeight(), getParent(), 
									NULL, getInstance(), (LPSTR)this);
			update();
			
			show();
		}
		
		void update() { UpdateWindow(getHandle()); }
		void show()	{ ShowWindow(getHandle(), SW_SHOW); }
		void hide()	{ ShowWindow(getHandle(), SW_HIDE); }
		void focus() { SetFocus(getHandle()); }

		static LRESULT CALLBACK defaultProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
		{
			Object *thisObject = (Object*)GetWindowLong(hWnd, GWL_USERDATA);
			
			if(!thisObject)
			{
				if(Msg == WM_CREATE)
				{
					MessageBox(NULL, "WM_CREATE", "WM_CREATE", 0);
					LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
					thisObject = (Object*)lpcs->lpCreateParams;
					SetWindowLong(hWnd, GWL_USERDATA, (LONG)thisObject);
					return thisObject->winProc(Msg, wParam, lParam);
				}
				else
					return DefWindowProc(hWnd, Msg, wParam, lParam); // should never be called
			}
			else
			{
				MessageBox(NULL, "winProc", "winProc", 0);
				return thisObject->winProc(Msg, wParam, lParam);
			}
		}
	
		virtual LRESULT winProc(UINT Msg, WPARAM wParam, LPARAM lParam) = 0;

	protected:

		void setClassName(const char *pClassName) { className = pClassName; }
		void setX(int pX) { x = pX; }		
		void setY(int pY) { y = pY; }		
		void setWidth(int pWidth) { width = pWidth; }		
		void setHeight(int pHeight) { height = pHeight; }		
		void setStyle(unsigned int pStyle) { style |= pStyle; }
		void setStyleEx(unsigned int pStyleEx) { styleEx |= pStyleEx; }
		void setCaption(const char *pCaption) { caption = pCaption; }

		bool registerClass()
		{
			if(!RegisterClassEx(&windowClass))
				return(false);
			else
				return(true);
		}
		
		void unRegisterClass()
		{
			UnregisterClass(getClassName(), getInstance());
		}

	private:
		HINSTANCE instance;
		HWND parent;
		HWND handle;
		WNDCLASSEX windowClass;
		const char* className;
		const char*	caption;
		int x;
		int	y;
		int	width;
		int	height;
		unsigned int style;
		unsigned int styleEx;
	};
}

#endif

// g3dgui.cpp
//Required include files.

//Application include files.
#include "g3dgui.h"
// Nothing in here all of it is inlined in the g3dgui.h file.

//winmain.cpp
#include <g3dgui.h>

using namespace G3DGUI;

bool running = true;

class TestWindow : public Object
{	
public:
	
	TestWindow(HINSTANCE pInstance, HWND pParent) : Object(pInstance, pParent){}

protected:

	LRESULT winProc(UINT Msg, WPARAM wParam, LPARAM lParam);
};

LRESULT TestWindow::winProc(UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch (Msg)
	{
	case WM_CREATE:
		MessageBox(NULL, "dood", "doods", 0);
	case WM_DESTROY:
		PostQuitMessage(0);

		running = false;

		break;
	default:
		return DefWindowProc(getHandle(), Msg, wParam, lParam);
	}
	return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	TestWindow testWindow(hInstance, NULL);

	testWindow.create("My Window", 10, 10, 100, 100, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, "My Window");

	while(running)
	{
		MSG msg;

		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}	
	}


	return(0);
}
 
Advertisement
Try removing the condition around the WM_CREATE in Object::defaultProc - do you know that GWL_USERDATA is always going to be 0 at the WM_CREATE stage ?

It''s unnecessary anyway, you are only ever going to get a WM_CREATE once per window instance.

Have you tried stepping through the code with the debugger and seeing where it fails ?

HTH,
t0ne.



Slightly shrimpy smell == unsafe breadbin
Slightly shrimpy smell == unsafe breadbin
yeah WM_CREATE never hapens...
Actually correction the defaulProc never gets called...
So, the CreateWindowEx call executes but returns NULL, yea ?
I would check then that the hInstance is valid and that you''ve correctly registered the WNDCLASS amd check your window styles are a correct combination. Also what does GetLastError return after the failure ?

A small point, although it probably works OK in this instance your setClassName and setCaption methods are unsafe. You should allocate some memory and store the contents of the buffers rather than the pointer to it (it could go out of scope, get modified elsewhere etc.).



Slightly shrimpy smell == unsafe breadbin
Slightly shrimpy smell == unsafe breadbin
The class does register correctly...

To check if the instance is correct I do what check for a null value?

But you should be able to pass an instance of null and it should work anyways
i think you should check for hWnd if it is null then there where no window created.
May the code be with us !
Tone -> having a char* as paramter cant go out of scope : heres an example :

void setCaption(const char* cap)

the calling

wnd.setCaption("hello");

in this case "hello" is static and can never be modified.
May the code be with us !
I think the very ''1st'' few messages that Windows send is not WM_CREATE. I think WM_GETMINMAXINFO or WM_NCCREATE came before WM_CREATE, and the WM_GETMINMAXINFO is the 1st.

I suggest that WM_NCCREATE would be a nice spot for SetWindowLong
"after many years of singularity, i'm still searching on the event horizon"
quote:Original post by hotdot
Tone -> having a char* as paramter cant go out of scope : heres an example :

void setCaption(const char* cap)

the calling

wnd.setCaption("hello");

in this case "hello" is static and can never be modified.


In this particular case this is true. But how about:

char buffer[256];
strcpy(buffer, "Hello");

setCaption(buffer);

strcpy(buffer, "something else");

or if the above code was done inside a function, buffer would be created on the stack and lost when it went out of scope.




Slightly shrimpy smell == unsafe breadbin
Slightly shrimpy smell == unsafe breadbin

This topic is closed to new replies.

Advertisement