Sign in to follow this  

Window Creation in Win 7

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

Hello,

 

I need help with creating a Microsoft Window in Win 7. I've experimented with calls to DoCreateWindow() with no luck.

 

I'd like to create a full fledged window that can switch between full screen mode and windowed mode with many resolution modes available and also with double buffering.

 

I am attempting this using C++ in MS VS Express 2013 and would like to continue using both.

 

Any hints, tips or tricks?

Thanks!

Share this post


Link to post
Share on other sites

I found it useful to look at DXUT: 

https://dxut.codeplex.com/

 

Maybe another example to look at would be Freeglut:

http://freeglut.sourceforge.net/

 

I used both as examples for my physics testbed years ago and never ran into any issues. Both should have examples for what you are trying to achieve.

 

HTH,

-Dirk

Share this post


Link to post
Share on other sites
L. Spiro - the NEHE tutorial linked above did actually work after I added old glaux.h and .lib files to my code. But yes the code is from 2000 so, obsolete. At least I got something off the ground so not a complete waste.

And it looks like Win32 was the secret google search sauce I needed. Thanks!

Dirk - Thanks for those links! Checking now. :)

Share this post


Link to post
Share on other sites

video tuts if you are so inclined, both great series for learning btw...

 

From scratch

Handmade Hero Day 002 - Opening a Win32 Window
https://www.youtube.com/watch?v=4ROiWonnWGk

 

With GLFW
Ep. 1: Window - Sparky Engine (How To Make a Game Engine)
https://www.youtube.com/watch?v=Pid8JGlBdPY

Share this post


Link to post
Share on other sites
Thanks so much for all the sources guys!

I've made quite a few windows so far. Now my next question...

How do I configure a Microsoft window tomget out of the way and let me render using OpenGL ?

I've been through a fair amount of sell research in OpenGL using the latest versions of the OpenGL superbible. And while some of the example code works, I can't seem to draw using OpenGL in windows I've created myself.

I'd like to draw using OpenGL 4.5 but 4.3 seems to be the most recent version supported by most graphics cards.

Thanks Again!

Share this post


Link to post
Share on other sites

You need to set the window pixel format and then create an OpenGL context.

You should be able to pick out the parts required to get it running in your window from this example:

#include <windows.h>
#include <gl/gl.h>

#pragma comment (lib, "opengl32.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	// Window class
	WNDCLASSEX wc = {};
	wc.cbSize = sizeof(wc);
	wc.lpszClassName = TEXT("MyClass");
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.style = CS_OWNDC;
	RegisterClassEx(&wc);

	// Window
	HWND hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		TEXT("OpenGL Window"),
		WS_OVERLAPPEDWINDOW |
			WS_CLIPSIBLINGS |
			WS_CLIPCHILDREN,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);

	// Get DC
	HDC hDC = GetDC(hWnd);

	// Pixel format
	PIXELFORMATDESCRIPTOR pfd = {};
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags =
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER |
		PFD_SUPPORT_COMPOSITION;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 32;

	int pf = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pf, &pfd);

	// OpenGL context
	HGLRC hGLRC = wglCreateContext(hDC);

	wglMakeCurrent(hDC, hGLRC);

	// Get OpenGL version and set it as window title
	SetWindowTextA(hWnd, (char*)glGetString(GL_VERSION));

	// Main loop
	ShowWindow(hWnd, nCmdShow);
	while(true) {
		MSG msg;
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
			if(msg.message == WM_QUIT)
				break;
			else {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else {
			// Draw
			glClearColor(1.0f, 0.7f, 0.2f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT);

			SwapBuffers(hDC);
		}
	}

	// Clean up
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(hGLRC);

	UnregisterClass(wc.lpszClassName, hInstance);

	return 0;
}

// Window proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg) {
		case WM_DESTROY:
			PostQuitMessage(0);
		return 0;

		case WM_SIZE:
			// Resize GL rendering area to match window size
			glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

However, that will only really allow you to use quite old OpenGL functionality without some extra work, as the newer version functions aren't readily available in opengl32.lib. The default library only provides version 1.1 or something like that (even when the context version is 4.5).

 

To load more functions you need to request their function pointers from WGL while your GL context is current, for example to use the glCompileShader function:

PFNGLCOMPILESHADERPROC glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");

The function pointer will match a function in the NVidia or AMD driver for example, not in the system OpenGL DLL.

 

This is a bit tedious, and if you want to do it manually the best way is probably to download glcorearb.h from opengl.org and write a script that goes through it and loads all the functions into some appropriate wrapper or global pointers or something.

There are libraries written specifically to take care of all this, such as GLEW for example: http://glew.sourceforge.net/

It can take care of checking all extensions etc. for you and help make sure everything is loaded properly and detect when it isn't. This is especially useful when loading extensions that may be available only on some drivers. If you make sure the context version is 4.x and you load only core functionality matching that version it's just about loading all the function pointers.

Edited by Erik Rufelt

Share this post


Link to post
Share on other sites

GLEW is a third-party library that contains code for loading all those function addresses etc. I don't have a code example unfortunately, but their site shows how to use it, just click on Usage at glew.sourceforge.net.

Share this post


Link to post
Share on other sites

So I checked GLEW and it looks like the tutorials suggest a use GLUT for window creation and handling.

 

I'd like to use as much windows code as possible. ( I am a linux sysadmin learning windows programming so I can use the practice :)

 

Is it possible to use the GLEW extensions with windows code like WndPrc and LRESULT CALLBACK functions?

Share this post


Link to post
Share on other sites

Any OpenGL method called works on the OpenGL context that is 'current' on the calling thread, same thing with what GLEW calls OpenGL for.

Once wglMakeCurrent has been called the OpenGL context you have created is current on the thread, so everything will work the same as if the window was created with some other method.

Share this post


Link to post
Share on other sites

Hi Guys,

 

It's been a while but I've since been able to ( assumedly ) get glew working.. or maybe not because this code below crashes at runtime...

 

I am assuming the pointers didn't map correctly even tho the code compiles. Any have any advice?

#include <windows.h>
//#include <gl/gl.h>
#include <GL/glew.h>
//#include <GL/glut.h>

#pragma comment (lib, "opengl32.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc = {};
	wc.cbSize = sizeof(wc);
	wc.lpszClassName = TEXT("MyClass");
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.style = CS_OWNDC;
	RegisterClassEx(&wc);

	// Window
	HWND hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		TEXT("OpenGL Window"),
		WS_OVERLAPPEDWINDOW |
		WS_CLIPSIBLINGS |
		WS_CLIPCHILDREN,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
		);

	// Get DC
	HDC hDC = GetDC(hWnd);

	// Pixel format
	PIXELFORMATDESCRIPTOR pfd = {};
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags =
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER |
		PFD_SUPPORT_COMPOSITION;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 32;

	int pf = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pf, &pfd);

	// OpenGL context
	HGLRC hGLRC = wglCreateContext(hDC);

	wglMakeCurrent(hDC, hGLRC);

	// Get OpenGL version and set it as window title
	SetWindowTextA(hWnd, (char*)glGetString(GL_VERSION));

	// test opengl
	// glCompileShader(GL_VERTEX_SHADER_FILE);
	static const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0 };

	// Main loop
	ShowWindow(hWnd, nCmdShow);
	while (true) {
		MSG msg;
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
			if (msg.message == WM_QUIT)
				break;
			else {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else {
			// Draw
			if ((char*)glGetString(GL_VERSION) != NULL) {
				//glClearColor(0.8956f, 0.3451f, 0.2234f, 1.0f); // <--		THIS LINE WORKS FINE 0.2345f, 0.7845f, 0.8934f, 1.0f
				glClearBufferfv(GL_COLOR, 0, red); // <-- THIS LINE CASUES A RUNTIME CRASH
			}
			else {
				glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //0.8956f, 0.3451f, 0.2234f, 1.0f
			}
			glClear(GL_COLOR_BUFFER_BIT);

			SwapBuffers(hDC);
		}
	}

	// Clean up
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(hGLRC);

	UnregisterClass(wc.lpszClassName, hInstance);

	return 0;
}

// Window proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_SIZE:
		// Resize GL rendering area to match window size
		glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites

ok.

 

Here is some updated code. I added in the glewinit() section and found that it does return GLEW_OK but my function to color the buffer and display it either doesnt run or leaves the buffer empty to show a black window.

 

Further help?

#include <windows.h>
//#include <gl/gl.h>
#include <GL/glew.h>
//#include <GL/glut.h>
#include <iostream>

using namespace std;

#pragma comment (lib, "opengl32.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	//ExitProcess(100);
	WNDCLASSEX wc = {};
	wc.cbSize = sizeof(wc);
	wc.lpszClassName = TEXT("MyClass");
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.style = CS_OWNDC;
	RegisterClassEx(&wc);

	// Window
	HWND hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		TEXT("OpenGL Window"),
		WS_OVERLAPPEDWINDOW |
		WS_CLIPSIBLINGS |
		WS_CLIPCHILDREN,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
		);

	// Get DC
	HDC hDC = GetDC(hWnd);

	// Pixel format
	PIXELFORMATDESCRIPTOR pfd = {};
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags =
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER |
		PFD_SUPPORT_COMPOSITION;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 32;

	int pf = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pf, &pfd);

	// OpenGL context
	HGLRC hGLRC = wglCreateContext(hDC);

	wglMakeCurrent(hDC, hGLRC);
	
	glewExperimental = GL_TRUE;
	GLenum err = glewInit();
	if (err != GLEW_OK)
	{
		//Problem: glewInit failed, something is seriously wrong.
		cout << "glewInit failed, aborting." << endl;
		ExitProcess(100); //<-- this does not run.
	}

	// Get OpenGL version and set it as window title
	SetWindowTextA(hWnd, (char*)glGetString(GL_VERSION));

	// test opengl
	// glCompileShader(GL_VERTEX_SHADER_FILE);
	static const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0 };

	// Main loop
	ShowWindow(hWnd, nCmdShow);
	while (true) {
		MSG msg;
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
			if (msg.message == WM_QUIT)
				break;
			else {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else {
			// Draw
			if ((char*)glGetString(GL_VERSION) != NULL) {
				//glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //0.8956f, 0.3451f, 0.2234f, 1.0f
				glClearBufferfv(GL_COLOR, 0, red);
				ExitProcess(100); //<--- THIS EXITPROCESS RUNS
			}
			else {
				//glClearColor(0.8956f, 0.3451f, 0.2234f, 1.0f); 
				glClearBufferfv(GL_COLOR, 0, red);
				//ExitProcess(100);
			}
			glClear(GL_COLOR_BUFFER_BIT);

			SwapBuffers(hDC);
		}
	}

	// Clean up
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(hGLRC);

	UnregisterClass(wc.lpszClassName, hInstance);

	return 0;
}

// Window proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	case WM_SIZE:
		// Resize GL rendering area to match window size
		glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites

You might consider a single Form/Window as high as C# application created- and pass its handle to your c++ module to make context of it. Should be smoother and interesting to see the result right in this situation, since old ways of registering windows are not encouraged on windows 7+ and those ways sure have more pitfals than int he past, to be fully functional and accommodated.

Share this post


Link to post
Share on other sites

//The docs say the second arg to glClearBufferfv should be GL_DRAW_BUFFERi to clear and if it is GL_NONE then the operation does nothing. GL_NONE = 0, which you use, so try using GL_DRAW_BUFFER0 instead of 0 as the second arg.(incorrect)

Also remember to remove the glClear after your if-statement so that you don't re-clear it to the default clear color again before swap.

You seem to run into many of these weird problems caused by small mistakes in the details. Make it a habit to read the docs for the functions you use if they don't work right away, as well as use the debugger to single-step through the code, which is extremely helpful to solve these problems a hundred times faster than posting on GD.net about them.

I like this site for GL docs: http://docs.gl/

 

Do you use Visual Studio? If you don't use the debugger then start doing so, by default just press F9 on a particular line of code and then F5 to run with the debugger and the debugger will break on that line, where you can single-step with F10 and inspect variables with mouse-over. Faster than ExitProcess and std::cout.

Edited by Erik Rufelt

Share this post


Link to post
Share on other sites

Thanks again Erik!

 

Yes I do have trouble with the details. I've been wanting to do what I am doing now for years but never had the time. And I still don't :) But I am trying now anyway. I'll do my best to check and recheck the opengl and MSDN docs!

 

I really do appreciate all your help!

Share this post


Link to post
Share on other sites

I've edited my code as below but still get a black screen... *sigh*

			if ((char*)glGetString(GL_VERSION) != NULL) {
				//glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //0.8956f, 0.3451f, 0.2234f, 1.0f
				glClearBufferfv(GL_COLOR, GL_DRAW_BUFFER0, red);
				//ExitProcess(100); //<--- THIS EXITPROCESS RUNS
			}
			else {
				//glClearColor(0.8956f, 0.3451f, 0.2234f, 1.0f); 
				glClearBufferfv(GL_COLOR, GL_DRAW_BUFFER0, red);
				//ExitProcess(100);
			}
			glClear(GL_COLOR_BUFFER_BIT);

			SwapBuffers(hDC);

Share this post


Link to post
Share on other sites

This topic is 602 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this