Jump to content
  • Advertisement
Sign in to follow this  
_Madman_

OpenGL GL window creation...

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

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);
	}
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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
}
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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");




Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!