Worked on XPS

Hello -

I am new to OpenGL, but had a working example of code for rotating triangles working on XPS. I got a new computer running Windows 7 and now I have built a version using Windows VS 2010 Express. It compiles and I can step through it in debug, but the window is blank. I tried changing glClearColor from 0 to 255 to see if that had an impact, but nothing changed.

What am I missing?

Thanks for your help.

Steve

#include “stdafx.h”
#include “DrawVtxs081912.h”

#define MAX_LOADSTRING 100
#pragma comment(lib,“opengl32.lib”)

// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

HWND hWnd;

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

float theta = 0.0f;

HDC hDC;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_DRAWVTXS081912, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
	return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DRAWVTXS081912));




// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
	hDC = GetDC(msg.hwnd);

	if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
	{

		// OpenGL animation code goes here
		glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
		glClear( GL_COLOR_BUFFER_BIT );
		
		glPushMatrix();
		glRotatef( theta, 0.0f, 0.0f, 1.0f );
		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 );
		
		theta += 1.0f;

		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

return (int) msg.wParam;

}

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the ‘RegisterClassEx’
// function that was added to Windows 95. It is important to call this function
// so that the application will get ‘well formed’ small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style			= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc	= WndProc;
wcex.cbClsExtra		= 0;
wcex.cbWndExtra		= 0;
wcex.hInstance		= hInstance;
wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DRAWVTXS081912));
wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_DRAWVTXS081912);
wcex.lpszClassName	= szWindowClass;
wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);

}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
	wmId    = LOWORD(wParam);
	wmEvent = HIWORD(wParam);
	// Parse the menu selections:
	switch (wmId)
	{
	case IDM_ABOUT:
		DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
		break;
	case IDM_EXIT:
		DestroyWindow(hWnd);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	break;
case WM_PAINT:
	hdc = BeginPaint(hWnd, &ps);
	// TODO: Add any drawing code here...
	EndPaint(hWnd, &ps);
	break;
case WM_DESTROY:
	PostQuitMessage(0);
	break;
default:
	return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;

}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
	if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
	{
		EndDialog(hDlg, LOWORD(wParam));
		return (INT_PTR)TRUE;
	}
	break;
}
return (INT_PTR)FALSE;

}

mmm… where is the code that create the openGL context? No context == no command buffer, no command buffer no communication with video card.
You are not initializing openGL, what is XPS? how can this code ever worked?

Thanks for the hint. Looks like I omitted a function called EnableOpenGL that set up the device context.

Steve

Some other things wrong with that code.

You’re calling GetDC but don’t seem to be calling ReleaseDC on each pass through your main loop; this will give you a nasty memory leak.

GetMessage is probably not what you want to use here - PeekMessage is normally used instead.

Even if GetMesssage is intended, there’s a failure case where it can return -1 that you’re not catching - see GetMessage function (winuser.h) - Win32 apps | Microsoft Learn

[QUOTE=mhagain;1241813]Some other things wrong with that code.

You’re calling GetDC but don’t seem to be calling ReleaseDC on each pass through your main loop; this will give you a nasty memory leak.

GetMessage is probably not what you want to use here - PeekMessage is normally used instead.

Even if GetMesssage is intended, there’s a failure case where it can return -1 that you’re not catching - see Microsoft Learn: Build skills that open doors in your career

Thank you for commenting on the code.

I had seen PeekMessage previously in the example I used for this code.

Now if I use PeekMessage(&msg, hWnd, 0,0,PM_REMOVE) the window displays for one iteration through the loop. The it exits.

If I use GetMessage(&msg, NULL,0,0) , the triangle rotates only as long as I move the mouse over the Window. Otherwise it is static.

Have I used PeekMessage appropriately?

Thanks again for your comments and willingness to help.

Steve

// DrawVtxs081912.cpp : Defines the entry point for the application.
//

#include “stdafx.h”
#include “DrawVtxs081912.h”

#define MAX_LOADSTRING 100
#pragma comment(lib,“opengl32.lib”)

void EnableOpenGL(HWND hWnd, HDC*, HGLRC*);
void DisableOpenGL(HWND hWnd, HDC, HGLRC);

HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

// Global Variables:
HDC hDC;
HGLRC hRC;
HWND hWnd;

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

BOOL Done = FALSE;
MSG msg;
HACCEL hAccelTable;

float theta = 0.0f;

// Initialize global strings

LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_DRAWVTXS081912, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
	return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DRAWVTXS081912));

// Main message loop:

//while (PeekMessage(&msg, hWnd, WM_KEYFIRST|WM_MOUSEFIRST,WM_KEYLAST|WM_MOUSELAST, PM_REMOVE))
while (GetMessage(&msg, NULL, 0, 0))	
//while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
{
	hDC = GetDC(msg.hwnd);

	if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
	{
		// OpenGL animation code goes here
		glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
		glClear( GL_COLOR_BUFFER_BIT );
		
		glPushMatrix();
		glRotatef( theta, 0.0f, 0.0f, 1.0f );
		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 );
		
		theta += 1.0f;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	ReleaseDC(hWnd, hDC);
}

DisableOpenGL(hWnd, hDC, hRC);

DestroyWindow(hWnd);

return (int) msg.wParam;

}

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the ‘RegisterClassEx’
// function that was added to Windows 95. It is important to call this function
// so that the application will get ‘well formed’ small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style			= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc	= WndProc;
wcex.cbClsExtra		= 0;
wcex.cbWndExtra		= 0;
wcex.hInstance		= hInstance;
wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DRAWVTXS081912));
wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_DRAWVTXS081912);
wcex.lpszClassName	= szWindowClass;
wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);

}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
0, 0, 768, 768, NULL, NULL, hInstance, NULL);
//CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

EnableOpenGL( hWnd, &hDC, &hRC );

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
	wmId    = LOWORD(wParam);
	wmEvent = HIWORD(wParam);
	// Parse the menu selections:
	switch (wmId)
	{
	case IDM_ABOUT:
		DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
		break;
	case IDM_EXIT:
		DestroyWindow(hWnd);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	break;
case WM_PAINT:
	hdc = BeginPaint(hWnd, &ps);
	// TODO: Add any drawing code here...
	EndPaint(hWnd, &ps);
	break;
case WM_DESTROY:
	PostQuitMessage(0);
	break;
default:
	return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;

}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
	if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
	{
		EndDialog(hDlg, LOWORD(wParam));
		return (INT_PTR)TRUE;
	}
	break;
}
return (INT_PTR)FALSE;

}

// Enable OpenGL

void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int format;

// get the device context (DC)
*hDC = GetDC( hWnd );

// set the pixel format for the DC
ZeroMemory( &pfd, 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;
format = ChoosePixelFormat( *hDC, &pfd );
SetPixelFormat( *hDC, format, &pfd );

// create and enable the render context (RC)
*hRC = wglCreateContext( *hDC );
wglMakeCurrent( *hDC, *hRC );

}

// Disable OpenGL

void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent( NULL, NULL );
wglDeleteContext( hRC );
ReleaseDC( hWnd, hDC );
}

PeekMessage return true if there is a message in the queue, false otherwise.
Your message pump should look similar to this.


MSG    msg;
while(quitNotRequested)
{
  while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
  {
    DispatchMessage(&msg);
  }
  // do wonderful stuf here
}

There’s a full example here: Writing the Game Loop

The version under the “Keeping Awake” heading on that page will be sufficient for now.

[QUOTE=mhagain;1241852]There’s a full example here: Writing the Game Loop

The version under the “Keeping Awake” heading on that page will be sufficient for now.[/QUOTE]

Thanks for the help. I will now experiment with this simple code and see what I can discover.

[QUOTE=Rosario Leonardi;1241850]PeekMessage return true if there is a message in the queue, false otherwise.
Your message pump should look similar to this.


MSG    msg;
while(quitNotRequested)
{
  while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
  {
    DispatchMessage(&msg);
  }
  // do wonderful stuf here
}

[/QUOTE]

Thanks for the help.