New to C++, simple window class
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: New to C++, simple window class

  1. #1
    Join Date
    Aug 2012
    Posts
    4

    New to C++, simple window class

    I've done a few years of C and Obj-C, and am now moving over to C++. I'm creating a simple window class and converting some old C game code as a means to learn, and I've come up with the following classes (Win32Window and Win32WindowManager). The problem is that the Win32Window class has a hWnd which gets initialised when it calls CreateWindow, and when the Win32Window object is destroyed it calls DestroyWindow. When the class's copy constructor is called (i.e. when the Win32Window object is put into the Win32WindowManager's list), the new object has the copied hWnd, but then the old object calls DestroyWindow.

    I was thinking of creating a wrapper class around hWnd that Win32Window has a smart pointer to, but feel like it should be stored within the Win32Window class itself, and there must be something simple I'm overlooking. How would you go about solving this, and is there anything else that I'm doing wrong or any bad programming techniques?

    Win32Window Header

    Code:
    #ifndef WIN32WINDOW_H_
    #define WIN32WINDOW_H_
    
    #include <windows.h>
    #include <gl/GL.h>
    #include <gl/GLU.h>
    #include <string>
    
    class Win32Window
    {
    	HWND hWnd; //Handle to window
    	HDC hDC; //Device context
    	HGLRC hRC; //OpenGL render context
    
    	int windowWidth;
    	int windowHeight;
    	int windowX;
    	int windowY;
    	bool fullscreen;
    
    	Win32Window();
    	void Init(std::wstring windowClassName);
    	void SetupPixelFormat();
    
    public:
    	Win32Window(std::wstring windowClassName);
    	Win32Window(const Win32Window &winSource);
    	Win32Window& operator= (const Win32Window &winSource);
    	~Win32Window();
    };
    
    #endif
    Win32Window source

    Code:
    #include <iostream>
    #include "win32Window.hpp"
    
    Win32Window::Win32Window()
    {
    	Init(0);
    }
    
    Win32Window::Win32Window(std::wstring windowClassName) : hWnd(0), hDC(0), hRC(0), windowWidth(800), windowHeight(600), windowX(0), windowY(0), fullscreen(false)
    {
    	std::cout << "Win32Window constructor" << std::endl;
    	Init(windowClassName);
    }
    
    Win32Window::Win32Window(const Win32Window &winSource)
    {
    	std::cout << "Win32Window copy constructor" << std::endl;
    	hWnd = winSource.hWnd;
    	hDC = winSource.hDC;
    	hRC = winSource.hRC;
    
    	windowWidth = winSource.windowWidth;
    	windowHeight = winSource.windowHeight;
    	windowX = winSource.windowX;
    	windowY = winSource.windowY;
    	fullscreen = winSource.fullscreen;
    }
    
    Win32Window& Win32Window::operator= (const Win32Window &winSource)
    {
    	std::cout << "Win32Window operator=" << std::endl;
    	
    	if(this == &winSource)
    		return *this;
    	
    	hWnd = winSource.hWnd;
    	hDC = winSource.hDC;
    	hRC = winSource.hRC;
    
    	windowWidth = winSource.windowWidth;
    	windowHeight = winSource.windowHeight;
    	windowX = winSource.windowX;
    	windowY = winSource.windowY;
    	fullscreen = winSource.fullscreen;
    
    	return *this;
    }
    
    void Win32Window::Init(std::wstring windowClassName)
    {
    	std::cout << "	Win32Window init" << std::endl;
    	//Initialize variables
    	int windowWidth = 800;
    	int windowHeight = 600;
    	bool fullscreen = false;
    
    	//Calculate x and y coords of where window should be
    	int windowX = GetSystemMetrics(SM_CXSCREEN);
    	int windowY = GetSystemMetrics(SM_CYSCREEN);
    
    	windowX /= 2;
    	windowX -= (windowWidth/2);
    
    	windowY /= 2;
    	windowY -= (windowHeight/2);
    
    	// Create the window
        hWnd = CreateWindow(
                windowClassName.c_str(),									// Name of window class
                windowClassName.c_str(),									// Title of window
                WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,	// Window style
                /*CW_USEDEFAULT,
                CW_USEDEFAULT,*/
    			windowX, windowY,											// x,y position of window
                windowWidth, windowHeight,									// w,h of window
                0,															// Parent window
                0,															// Menus
                GetModuleHandle(0),											// Application handle
                0);															// Multiple windows
    	
    	if(!hWnd) return;
    
    
    
    
    	hDC = GetDC(hWnd);
    
        SetupPixelFormat();
    
        /*hRC = wglCreateContext(hDC);
        wglMakeCurrent(hDC, hRC);
    
        glClearColor(0, 0, 0, 0.5);
        glClearDepth(1.0);
        glEnable(GL_DEPTH_TEST);*/
    
    
    
    	ShowWindow(hWnd, SW_SHOWDEFAULT);
    	UpdateWindow(hWnd);
    
        /*SetupPixelFormat();
    
        hRC = wglCreateContext(hDC);
        wglMakeCurrent(hDC, hRC);
    
        glClearColor(0, 0, 0, 0.5);
        glClearDepth(1.0);
        glEnable(GL_DEPTH_TEST);
    
    	//Now create an OpenGL context within the window
    	hDC = GetDC(*/
    }
    
    void Win32Window::SetupPixelFormat()
    {
        PIXELFORMATDESCRIPTOR pfd, *ppfd;
        int pixelformat;
    
        ppfd = &pfd;
    
        ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
        ppfd->nVersion = 1;
        ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
        ppfd->dwLayerMask = PFD_MAIN_PLANE;
        ppfd->iPixelType = PFD_TYPE_COLORINDEX;
        ppfd->cColorBits = 16;
        ppfd->cDepthBits = 16;
        ppfd->cAccumBits = 0;
        ppfd->cStencilBits = 0;
    
        pixelformat = ChoosePixelFormat(hDC, ppfd);
        SetPixelFormat(hDC, pixelformat, ppfd);
    }
    
    Win32Window::~Win32Window()
    {
    	std::cout << "Win32Window destructor" << std::endl;
    	ReleaseDC(hWnd, hDC);
    	DestroyWindow(hWnd);
    }
    Win32WindowManager header

    Code:
    #ifndef WIN32WINDOWMANAGER_H_
    #define WIN32WINDOWMANAGER_H_
    
    #include <windows.h>
    #include <gl/GL.h>
    #include <gl/GLU.h>
    #include "win32Window.hpp"
    #include <list>
    
    class Win32WindowManager
    {
    	std::list<Win32Window> windowList;
    	std::wstring windowClassName;
    
    	void Init();
    	static LONG WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM  lParam);
    
    public:
    	Win32WindowManager();
    	~Win32WindowManager();
    
    	int CreateNewWindow();
    	void DestroyWindow(int id);
    	int NumberOfWindows();
    };
    
    #endif
    Win32WindowManager source

    Code:
    #include "win32WindowManager.hpp"
    #include <iostream>
    
    Win32WindowManager *activeWindowManager;
    
    Win32WindowManager::Win32WindowManager() : windowList(), windowClassName(L"RAGE Window")
    {
    	//Create and register the app-specific Window class
    	Init();
    }
    
    Win32WindowManager::~Win32WindowManager()
    {
    	windowList.clear();
    }
    
    void Win32WindowManager::Init()
    {
    	activeWindowManager = this;
    
    	//If the window list already has windows in it, remove them from the list
    	windowList.clear();
    
    	//Create and register the Window class for this app - if already registered, this will return false
    	WNDCLASS wndclass;
    	//wndclass.cbSize		   = sizeof(WNDCLASSEX);
        wndclass.style         = 0;
        wndclass.lpfnWndProc   = (WNDPROC)WndProc;
        wndclass.cbClsExtra    = 0;
        wndclass.cbWndExtra    = 0;
        wndclass.hInstance     = GetModuleHandle(0);
        wndclass.hIcon         = LoadIcon(0, windowClassName.c_str());
        wndclass.hCursor       = LoadCursor(0,IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wndclass.lpszMenuName  = windowClassName.c_str();
        wndclass.lpszClassName = windowClassName.c_str();
    
    	// Register the window class
        if (!RegisterClass(&wndclass)) return;
    }
    
    LONG WINAPI Win32WindowManager::WndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM  lParam)
    {
    		std::cout << "Received message" << std::endl;
    		switch (uMsg)
    		{
    		case WM_MOUSEMOVE:
    		case WM_LBUTTONDOWN:
    		case WM_LBUTTONUP:
    		case WM_RBUTTONDOWN:
    		case WM_RBUTTONUP:
    		case WM_MBUTTONDOWN:
    		case WM_MBUTTONUP:
    		case WM_XBUTTONDOWN:
    		case WM_XBUTTONUP:
    			//handleMouseMessage(hWnd, uMsg, wParam, lParam);
    			return 0;
    			break;
    
    		case WM_INPUT:
    			//handleInputMessage(hWnd, uMsg, wParam, lParam);
    			return 0;
    			break;
    
    		case WM_SIZE:
    			//ResizeGraphics();
    			break;
    
    		case WM_CLOSE:
    			{
    				//Find which vector in our window vector has this hWnd
    				int windowID = 0;
    
    				//Destroy this window from our vector and the hWnd from Windows
    				activeWindowManager->DestroyWindow(windowID);
    			}
    			break;
     
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			break;
    
    		case WM_SYSCOMMAND:
    			//ToggleFullscreen();
    			break;
     
    		// Default event handler
    		default: 
    			return DefWindowProc (hWnd, uMsg, wParam, lParam); 
    			break; 
    		} 
     
    		return 1;
    }
    
    int Win32WindowManager::CreateNewWindow()
    {
    	int windowID = windowList.size();
    
    	Win32Window newWindow(windowClassName);
    	windowList.push_back(newWindow);
    
    	return windowID;
    }
    void Win32WindowManager::DestroyWindow(int id)
    {
    	std::list<Win32Window>::iterator it;
    	it = windowList.begin();
    	std::advance(it, id);
    
    	windowList.erase(it);
    }
    
    int Win32WindowManager::NumberOfWindows()
    {
    	return windowList.size();
    }

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    1,999

    Re: New to C++, simple window class

    Quote Originally Posted by Rajveer86 View Post
    The problem is that the Win32Window class has a hWnd which gets initialised when it calls CreateWindow, and when the Win32Window object is destroyed it calls DestroyWindow. When the class's copy constructor is called (i.e. when the Win32Window object is put into the Win32WindowManager's list), the new object has the copied hWnd, but then the old object calls DestroyWindow.
    So the lifetime of the Win32Window is tied to the time the window exists. Then what does it mean if you copy an instance of Win32Window? Do you create a new window with the same settings?
    Who is responsible for creating windows? Can the application programmer simply create a window by instantiating and initializing a Win32Window? Or can a window only be created by the window manager? In the former case, what is the role of the manager?
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    5,877

    Re: New to C++, simple window class

    The problem is that the Win32Window class has a hWnd which gets initialised when it calls CreateWindow, and when the Win32Window object is destroyed it calls DestroyWindow. When the class's copy constructor is called (i.e. when the Win32Window object is put into the Win32WindowManager's list), the new object has the copied hWnd, but then the old object calls DestroyWindow.
    If calling DestroyWindow in destructor is a problem, then just don't call it. Instead, notify manager about assigning hWnd to increment window ref counter and releasing hWnd to decrement the counter. This way manager could be aware of ref counter reaching zero, which means the window may be destroyed by manager.

    I have to admit, the entire design seems vague. What is Manager, and why it implements window procedure? Why do you need window size be stored in window class while this information can be directly get from Windows any time you want? Why do you need window DC be constantly open?

    And what's wrong with other libraries like Qt, MFC, WTL, etc.?
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center