Screensaver application not turning off after the dialog box closes - c++

I am trying to write a screensaver in C++. I have the preview window implemented, but I caught the problem of it not turning off because I had Task Manager open, and I saw 3 instances of "bounce.scr" open, obviously from the preview window. And don't get me wrong. I spent hours trying to get it to turn off, such as checking if the window is visible, and the parent window, using WM_SYSTEMCOMMAND with SC_CLOSE. It still won't close after the screensaver dialog box closes. Here is the code:
Sorry if it's hard to read, but I don't really comment my code.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <string.h>
#include <stdlib.h>
#include <sys/timeb.h>
struct BALL
{
float posX;
float posY;
float posZ;
float velX;
float velY;
float velZ;
float size;
float colorR;
float colorG;
float colorB;
};
float state;
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);
}
HDC scr_hdc;
bool done;
bool isPreview;
int timeFromStart = 0;
int prevX = 0;
int prevY = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HGLRC hRC;
static HDC hDC;
int width, height;
if (!IsWindowVisible(GetParent(hwnd)) && timeFromStart >= 5 && isPreview)
{
message = WM_CLOSE;
}
switch(message)
{
case WM_CREATE:
hDC = GetDC(hwnd);
scr_hdc = hDC;
SetupPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return 0;
break;
case WM_KEYDOWN:
case WM_MOUSEMOVE:
if (isPreview) break;
case WM_SYSCOMMAND:
if (isPreview)
{ if (wParam == SC_CLOSE) { } else { break; } }
case WM_CLOSE:
int x = LOWORD(lParam);
int y = HIWORD(lParam);
if (timeFromStart >= 5)
{
if ((x != prevX && y != prevX) || message != WM_MOUSEMOVE)
{
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
done = true;
//PostQuitMessage(0);
}
}
else
{
timeFromStart++;
}
prevX = x;
prevY = y;
return 0;
break;
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
int screensaver(HINSTANCE hInstance, int balls, HWND parent)
{
WNDCLASSEX windowClass;
HWND hwnd;
HWND desktopHWND;
MSG msg;
DWORD dwExStyle;
DWORD dwStyle;
RECT windowRect;
RECT desktopRect;
if (parent)
{
GetClientRect(parent, &windowRect);
windowRect.left = 0L;
windowRect.top = 0L;
isPreview = true;
}
else
{
desktopHWND = GetDesktopWindow();
GetWindowRect(desktopHWND, &desktopRect);
windowRect.left = 0L;
windowRect.right = desktopRect.right;
windowRect.top = 0L;
windowRect.bottom = desktopRect.bottom;
isPreview = false;
}
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(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = "ScreensaverClass";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if (!RegisterClassEx(&windowClass))
{
return 0;
}
//SetCapture();
/*DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = 800;
dmScreenSettings.dmPelsHeight = 600;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN != DISP_CHANGE_SUCCESSFUL); */
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
if (!parent)
{
ShowCursor(FALSE);
}
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
hwnd = CreateWindowEx(NULL, "ScreensaverClass",
"Screensaver",
dwStyle |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0,
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top,
NULL,
NULL,
hInstance,
NULL);
if (!hwnd)
{
return 0;
}
if (parent)
{
SetParent(hwnd, parent);
SetWindowLong(hwnd, -16, GetWindowLong(hwnd, -16) | 0x40000000);
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(79, (float)windowRect.right / (float)windowRect.bottom, .03f, 100);
glMatrixMode(GL_MODELVIEW);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
GLuint room = glGenLists(1);
glNewList(room, GL_COMPILE);
glBegin(GL_QUADS);
glColor4f(1,1,1,1);
glNormal3f(0,0,-1); // North Side
glVertex3i(0, 50, 50);
glVertex3i(50, 50, 50);
glVertex3i(50, 0, 50);
glVertex3i(0, 0, 50);
glNormal3f(-1,0,0); // East Side
glVertex3i(50, 50, 50);
glVertex3i(50, 50, 0);
glVertex3i(50, 0, 0);
glVertex3i(50, 0, 50);
glNormal3f(0,0,1); // South Side
glVertex3i(50, 50, 0);
glVertex3i(0, 50, 0);
glVertex3i(0, 0, 0);
glVertex3i(50, 0, 0);
glNormal3f(1,0,0); // West Side
glVertex3i(0, 50, 0);
glVertex3i(0, 50, 50);
glVertex3i(0, 0, 50);
glVertex3i(0, 0, 0);
glNormal3f(0,-1,0); // Top Side
glVertex3i(0, 50, 0);
glVertex3i(50, 50, 0);
glVertex3i(50, 50, 50);
glVertex3i(0, 50, 50);
glNormal3f(0,1,0); // Bottom Side
glVertex3i(0, 0, 50);
glVertex3i(50, 0, 50);
glVertex3i(50, 0, 0);
glVertex3i(0, 0, 0);
glEnd();
glEndList();
GLuint ball = glGenLists(1);
glNewList(ball, GL_COMPILE);
GLUquadric *s = gluNewQuadric();
gluSphere(s, 1, 10, 10);
glEndList();
struct BALL* ballsList = (struct BALL*)calloc(balls, sizeof(struct BALL));
for (int i = 0; i < balls; i++)
{
ballsList[i].posX = (float)(rand()%50);
ballsList[i].posY = (float)(rand()%50);
ballsList[i].posZ = (float)(rand()%50);
ballsList[i].velX = ((float)rand() / (float)RAND_MAX) - .5f;
ballsList[i].velY = ((float)rand() / (float)RAND_MAX) - .5f;
ballsList[i].velZ = ((float)rand() / (float)RAND_MAX) - .5f;
ballsList[i].size = (float)rand() / (float)RAND_MAX;
ballsList[i].colorR = (float)rand() / (float)RAND_MAX;
ballsList[i].colorG = (float)rand() / (float)RAND_MAX;
ballsList[i].colorB = (float)rand() / (float)RAND_MAX;
}
SetTimer(hwnd, 31, 50, (TIMERPROC) NULL);
struct timeb timeobj;
long lasttimestamp;
long thistimestamp;
float framemultiplier;
ftime(&timeobj);
lasttimestamp = (long)timeobj.time * 1000L + timeobj.millitm;
done = false;
state = 3;
float yaw = 0;
while (!done)
{
PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT)
{
state = 1;
done = true;
}
else
{
if (msg.message == WM_TIMER)
{
ftime(&timeobj);
thistimestamp = timeobj.time * 1000L + timeobj.millitm;
framemultiplier = (float)(thistimestamp - lasttimestamp) / 50;
yaw += framemultiplier;
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(yaw,0,1,0);
glTranslatef(-25,-25,-25);
glCallList(room);
for (int i = 0; i < balls; i++)
{
struct BALL *b = &ballsList[i];
b->posX += (b->velX * framemultiplier);
b->posY += (b->velY * framemultiplier);
b->posZ += (b->velZ * framemultiplier);
if (b->posX < b->size)
{
b->velX = -b->velX;
b->posX = b->size;
}
if (b->posY < b->size)
{
b->velY = -b->velY;
b->posY = b->size;
}
if (b->posZ < b->size)
{
b->velZ = -b->velZ;
b->posZ = b->size;
}
float fms = 50 - b->size;
if (b->posX > fms)
{
b->velX = -b->velX;
b->posX = fms;
}
if (b->posY > fms)
{
b->velY = -b->velY;
b->posY = fms;
}
if (b->posZ > fms)
{
b->velZ = -b->velZ;
b->posZ = fms;
}
b->velY -= .01f * framemultiplier;
glColor3f(b->colorR, b->colorG, b->colorB);
glPushMatrix();
glTranslatef(b->posX, b->posY, b->posZ);
glScalef(b->size, b->size, b->size);
glCallList(ball);
glPopMatrix();
lasttimestamp = thistimestamp;
}
SwapBuffers(scr_hdc);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/*ChangeDisplaySettings(NULL, 0);*/
ShowCursor(TRUE);
//ReleaseCapture();
KillTimer(hwnd, 31);
free(ballsList);
return msg.wParam;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if (strstr(lpCmdLine, "/s"))
{
return screensaver(hInstance, 30, NULL);
}
else if (strstr(lpCmdLine, "/p"))
{
HWND ptr = (HWND)atoi(lpCmdLine + 3);
screensaver(hInstance, 30, ptr);
}
return 0;
}

When you're making a preview window you should use WS_CHILD in stead of WS_POPUP, or you won't be notified of the parent-window closing.

You don't need to create your own window for preview.
You can use one created for you by Windows.
if( parent ){
hwnd= parent;
}else{
hwnd= CreateWindow ...
}
hDC= GetDC(hwnd);
SetupPixelFormat(hDC);
hRC= wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
And later after rendering check result of SwapBuffers. If it fails, then user have closed the preview, and window was destroyed, and it's time to quit.
if( !SwapBuffers(scr_hdc) )
break;
}
Just have in mind that your WndProc is not attach to that window. So there will be no WM_TIMER, WM_CREATE, WM_QUIT, while you are in preview.
Also remember not to destroy preview window, if you haven't created it.

Related

How to increase bitmap pixel size? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I'm struggling to find the way to increase pixel sizes in a win32 bitmap. Is there any way to do it?
I made a small win32 program below. When you run it, you should get a window with a very tiny red dot in the center. You can use up, down, left, and right arrow keys to control the dot.
/* compile: gcc test.c -o test -lgdi32 -Wl,-subsystem,windows */
// TODO fast way to update? resize pixel size? best coding practices?
#include <windows.h>
#define WND_WIDTH 500
#define WND_HEIGHT 500
#define ID_TIMER 1
void DrawBitmap(HDC hdc, RECT *rect, BITMAPINFO info, void *bmpMem)
{
int width = rect->right - rect->left;
int height = rect->bottom - rect->top;
StretchDIBits(hdc,
0,
0,
info.bmiHeader.biWidth,
info.bmiHeader.biHeight,
0,
0,
width,
height,
bmpMem,
&info,
DIB_RGB_COLORS,
SRCCOPY);
}
void UpdateBitmap(BITMAPINFO info, void *bmpMem, POINT pix)
{
int width = info.bmiHeader.biWidth;
int height = info.bmiHeader.biHeight;
BYTE *pixel = (BYTE *) bmpMem;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x == pix.x && y == pix.y)
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 255; /* red */
*pixel++ = 255; /* alpha */
}
else
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 0; /* red */
*pixel++ = 255; /* alpha */
}
}
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static BITMAPINFO info;
static void *bmpMem;
static POINT pixel;
switch (msg)
{
case WM_CREATE:
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
int width = rcClient.right - rcClient.left;
int height = rcClient.bottom - rcClient.top;
info.bmiHeader.biSize = sizeof(info.bmiHeader);
info.bmiHeader.biWidth = width;
info.bmiHeader.biHeight = height;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = 0;
info.bmiHeader.biXPelsPerMeter = 0;
info.bmiHeader.biYPelsPerMeter = 0;
info.bmiHeader.biClrUsed = 0;
info.bmiHeader.biClrImportant = 0;
bmpMem = VirtualAlloc(0, width * height * 4, MEM_COMMIT, PAGE_READWRITE);
pixel.x = width / 2;
pixel.y = height / 2;
if(!SetTimer(hWnd, ID_TIMER, 50, NULL))
{
MessageBox(hWnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
PostQuitMessage(1);
}
break;
}/*
case WM_PAINT:
{
RECT rcClient;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rcClient);
DrawBitmap(hdc, &rcClient, info, bmpMem);
EndPaint(hWnd, &ps);
break;
}*/
case WM_TIMER:
{
RECT rcClient;
HDC hdc = GetDC(hWnd);
GetClientRect(hWnd, &rcClient);
UpdateBitmap(info, bmpMem, pixel);
DrawBitmap(hdc, &rcClient, info, bmpMem);
ReleaseDC(hWnd, hdc);
break;
}
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_LEFT: pixel.x -= 1; break;
case VK_RIGHT: pixel.x += 1; break;
case VK_UP: pixel.y += 1; break;
case VK_DOWN: pixel.y -= 1; break;
}
break;
}
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
VirtualFree(bmpMem, 0, MEM_RELEASE);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const TCHAR szClassName[] = TEXT("MyClass");
WNDCLASS wc;
HWND hWnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 1;
}
hWnd = CreateWindow(szClassName,
TEXT("Title"),
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* this window style prevents window resizing */
CW_USEDEFAULT,
CW_USEDEFAULT,
WND_WIDTH,
WND_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if (hWnd == NULL)
{
MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
I want to increase the size of the tiny red dot and all other pixels in the bitmap. I tried to decrease the width and height like this
switch (msg)
{
case WM_CREATE:
{
//RECT rcClient;
//GetClientRect(hWnd, &rcClient);
int width = 30;
int height = 30;
I expected to see a big red dot at the center but I got the white screen instead. How can I edit the code to display bigger pixels?
You are creating a single red pixel in your UpdateBitmap:
if (x == pix.x && y == pix.y)
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 255; /* red */
*pixel++ = 255; /* alpha */
}
If you want a bigger "dot" - define a radius somewhere:
int r = 17;
and change your condition to
if ((x - pix.x)* (x - pix.x) + (y - pix.y)* (y - pix.y) <= r*r)
To scale the entire bitmap, modify DrawBitmap:
void DrawBitmap(HDC hdc, RECT* rect, BITMAPINFO info, void* bmpMem)
{
int width = rect->right - rect->left;
int height = rect->bottom - rect->top;
int scale = 7;
StretchDIBits(hdc,
-(info.bmiHeader.biWidth * scale - width) / 2,
-(info.bmiHeader.biHeight * scale - height) / 2,
info.bmiHeader.biWidth * scale,
info.bmiHeader.biHeight * scale,
0,
0,
width,
height,
bmpMem,
&info,
DIB_RGB_COLORS,
SRCCOPY);
}
StretchDIBits will stretch (or shrink) the area of the source (specified by 0, 0, width, height) into some are of the destination.
In this example, I magnified the size of the destination by the factor of scale - so the image will stretch. The negative offset is to "center" the image over destination; you can use 0,0 to keep the top-left anchor.

OpenGL Flashing?

I'm trying to draw some text in OpenGL while the program draw a cube or any Opengl native so, when I try to put the text on the screen it flashes very fast and I don't know why, I tried to change the Sleep value and nothing...
The code is below; here is a GIF showing the problem.
The green background is the cube, the camera is very close to the background, you can move back with the NUM_2.
#include <windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "default.h"
using namespace std;
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
DWORD WINAPI WorkLoop(LPVOID PARAMS);
void keyScan (MSG msg, Camera cam);
HDC hDC;
HGLRC hRC;
HWND hwnd;
RECT WBounds;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
MSG msg;
BOOL bQuit = FALSE;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "GLSample";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;
Screen ();
if (!RegisterClassEx(&wcex))
return 0;
hwnd = CreateWindowEx(0,
"GLSample",
"OpenGL Testing",
WS_OVERLAPPEDWINDOW,
Scr.sx/2-630,
Scr.sy/2-450,
1260,
900,
NULL,
NULL,
hInstance,
NULL);
GetClientRect(hwnd, &WBounds);
ShowWindow(hwnd, nCmdShow);
EnableOpenGL(hwnd, &hDC, &hRC); ///ENABLE OPENGL
Camera cam = Camera (0, 0, -1);
CreateThread(0, 0x1000, &WorkLoop, 0, 0, 0);
while (!bQuit)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) bQuit = TRUE;
else
{
keyScan (msg, cam);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
renderSimulation (cam);
SwapBuffers (hDC);
}
Sleep(1);
}
DisableOpenGL(hwnd, hDC, hRC);
DestroyWindow(hwnd);
return msg.wParam;
}
DWORD WINAPI WorkLoop(LPVOID PARAMS)
{
while (true)
{
InvalidateRect(hwnd, &WBounds, true);
Sleep(33);
}
ExitThread(0);
}
float x = 0.0f, y = 0.0f, z = 0.0f;
float rx = 0.0f, ry = 0.0f, rz = 0.0f;
char* textas = "test";
void keyScan (MSG p, Camera cam)
{
if (p.message == WM_KEYDOWN)
{
if (p.wParam == ARROW_RIGHT) {x += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_LEFT) {x -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_UP) {y += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_DOWN) {y -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == NUM_8) {z += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == NUM_2) {z -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == L) SetFullScreen (p.hwnd, hDC, hRC);
else if (p.wParam == K) textas = "cambiado";
}
}
HFONT Font = CreateFont(40, 0, 0, 0,FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, FF_MODERN, TEXT("Arial"));
HPEN BoxPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
HPEN OutlinePen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
HPEN CHPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
HBRUSH CHBrush = CreateSolidBrush(RGB(0, 255, 0));
void drawtext(HDC hdc, int x, int y, const char * text)
{
SetBkMode (hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0, 255, 0));
SetBkColor(hdc, RGB(255, 255, 255));
TextOutA(hdc, x, y, text, strlen(text));
}
/*void Draw(HDC hdc, int x, int y, float dist)
{
int width = 20000 / dist;
int height = 45000 / dist;
SelectObject(hdc, OutlinePen);
SelectObject(hdc, WHITE_BRUSH);
Rectangle(hdc, x - (width / 2), y - height, x + (width / 2), y);
SelectObject(hdc, BoxPen);
Rectangle(hdc, x - (width / 2), y - height, x + (width / 2), y);
SetTextAlign(hdc, TA_CENTER | TA_NOUPDATECP);
std::stringstream ss2;
ss2 << "Dist: " << dist << " m";
drawtext(hdc, x, y + 90, ss2.str().c_str());
}*/
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_PAINT:
{
int win_width = WBounds.right - WBounds.left;
int win_height = WBounds.bottom + WBounds.left;
PAINTSTRUCT ps;
HDC Memhdc;
HDC hdc;
HBITMAP Membitmap;
hdc = BeginPaint(hwnd, &ps);
Memhdc = CreateCompatibleDC (hdc);
Membitmap = CreateCompatibleBitmap (hdc, win_width, win_height);
SelectObject (Memhdc, Membitmap);
//FillRect (Memhdc, &WBounds, WHITE_BRUSH);
SelectObject (Memhdc, Font);
SetTextAlign (Memhdc, TA_LEFT | TA_NOUPDATECP);
drawtext(Memhdc, 100, 100, textas);
//Draw (Memhdc, 20, 50, 90.0);
/*SelectObject(Memhdc, CHPen);
SelectObject(Memhdc, CHBrush);*/
BitBlt (hdc, 0, 0, win_width, win_height, Memhdc, 0, 0, SRCCOPY);
DeleteObject(Membitmap);
DeleteDC(Memhdc);
DeleteDC(hdc);
EndPaint(hwnd, &ps);
ValidateRect(hwnd, &WBounds);
}
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
}
}
case WM_ERASEBKGND:
return 1;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
Two problems with your program:
Setting a background brush for a OpenGL window will make the OS visibly clear the window with the brush before sending WM_PAINT (upon which you overdraw with OpenGL). By using InvalidateRect you're triggering this erase-with-background before WM_PAINT
Double buffered OpenGL pixelformats and drawing with the GDI don't go well together. If you want to draw text you'll have to do it differently. For example drawing to a DIBSECTION DC and then drawing that bitmap per using a textured quad. Or using a font rasterizer that addresses OpenGL (FTGL, Glyphy or the likes).

gluPerspective not working

I use gluPerspective to mainly increase the draw distance, but it doesn't seem to work.
This is how it shows in my code:
gluPerspective(0, 70/70, 0, 4333);
ratio: The window Width and Height is both 700 and they are constant, in case of wondering.
fovy: I put 0 because, "they" say that using 45 is very nice to draw, but it stops drawing on the screen.
This is the full code:
#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>
WNDCLASSEX wclass;
MSG msg;
HWND hwnd;
HDC hdc;
HDC p_hdc;
float t;
int red, green, blue, x, y, z;
void update()
{
RECT rec;
GetClientRect(hwnd, &rec);
InvalidateRect(hwnd, &rec, false);
UpdateWindow(hwnd);
t += 0.5f;
}
void game()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
gluPerspective(45, 70/70, 0.01f, 4333);
glPopMatrix();
SwapBuffers(hdc);
}
HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = WinProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "CLASS";
wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wclass))
{
MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
0, 0, 700, 700,
HWND_DESKTOP, NULL, hInstance, NULL
);
EnableOpenGL(hwnd, &hdc, &hrc);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
if(hwnd == NULL)
{
MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
}
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_TIMER:
game();
update();
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC win;
win = BeginPaint(hwnd, &ps);
p_hdc = win;
game();
EndPaint(hwnd, &ps);
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
*hDC = GetDC(hwnd);
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;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
What to do?
EDIT: THE NEW CODE
#include <Windows.h>
#include <gl\GL.h>
#include <gl/glut.h>
WNDCLASSEX wclass;
MSG msg;
HWND hwnd;
HDC hdc;
HDC p_hdc;
float t;
int red, green, blue, x, y, z;
float cx, cy, cz;
void handle_resize()
{
RECT rec;
GetClientRect(hwnd, &rec);
long width = rec.right - rec.left;
long height = rec.top - rec.bottom;
float aspect = (float)width/(float)height;
glViewport(0, 0, 700, 700);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, aspect, 0.01f, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void update()
{
RECT rec;
GetClientRect(hwnd, &rec);
InvalidateRect(hwnd, &rec, false);
UpdateWindow(hwnd);
t += 0.5f;
cz = -3;
}
void game()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
glPopMatrix();
SwapBuffers(hdc);
}
HGLRC hrc;
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpstr, int nCmdShow)
{
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = WinProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = "CLASS";
wclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wclass))
{
MessageBox(0, "Windows Class Registration Failure Detected!\nProgram Can't Be Initialized..", "Failure Detected", MB_ICONERROR | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
0, "CLASS", "OPENGL WORLD", WS_OVERLAPPEDWINDOW,
0, 0, 700, 700,
HWND_DESKTOP, NULL, hInstance, NULL
);
EnableOpenGL(hwnd, &hdc, &hrc);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_MODELVIEW);
if(hwnd == NULL)
{
MessageBox(0, "Windows Form Creation Failure..", "Failure", MB_ICONERROR | MB_OK);
}
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_TIMER:
game();
update();
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC win;
win = BeginPaint(hwnd, &ps);
p_hdc = win;
game();
EndPaint(hwnd, &ps);
break;
case WM_SIZE:
handle_resize();
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
*hDC = GetDC(hwnd);
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;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
gluPerspective(0, 70/70, 0, 4333);
^ nope ^ nope
fovy and zNear must both be positive and non-zero.
Try this:
gluPerspective( 45, 70/70, 0.1, 4333 );
EDIT: Push your camera back a bit too:
#include <GL/glut.h>
float t = 0;
void timer( int val )
{
t += 0.5f;
glutTimerFunc( 10, timer, 0 );
glutPostRedisplay();
}
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective( 45, w / h, 0.1, 4333.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -5 );
float norm = 1;
float z = 0;
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3f(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3f(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
As-per our comments, I made a few changes to your code that are necessary to properly deal with the perspective projection matrix and window sizing. There are still a number of things about this code that I do not like, such as drawing using a timer but this should at least address the small things.
New code:
void handle_resize (void)
{
RECT rec;
GetClientRect(hwnd, &rec);
long width = rec.right - rec.left;
long height = rec.top - rec.bottom;
float aspect = (float)width/(float)height;
glViewport (0, 0, width, height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (45, aspect, 0.01f, 4333);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
void game()
{
glClearColor(0, 0, 0, 0); // Do this first
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float norm = 1;
float z = 0;
red = 255;
green = 255;
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
glRotatef(t, 0, 1, 1);
glBegin(GL_TRIANGLES);
glColor3ub(255, 0, 0);
glVertex3f(-norm, norm, z);
glVertex3f(norm, norm, z);
glColor3ub(0, 110, 10);
glVertex3f(-norm, -norm, z);
glEnd();
//gluPerspective(45, 70/70, 0.01f, 4333); // GET THIS OUT OF HERE!!!
glPopMatrix();
SwapBuffers(hdc);
}
Changes to your window message handler:
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1, NULL);
break;
// NEW EVENT: Handle window size change
case WM_SIZE:
handle_resize ();
break;
Other things to note:
glColor3f clamps the floating-point value to the range [0.0,1.0], you were using values of 255 which is only appropriate if you use glColor3ub, which is essentially the same thing as glColor3f (1.0f, 1.0f, 1.0f).

Solving problems with concurrency c++ windows

I am learning opengl for the first time, and i am trying to make a simple program. My program runs in two threads, one thread renders the program on the screen, while the other thread updates the data of the program. However, sometimes when i try to close my program i get a nasty error message. I don't understand why, although i feel like it is a concurrency error. Here is my code.
Main.cpp
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define GLX_GLXEXT_LEGACY
#include <windows.h>
#include "glwindow.h"
#include "example.h"
#include "util.h"
void updateThread(Example* example);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
{
const int windowWidth = 1024;
const int windowHeight = 768;
const int windowBPP = 16;
const int windowFullscreen = false;
GLWindow programWindow(hInstance);
Example example;
programWindow.attachExample(&example);
if (!programWindow.create(windowWidth, windowHeight, windowBPP, windowFullscreen))
{
MessageBox(NULL, "Unable to create the OpenGL Window", "An error occurred", MB_ICONERROR | MB_OK);
programWindow.destroy();
return 1;
}
if (!example.init())
{
MessageBox(NULL, "Could not initialize the application", "An error occurred", MB_ICONERROR | MB_OK);
programWindow.destroy();
return 1;
}
HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) updateThread, &example, 0, 0);
example.setThread(&thread);
while(programWindow.isRunning())
{
programWindow.processEvents();
example.render();
programWindow.swapBuffers();
}
example.shutdown();
programWindow.destroy();
return 0;
}
void updateThread(Example* example)
{
setFPS(2000);
while(true)
{
example->update();
sync();
}
}
Util.cpp
#include "util.h"
int fps;
long timeThen;
void sync()
{
while(fps == 0);
long gapTo = 1000 / fps + timeThen;
long timeNow = time(nullptr);
while (gapTo > timeNow)
{
timeNow = time(nullptr);
}
timeThen = timeNow;
}
void setFPS(int FPS)
{
fps = FPS;
}
glwindow.cpp
#include <ctime>
#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"
#include "glwindow.h"
#include "example.h"
typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
GLWindow::GLWindow(HINSTANCE hInstance):
m_isRunning(false),
m_example(NULL),
m_hinstance(hInstance),
m_lastTime(0)
{
}
bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
DWORD dwExStyle;
DWORD dwStyle;
m_isFullscreen = fullscreen;
m_windowRect.left = (long)0;
m_windowRect.right = (long)width;
m_windowRect.top = (long)0;
m_windowRect.bottom = (long)height;
m_windowClass.cbSize = sizeof(WNDCLASSEX);
m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc = GLWindow::StaticWndProc;
m_windowClass.cbClsExtra = 0;
m_windowClass.cbWndExtra = 0;
m_windowClass.hInstance = m_hinstance;
m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
m_windowClass.hbrBackground = NULL;
m_windowClass.lpszMenuName = NULL;
m_windowClass.lpszClassName = "GLClass";
m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if(!RegisterClassEx(&m_windowClass))
{
return false;
}
if(m_isFullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bpp;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
m_isFullscreen = false;
}
}
if (m_isFullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(false);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle);
m_hwnd = CreateWindowEx(NULL, "GLClass", "BOGLGP - Chapter 2 - Simple OpenGL Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top, NULL, NULL, m_hinstance, this);
if (!m_hwnd)
{
MessageBox(NULL, "Window Creation Failed", NULL, MB_OK);
return 1;
}
m_hdc = GetDC(m_hwnd);
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
m_lastTime = GetTickCount() / 1000.0f;
return true;
}
void GLWindow::destroy()
{
if (m_isFullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(true);
}
}
void GLWindow::attachExample(Example* example)
{
m_example = example;
}
bool GLWindow::isRunning()
{
return m_isRunning;
}
void GLWindow::processEvents()
{
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void GLWindow::setupPixelFormat(void)
{
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
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,
};
pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
SetPixelFormat(m_hdc, pixelFormat, &pfd);
}
LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
m_hdc = GetDC(hWnd);
setupPixelFormat();
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
0};
HGLRC tmpContext = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, tmpContext);
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB)
{
MessageBox(NULL, "Open GL 3.0 Is Not Supported", NULL, MB_OK);
m_hglrc = tmpContext;
DestroyWindow(hWnd);
return 0;
}
else
{
m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
wglDeleteContext(tmpContext);
}
wglMakeCurrent(m_hdc, m_hglrc);
m_isRunning = true;
}
break;
case WM_DESTROY:
case WM_CLOSE:
wglMakeCurrent(m_hdc, NULL);
wglDeleteContext(m_hglrc);
m_isRunning = false;
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
{
int height = HIWORD(lParam);
int width = LOWORD(lParam);
getAttachedExample()->onResize(width, height);
}
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(m_hwnd);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GLWindow* window = NULL;
if(uMsg == WM_CREATE)
{
window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
}
else
{
window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(!window)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return window->WndProc(hWnd, uMsg, wParam, lParam);
}
float GLWindow::getElapsedSeconds()
{
float currentTime = float(GetTickCount()) / 1000.0f;
float seconds = float(currentTime - m_lastTime);
m_lastTime = currentTime;
return seconds;
}
example.cpp
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "example.h"
Example::Example()
{
m_rotationAngle = 0.0f;
}
bool Example::init()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
return true;
}
void Example::update()
{
const float SPEED = 15.0f;
m_rotationAngle += SPEED;
if (m_rotationAngle > 360.0f)
{
m_rotationAngle -= 360.0f;
}
}
void Example::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(m_rotationAngle, 0, 0, 1);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, -0.5f, -4.0f);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, -0.5f, -4.0f);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.5f, -4.0f);
glEnd();
}
void Example::shutdown()
{
TerminateThread(thread, 0);
}
void Example::onResize(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(width) / float(height), 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
EDIT
I am convinced that my problem is in the threading with example.cpp and main.cpp however i included all of the code to give more context to the situation.
Here is the error i get.
I don't see how your thread can exit cleanly.
In your while loop you should have something like
while (true) {
...
if (IShouldExit()) break;
}
That can be something simple like a bool or similar.
Then in your main you can set the flag then simply join with your thread, to give it time to exit cleanly.

glutKeyboardFunc error [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an opengl c++ code for reading .ply file. I want to read keyboard arrow keys(up,down,right,left) for move a point on the screen. I used glutKeyboardFunc function but i have an error:
Unhandled exception at 0x1000bb1e in opengl3.exe: 0xC0000005: Access violation reading location 0x00000070.
On this line:
glutKeyboardFunc(keyPressed);
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <string>
#include <conio.h>
HWND hWnd;
HDC hDC;
HGLRC hRC;
// Set up pixel format for graphics initialization
void SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
ppfd->cColorBits = 16;
ppfd->cDepthBits = 16;
ppfd->cAccumBits = 0;
ppfd->cStencilBits = 0;
pixelformat = ChoosePixelFormat(hDC, ppfd);
SetPixelFormat(hDC, pixelformat, ppfd);
}
void InitGraphics()
{
hDC = GetDC(hWnd);
SetupPixelFormat();
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glClearColor(0, 0, 0, 0.5);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
}
// Resize graphics to fit window
void ResizeGraphics()
{
// Get new window size
RECT rect;
int width, height;
GLfloat aspect;
GetClientRect(hWnd, &rect);
width = rect.right;
height = rect.bottom;
aspect = (GLfloat)width / height;
// Adjust graphics to window size
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspect, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// Draw frame
void DrawGraphics()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set location in front of camera
glLoadIdentity();
glTranslated(0, 0, -10);
// Draw a square
glBegin(GL_QUADS);
glColor3d(100, 200, 30);
/*
glVertex3d(-2, 2, 0);
glVertex3d(2, 2, 0);
glVertex3d(2, -2, 0);
glVertex3d(-2, -2, 0);
*/
//FILE * file = fopen("D:\\dart.ply","r");
FILE * file = fopen("mosalas.ply","r");
if (file!=NULL)
{
fseek(file,0,SEEK_END);
long fileSize = ftell(file);
float* Vertex_Buffer;
try
{
Vertex_Buffer = (float*) malloc (ftell(file));
}
catch (char* )
{
//return -1;
}
//if (Vertex_Buffer == NULL) return -1;
fseek(file,0,SEEK_SET);
//Faces_Triangles = (float*) malloc(fileSize*sizeof(float));
//Normals = (float*) malloc(fileSize*sizeof(float));
if (file)
{
int i = 0;
int temp = 0;
int quads_index = 0;
int triangle_index = 0;
int normal_index = 0;
char buffer[1000];
fgets(buffer,300,file); // ply
// READ HEADER
// -----------------
int TotalConnectedPoints;
// Find number of vertexes
while ( strncmp( "element vertex", buffer,strlen("element vertex")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element vertex"));
sscanf(buffer,"%i", &TotalConnectedPoints);
int TotalFaces;
// Find number of face
fseek(file,0,SEEK_SET);
while ( strncmp( "element face", buffer,strlen("element face")) != 0 )
{
fgets(buffer,300,file); // format
}
strcpy(buffer, buffer+strlen("element face"));
sscanf(buffer,"%i", &TotalFaces);
// go to end_header
while ( strncmp( "end_header", buffer,strlen("end_header")) != 0 )
{
fgets(buffer,300,file); // format
}
i =0;
float* ver0,ver1,ver2,ver3;
//char* key[100];
for (int iterator = 0; iterator < TotalConnectedPoints; iterator++)
{
fgets(buffer,300,file);
//sscanf(buffer,"%f %f %f", &Vertex_Buffer[i], &Vertex_Buffer[i+1], &Vertex_Buffer[i+2]);
sscanf(buffer,"%f %f %f", &ver1, &ver2, &ver3);
glNormal3f(ver1, ver2, ver3);
glVertex3d(ver1, ver2, ver3);
//glVertex3f(ver1, ver2, ver3);
i += 3;
}
}
}
glPushMatrix();
glBegin;
glTranslatef(-10,5,0);
glColor3f(1,1,1);
glRotatef(90,0,1,0);
glutSolidCone(0.25, 15, 20, 20);
glEnd();
glPopMatrix();
//glutMouseFunc(0,0,0);
/*
glVertex3d(1.000000, 1.000000, 6);
glVertex3d(3.000000, 0.000000, 4);
glVertex3d(0.000000, 0.000000, 4);
glVertex3d(0.000000, 3.000000, 4);
glVertex3d(1.500000, 0.500000, 0);*/
glEnd();
// Show the new scene
SwapBuffers(hDC);/**/
}
void keyPressed (unsigned char key, int x, int y) {
}
// Handle window events and messages
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
ResizeGraphics();
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
// Default event handler
default:
return DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}
return 1;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const LPCWSTR appname = TEXT("OpenGL Sample");
WNDCLASS wndclass;
MSG msg;
// Define the window class
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, appname);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = appname;
wndclass.lpszClassName = appname;
// Register the window class
if (!RegisterClass(&wndclass)) return FALSE;
// Create the window
hWnd = CreateWindow(
appname,
appname,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) return FALSE;
// Initialize OpenGL
InitGraphics();
// Display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
DrawGraphics();
// Event loop
int key;
int asgh = 0;
POINT pt;
/**/while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (!GetMessage(&msg, NULL, 0, 0))
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glutKeyboardFunc(keyPressed);
DrawGraphics();
}
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
The program you posted lacks a call to glutInit().
Furthermore you're doing all of the platform-specific window management and context creation that GLUT is supposed abstract away.
Bottom line: If you want to use GLUT, use GLUT. If you want to use Win32, use Win32. Don't try to mix-and-match.