Archived

This topic is now archived and is closed to further replies.

Shadow1234567890

Window will not show up

Recommended Posts

I have been reading in my book for a while and I tried writing a simple windows program from scratch. I have been scrutinizing the code for quite some time. It even got to the point where I had to open the book back up again and compare my code (which I unsuccessfully tried writing almost totally by myself) with the code from the book. I still cannot find my error. The code compiles, but doesn''t execute. If you can help me, I will love you for all eternity. The code is not documented.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>

HDC g_hDc;

void SetupPixelFormat(HDC hDc) {
	int nPixelFormat;
	static PIXELFORMATDESCRIPTOR pfd = { 
			sizeof(PIXELFORMATDESCRIPTOR),
			1,
			PFD_DRAW_TO_WINDOW |
			PFD_SUPPORT_OPENGL |
			PFD_DOUBLEBUFFER,
			PFD_TYPE_RGBA,
			32,
			0,0,0,0,0,0,
			0,
			0,
			0,
			0,0,0,0,
			16,
			0,
			0,
			PFD_MAIN_PLANE,
			0,
			0,0,0
	};
	nPixelFormat = ChoosePixelFormat(hDc, &pfd);
	SetPixelFormat(hDc, nPixelFormat, &pfd);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static HGLRC hRc;
static HDC hDc;
int width, height;
switch(message) {
case WM_CREATE:
	hDc = GetDC(hwnd);
	g_hDc = hDc;
	SetupPixelFormat(hDc);
	wglCreateContext(hDc);
	wglMakeCurrent(hDc, hRc);
	
case WM_CLOSE:
	wglMakeCurrent(hDc, NULL);
	wglDeleteContext(hRc);

	DestroyWindow(hwnd);		////////This was suggested by someone else, not from the book!

	PostQuitMessage(0);

	return 0;
	break;

case WM_PAINT:
	height = HIWORD(lParam);
	width = LOWORD(lParam);
	if(height == 0) 
		height = 1;

	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	return 0;
	break;


default:
	break;
	}

return (DefWindowProc(hwnd, message, wParam, lParam));
}

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
	WNDCLASSEX WindowClass;
	HWND hwnd;
	MSG msg;
	bool done;
	WindowClass.cbSize = sizeof(WNDCLASSEX);
	WindowClass.style = CS_HREDRAW | CS_VREDRAW;
	WindowClass.lpfnWndProc = WndProc;
	WindowClass.cbClsExtra = 0;
	WindowClass.cbWndExtra = 0;
	WindowClass.hInstance = hInstance;
	WindowClass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
	WindowClass.hCursor = LoadCursor(hInstance, IDC_CROSS);
	WindowClass.hbrBackground = NULL;
	WindowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
	WindowClass.lpszClassName = "My class";
	WindowClass.lpszMenuName = "My windows application";	

	if(!RegisterClassEx(&WindowClass))
		return 0;

		hwnd = CreateWindowEx(NULL,
		"My class",
		"My window",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU | WS_CLIPCHILDREN |
		WS_CLIPSIBLINGS,
		0, 0, 
		512, 512,
		NULL,
		NULL,
		hInstance,
		NULL);
		
		if(!hwnd)
			return 0;

		done = false;

		ShowWindow(hwnd, SW_SHOW);
		UpdateWindow(hwnd);

		while(!done) {
			PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
			if(msg.message == WM_CLOSE)
				done = true;

			else {
				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				glLoadIdentity();
				glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
				glColor3f(0.0f, 1.0f, 0.0f);
				glBegin(GL_LINES);
					glVertex3f(0.0f, 0.0f, -1.0f);
					glVertex3f(1.0f, 1.0f, -1.0f);
				glEnd();

				SwapBuffers(g_hDc);
				TranslateMessage(&msg);
				DispatchMessage(&msg);

			}
		}
		return msg.wParam;
}
 
Like I said, I don''t get any errors or warnings, but for some reason nothing shows up.

Share this post


Link to post
Share on other sites
hum i notice somehting but i dont if it really isnthe problem.. the msg.message.. change to msg.wParam.. also the last return would work fine with return 0.... other thing.. the wglCreateContext (hDc) to what ?? tri this hRc = wglCreateContext (hDc) ... and make both wglCreateContext and wglMakeCurrent (hDc,hRc) inside the other funcion called setuuppixelformat.. if i''m not mistake .. strange the gl/ should not work it''s gl\whatever.h ...

Metal Typhoon

Share this post


Link to post
Share on other sites
One thing I noticed is that in your call to wglCreateContext, you didn't assign the context created to hRc...so there is no rendering context for you to render with. you need to put
hRc = wglCreateContext(hDc);

the code ran and worked once that change had been made

[edited by - gowron67 on August 12, 2002 4:45:16 PM]

Share this post


Link to post
Share on other sites
case WM_CREATE:
   hDc = GetDC(hwnd);
   g_hDc = hDc;
   SetupPixelFormat(hDc);
   wglCreateContext(hDc);
   wglMakeCurrent(hDc, hRc);
   return 0 ;

AND

while(!done) {
   if(PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE)){
      if(msg.message == WM_QUIT)
         done = true;
   
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   else {
      ...
   }
}

Also, yeah. You''ll want to store the rendering context and so you can actually draw.

Peace,
ZE.


//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites
I see where I should''ve assigned the wglCreateContext(hDc) to something. I changed that in my WM_CREATE: case in my wndproc (the only place it seems that should be changed) and the code does not run.

case WM_CREATE:
hDc = GetDC(hwnd);
g_hDc = hDc;
hRc = wglCreateContext(hDc);
SetupPixelFormat(hDc);
wglMakeCurrent(hDc, hRc);


That is what it looks like, is that correct?

Share this post


Link to post
Share on other sites
A few more things:

*[EDIT] DON'TUse NULL instead of 0 unless you defined NULL yourself.
*Don't use globals, ever.
*Don't set your background to NULL/0. If you're having trouble with an explicit cast error, then explicitly cast! (e.g. hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH))
*return 0 from all the messages you process (there might be exceptions to that sometimes)
*Don't use glaux. All you might need it for is bitmap loading, and you can write your own.
*I would strongly advise you to set up your perspective stuff within WM_SIZE, rather than WM_PAINT.
*Only process messages when you get them. That is, PeekMessage will return true if you have received a message from the queue, and only then do you need to check for a WM_QUIT (not WM_CLOSE) and dispatch it.
*I'd advise that you add CS_OWNDC to your class styles
*When loading icons and cursors that are already defined (e.g. IDI_WINLOGO, IDC_ARROW, IDC_CROSS), don't set the hInstance to the hInstance of your application. Rather, set it to NULL/0 unless you are loading the icon from a file or a resource

That's about it.

[edited by - zealouselixir on August 12, 2002 10:34:51 PM]

Share this post


Link to post
Share on other sites
Tilch is right- you need to return from WM_CREATE, otherwise execution proceeds to your code under WM_CLOSE, where you call DestroyWindow.
this is useful if you want do the same thing for two or more different messages:

case WM_KEYDOWN:
case WM_LBUTTONDOWN:
//do something here
return 0;

whatever you put in between WM_LBUTTONDOWN will execute in the case of a keydown or a left mouse button click.
This same concept is your problem because you are calling DestroyWindow directly after WM_CREATE, so you never even show it before it''s destruction...and you probably dont want to destroy it until you close your application. That may be your problem as far as getting the window to show up. You should add more error handling, like checking the return of the API functions you call. By the way i am by no means an expert, I''m a beginner. these are just some things i''ve learned from my own mistakes.
one other thing- it is redundant to call break after return because return ends the function, whereas break just exits the switch. this is not an error that would cause problems, but i hope you can better understand what is going on in your code.

Share this post


Link to post
Share on other sites
Hey guys, you have been MORE than helpful. I have saved just about everything in this post in text files. I don't really know how to learn this freakin API...I just read OpenGL game programming, I take notes, I write down what Winmain and wndproc are supposed to accomplish and then I try to write the program on my own. A lot of the stuff you guys suggested goes against what i learned in ogl game programming (e.g the global variables) but then again they have made plenty of mistakes in that book.

Also, do you guys have any suggestions for learning the OpenGL api. I mean are there any special rituals you guys have when reading or coding or whatnot? Thanks again for helping me and being cool.

[edited by - Shadow1234567890 on August 13, 2002 10:15:15 AM]

Share this post


Link to post
Share on other sites
One more error I have encountered...when I am doing something wrong I get this error: cannot open Debug/Opengl3.exe for writing.

This means that I can''t compile it, and I can''t shut down my program (it runs in the background and uses 99% of my processor). I have to restart my computer and if i am lucky I will be able to compile. Any special reason why this is happening?

Now I must go restart

Share this post


Link to post
Share on other sites
quote:
Original post by Shadow1234567890
One more error I have encountered...when I am doing something wrong I get this error: cannot open Debug/Opengl3.exe for writing.
Any special reason why this is happening?

Now I must go restart


Uh. Okay. Here''s what''s happening. Your window is getting destroyed, but the application is not terminating. Are you sure your message loop is set up in the way that I posted? You need to set done to true when Msg.message is equal to WM_QUIT.

There may be quirks with shutting down your application due to things your operating system does. Which flavor of Windowz are you on?

Also, next time that happens, just hit Ctrl+Alt+Del and kill the process manually with the task manager, no need to restart. The process should have the same name as your project.

Peace,
ZE.


//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites
depending on how your message loop is set up, you could also add this inside the loop:

if(msg.message == WM_QUIT)
break;

then when you recieve a quit message your loop will terminate. note that a quit message must be put in the queue by you. You do this with PostQuitMessage in your WM_CLOSE handler, but most of the time you should put it in WM_DESTROY so that if anything else destroys your window your program will still terminate, freeing up your memory and allowing the executable file to be written to.

Share this post


Link to post
Share on other sites
Okay, from your advice my program runs fine (as far as I know). I have compiled and ran it 10 times, and nothing bad has happened. The image I created shows up fine. The window shuts down, and it is no longer running in the background when i hit ctrl alt del. I am running windows 98SE, so I cannot close things down with ctrl alt del (my system freezes). One more question, do I still need DestroyWindow(hwnd) in my WM_CLOSE case? I already have PostQuitMessage(0); in my WM_CLOSE.

Again, thank you guys for your help, I really do appreciate it.

Share this post


Link to post
Share on other sites
Here''s the deal. Somehow or another you have to release everything, whether when destroying the window or when the application is closing. Your window IIRC will receive a WM_DESTROY message upon the application''s termination, so you can just deinit your API and kill the window from there, and then do nothing but posting WM_QUIT within the WM_CLOSE handler (via PostQuitMessage(...). Then, you might have a shutdown function after your message loop that unregisters the class and does whatever else is necessary.

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites