GL window creation...

Started by
6 comments, last by Dave Hunt 19 years, 6 months ago
I've been creating GL windows for a looong time now, but after carefully reading WIN32 API doc's I'm confused. The reason is window destruction code as well as PeekMessage return codes. Concerning peek message API says we receive 0 if no message is available, or smthn else if there is something to process. I know that a lot of sources suggest checking against negative values, but I can't find a proof for it in peek routine docs. Concerning quit, it's even worse... As far as I understand messages are called this way WM_CLOSE->WM_DESTROY->WM_QUIT, but what if I skip message loop after WM_CLOSE and then call smthn like DestroyWindow? I should still get WM_DESTROY->WM_QUIT, though loop is allready skipped. Currently I am trying to avoid this hierarchy and use simplier exit routine, but now i'm wondering if I'm doing it right. Code below:

#include "main.h"

WNDCLASS wc;
HWND hWnd;
HDC hDC;
HGLRC hRC;  
MSG msg;
const int WSize = 512;
bool bQuit = false;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
					LPSTR lpCmdLine, int iCmdShow)
{
	memset(&wc, 0, sizeof(WNDCLASS));
	wc.style = CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(hInstance,(LPCSTR)IDI_ILARGE);
	wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszClassName = "WndClass";
	if(!RegisterClass(&wc))
		return 0;
	
	int screenx = GetSystemMetrics(SM_CXSCREEN);
	int screeny = GetSystemMetrics(SM_CYSCREEN);
	screenx=screenx/2-WSize/2;
	screeny=screeny/2-WSize/2;

	hWnd = CreateWindow("WndClass", "Generative Art", WS_POPUPWINDOW | WS_VISIBLE,
						screenx, screeny, WSize, WSize, NULL, NULL, hInstance, NULL);
	if(!hWnd)
		return 0;
	
	hDC = GetDC(hWnd);

	PIXELFORMATDESCRIPTOR pfd;
	memset(&pfd, 0, sizeof(pfd));
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 24;
	pfd.cDepthBits = 16;
	pfd.iLayerType = PFD_MAIN_PLANE;
	int iFormat = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, iFormat, &pfd);

	hRC = wglCreateContext(hDC);
	wglMakeCurrent(hDC, hRC);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	ShowWindow(hWnd, iCmdShow);

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

		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glPushMatrix();
		glBegin(GL_TRIANGLES);
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex2f(0.0f, 1.0f);
		glColor3f(0.0f, 1.0f, 0.0f);
		glVertex2f(0.87f, -0.5f);
		glColor3f(0.0f, 0.0f, 1.0f);
		glVertex2f(-0.87f, -0.5f);
		glEnd();
		glPopMatrix();

		SwapBuffers(hDC);
	}while(!bQuit);

	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(hRC);
	ReleaseDC(hWnd, hDC);

	DestroyWindow(hWnd);
	PostQuitMessage(0);

	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_QUIT:
	case WM_CLOSE:
	case WM_DESTROY:
		bQuit = true;
		return 0;

	case WM_CREATE:
		return 0;

	case WM_KEYDOWN:
		switch(wParam)
		{
		case VK_ESCAPE:
			bQuit = true;
			return 0;
		}
		return 0;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
}
______________________________Madman
Advertisement
well, if it works then go with it, however my windowing frame work handles the destory and close messages independantly and lets teh default handler deal with the 'quit' messages

long Window::OnClose( Window & wnd, long p0, long p1 ){	::DestroyWindow( wnd );	return 0;}long Window::OnDestroy( Window & wnd, long p0, long p1 ){	::PostQuitMessage( 0 );	return 0;}


btw, when posting code its best to use the source or code tag, forum FAQ has details on it
The WM_QUIT message is never dispatched to the window procedure, so there is no point in checking for it there.

The most common way to handle this is to have WM_CLOSE or WM_DESTROY call PostQuitMessage(0). Then, your loop is done like this:

while (true){    if (PeekMessage(...))    {        if (message is WM_QUIT)            break;        Translate()        Dispatch()    }    else    {        render stuff    }}

i wouldnt put the 'render stuff' bit in an 'else' block, you want that to execute every frame, not just when there isnt a message to process
Quote:Original post by _the_phantom_
i wouldnt put the 'render stuff' bit in an 'else' block, you want that to execute every frame, not just when there isnt a message to process


Not if the message you just dispatched invalidated your window handle. Otherwise, you might end up crashing in your render code.
I am not invalidating HWND in my message loop, and I am leaving render code without else. I guess my approach should be valid.

BTW, I was using code tag, all it does is font change & indent preserve.

CODE tag:

system("format c: -y");


SOURCE tag:
system("format c: -y");



______________________________Madman
Quote:Original post by Dave Hunt
Quote:Original post by _the_phantom_
i wouldnt put the 'render stuff' bit in an 'else' block, you want that to execute every frame, not just when there isnt a message to process


Not if the message you just dispatched invalidated your window handle. Otherwise, you might end up crashing in your render code.


On that note, your loop still isn't correct. As you only handle a single message per frame. You should handle all pending messages first, then move on to rendering your frame (if applicable). You also don't handle the quit case correctly.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:Original post by Washu
On that note, your loop still isn't correct. As you only handle a single message per frame. You should handle all pending messages first, then move on to rendering your frame (if applicable). You also don't handle the quit case correctly.


Since the only things in the loop are message handling and rendering, skipping the rendering when messages are present effecively takes care of handling all messages first without using an additional while loop.

Would you care to explain how the quit case handling is wrong?

This topic is closed to new replies.

Advertisement