-
August 21st, 2012, 04:49 PM
#1
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();
}
-
August 22nd, 2012, 04:55 AM
#2
Re: New to C++, simple window class
Originally Posted by Rajveer86
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
-
August 26th, 2012, 04:54 AM
#3
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|