In C++ using Code::Blocks v10.05, how do I draw a single pixel on the console screen? Is this easy at all, or would it be easier to just draw a rectangle? How do I color it?
I'm sorry, but I just can't get any code from SOF, HF, or even cplusplus.com to work. This is for a Super Mario World figure on the screen. The game I think is 16-bit, and is for the SNES system. C::B says I need SDK for C::B. It says "afxwin.h" doesn't exist. Download maybe?
This is what I'm trying to make:
It depends on your OS. I suppose you are programming in a Windows platform, therefore you can use SetPixel but you have to use "windows.h" to get a console handle, so here an example for drawing the cos() function:
#include<windows.h>
#include<iostream>
#include <cmath>
using namespace std;
#define PI 3.14
int main()
{
//Get a console handle
HWND myconsole = GetConsoleWindow();
//Get a handle to device context
HDC mydc = GetDC(myconsole);
int pixel =0;
//Choose any color
COLORREF COLOR= RGB(255,255,255);
//Draw pixels
for(double i = 0; i < PI * 4; i += 0.05)
{
SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
pixel+=1;
}
ReleaseDC(myconsole, mydc);
cin.ignore();
return 0;
}
You can also use some others libraries like: conio.h allegro.h sdl, etc.
If you're willing to have the image look blocky, you could take advantage of the block characters from the console code page.
█ = '\xDB' = U+2588 FULL BLOCK
▄ = '\xDC' = U+2584 LOWER HALF BLOCK
▀ = '\xDF' = U+2580 UPPER HALF BLOCK
and space
By using the half-blocks in combination with colored text, you can turn an 80×25 console window into an 80×50 16-color display. (This was the approach used by the QBasic version of Nibbles.)
Then, you just need to convert your image to the 16-color palette and a reasonably small size.
windows.h provides a function SetPixel() to print a pixel at specified location of a window. The general form of the function is
SetPixel(HDC hdc, int x, int y, COLORREF& color);
where, x and y are coordinates of pixel to be display and color is the color of pixel.
Important: to print the pixel in your machine with Code::blocks IDE, add a link library libgdi32.a (it is usually inside MinGW\lib ) in linker setting.
Console is a text device, so in general you don't write to individual pixels. You can create a special font and select it as a font for console, but it will be monochromatic. There are libraries which simplify writing console UI (e.g. Curses), but I believe that you also have more gamelike functionality in mind besides just showing a sprite.
if you want to write a game, I suggest taking a look at some of the graphics/game frameworks/libs, e.g. SDL
I have drawn the straight line using windows.h in code::blocks. I can't explain it in details, but I can provide you a code and procedure to compile it in code::blocks.
go to setting menu and select compiler and debugger.
Click on linker tab and add a link library libgdi32.a which is at C:\Program Files\CodeBlocks\MinGW\lib directory.
Now compile this program
#include <windows.h>
#include <cmath>
#define ROUND(a) ((int) (a + 0.5))
/* set window handle */
static HWND sHwnd;
static COLORREF redColor=RGB(255,0,0);
static COLORREF blueColor=RGB(0,0,255);
static COLORREF greenColor=RGB(0,255,0);
void SetWindowHandle(HWND hwnd){
sHwnd=hwnd;
}
/* SetPixel */
void setPixel(int x,int y,COLORREF& color=redColor){
if(sHwnd==NULL){
MessageBox(NULL,"sHwnd was not initialized !","Error",MB_OK|MB_ICONERROR);
exit(0);
}
HDC hdc=GetDC(sHwnd);
SetPixel(hdc,x,y,color);
ReleaseDC(sHwnd,hdc);
return;
// NEVERREACH //
}
void drawLineDDA(int xa, int ya, int xb, int yb){
int dx = xb - xa, dy = yb - ya, steps, k;
float xIncrement, yIncrement, x = xa, y = ya;
if(abs(dx) > abs(dy)) steps = abs(dx);
else steps = abs(dy);
xIncrement = dx / (float) steps;
yIncrement = dy / (float) steps;
setPixel(ROUND(x), ROUND(y));
for(int k = 0; k < steps; k++){
x += xIncrement;
y += yIncrement;
setPixel(x, y);
}
}
/* Window Procedure WndProc */
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
switch(message){
case WM_PAINT:
SetWindowHandle(hwnd);
drawLineDDA(10, 20, 250, 300);
break;
case WM_CLOSE: // FAIL THROUGH to call DefWindowProc
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break; // FAIL to call DefWindowProc //
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow){
static TCHAR szAppName[] = TEXT("Straight Line");
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW|CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
// Register the window //
if(!RegisterClass(&wndclass)){
MessageBox(NULL,"Registering the class failled","Error",MB_OK|MB_ICONERROR);
exit(0);
}
// CreateWindow //
HWND hwnd=CreateWindow(szAppName,"DDA - Programming Techniques",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if(!hwnd){
MessageBox(NULL,"Window Creation Failed!","Error",MB_OK);
exit(0);
}
// ShowWindow and UpdateWindow //
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
// Message Loop //
MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* return no error to the operating system */
return 0;
}
In this program I have used DDA line drawing algorithm. Pixel drawing tasks is done by setPixel(ROUND(x), ROUND(y)) function.
This is windows programing which you can learn details here
To use in CodeBlocks I found this (you have to add a linker option -lgdi32):
//Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32
I forgot: You have to put this before including windows.h:
#define _WIN32_WINNT 0x0500
The whole cosine code again. Ready to compile:
//Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32
#define _WIN32_WINNT 0x0500
#include "windows.h"
#include <iostream>
#include <cmath>
using namespace std;
#define PI 3.14
int main(){
HWND myconsole = GetConsoleWindow();
HDC mydc = GetDC(myconsole);
int pixel =0;
COLORREF COLOR= RGB(255,255,255);
//Draw pixels
for(double i = 0; i < PI * 4; i += 0.05)
{
SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
pixel+=1;
}
ReleaseDC(myconsole, mydc);
cin.ignore();
return 0;
}
Related
I got the following example code for a C windows programm from the developer of my analog to digital converter and want to make it run as a windows c++ project in Visual Studio 2016.
As a beginner in C++, windows API and this universal library for the converter I'm overwhelmed with the troubleshooting right now. The plan was to learn by making the code work but right now it's really hard to find out where the problems are and there's not the time to learn everything from scratch (though I try next to it)
This is my setup: Windows 7 64bit, MS Visual Studio Community 2017, USB 1608fs plus a/d converter with its universal library
These are the errors I'm currently getting:
a value of type "HANDLE" cannot be used to initialize an entity of type "HINSTANCE" (row 83)
a value of type "HGDIOBJ" cannot be used to initialize an entity of type "HBRUSH"(row 86)
the argument of type "HANDLE" is incompatible with parameter type "HINSTANCE" (row 93)
Actions I took until now:
creating a new empty win32 project in MS Visual Studio
copying the example code
copying the header file and the library from the converter into the same folder
switching the character set from unicode to multibyte
switching off the precompiled header
include the missing headers from the precompiled header
Here is the code:
#include <windows.h> /* Compiler's include files's */
#include <string.h>
#include <stdio.h>
#include "cbw.h" /* Universal Library's include file */
#include "targetver.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#define BOARD_NUM 0 /* Number of A/D board as defined with InstaCal */
#define ADRANGE BIP5VOLTS /* A/D voltage range */
#define TIMER_NUM 1 /* Windows timer used by this program */
HWND hWndMain; /* handle for main window */
LONG FAR PASCAL MainMessageHandler(HWND, UINT, WPARAM, LPARAM);
/************************************************************************
*
* Name: WinMain
*
* Arguments: hInstance - the instance handle for the program
* hPrevInstance - the class name of the application (not used)
* CmndLine - command line was called with (not used)
* CmndShow - indicates how to display window
*
* This is the entry point to the program. It gets called by Windows
* to start the program up. This routine creates the main window,
* initializes a timer, and then falls into the main Windows Get
* message/Dispatch message loop.
*
************************************************************************/
int PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR CmdLine, int nCmdShow)
{
MSG msg; /* MSG structure to pass to windows proc */
WNDCLASS wndclass;
char *AppName; /* Name for the window */
cbErrHandling(PRINTALL, STOPALL); /* Set library's error handling */
CmdLine = NULL; /* Not used */
AppName = "WINCDEMO"; /* The name of this application */
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainMessageHandler;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, AppName);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = AppName;
wndclass.lpszClassName = AppName;
RegisterClass(&wndclass);
}
/* create application's Main window */
hWndMain = CreateWindow(AppName, /* Window class name */
"AIn Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, /* Use default X, Y */
CW_USEDEFAULT, /* Use default X, Y */
GetSystemMetrics(SM_CXSIZE) * 12, /* x - fit text */
GetSystemMetrics(SM_CYSIZE) * 10, /* y - fit text */
NULL, /* Parent window's handle */
NULL, /* Default to Class Menu */
hInstance, /* Instance of window */
NULL); /* Create struct for WM_CREATE */
if (hWndMain == NULL)
{
MessageBox(NULL, "Could not create window in WinMain", NULL, MB_ICONEXCLAMATION);
return (1);
}
ShowWindow(hWndMain, nCmdShow); /* Display main window */
UpdateWindow(hWndMain);
// /* Start a 500ms timer to update display */
if (!SetTimer(hWndMain, TIMER_NUM, 50, NULL))
{
MessageBox(NULL, "Error starting Windows timer", NULL, MB_OK |
MB_ICONEXCLAMATION);
return (1);
}
while (GetMessage(&msg, NULL, 0, 0)) /* Main message loop */
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(AppName, hInstance);
return (msg.wParam);
}
/************************************************************************
*
* Name: MainMessageHandler
*
* Arguments: hWnd - handle to the window
* Message - message that needs to be handled
* hParam - message parameter
* lParam - message parameter
*
* This is the message dispatcher that gets called whenever Windows
* sends a message to this window. WinMain started up a timer that
* sends a message every 1/2 sec. When the message (WM_TIMER)is received
* by this routine, it reads the A/D.
* It also causes a screen update which will automatically generate a
* WM_PAINT message. The WM_PAINT handler takes care of converting the
* raw A/D values to voltages and printing them in the Window.
*
************************************************************************/
LONG FAR PASCAL
MainMessageHandler(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
HDC hDC; /* handle for the display device */
PAINTSTRUCT ps; /* holds PAINT information */
TEXTMETRIC tm; /* holds TEXT information */
static HRGN hRgn; /* Rectangle region Handles */
static int CharWidth, CharHeight;
static unsigned short DataVal;
int x, y;
char OutString[80], *str;
float Voltage;
switch (Message) /* Windows Message Loop */
{
case WM_CREATE:
hDC = GetDC(hWndMain); /* Get the device context for window */
GetTextMetrics(hDC, &tm); /* From context, get size of font */
CharWidth = tm.tmAveCharWidth;
CharHeight = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hWndMain, hDC);
hRgn = CreateRectRgn(0, 0, CharWidth * 30, CharHeight * 12);
break;
case WM_TIMER: /* All Timer Events Processed Here */
InvalidateRgn(hWndMain, hRgn, FALSE); /* Force screen update */
break;
case WM_PAINT: /* Repaint client area of window */
hDC = BeginPaint(hWndMain, &ps);
x = CharWidth * 2; /* Position cursor within window */
y = CharHeight; /* One line down and 2 chars in */
str = " A/D Info"; /* Print title */
TextOut(hDC, x, y, str, strlen(str));
y += CharHeight; /* Print current index */
cbAIn(BOARD_NUM, 0, ADRANGE, &DataVal);
y += CharHeight * 2; /* Print raw data value */
sprintf(OutString, "Raw A/D value = %u ", DataVal);
TextOut(hDC, x, y, OutString, strlen(OutString));
y += CharHeight; /* Convert raw A/D to volts and print */
cbToEngUnits(BOARD_NUM, ADRANGE, DataVal, &Voltage);
sprintf(OutString, "Voltage = %.2f ", Voltage);
TextOut(hDC, x, y, OutString, strlen(OutString));
SetTextAlign(hDC, TA_LEFT | TA_TOP);
EndPaint(hWndMain, &ps);
break;
case WM_CLOSE: /* Close the window */
DestroyWindow(hWnd);
if (hWnd == hWndMain)
PostQuitMessage(0); /* Send message to Quit application */
break;
default:
return (DefWindowProc(hWnd, Message, wParam, lParam));
}
return (0l);
}
Instead of randomly roaming around copypasting staff and switching things on and off you should first understand the errors you are facing. For example first error: You should lookup on MSDN what HANDLE and HINSTANCE are and figure out where are you getting them from. You get hInstance from WinMain. You should lookup on MSDN for WinMain and figure out that signature you used is somewhat wrong and you are supposed to use
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
So the error with wndclass.hInstance = hInstance; assignment of HANDLE to HINSTANCE should be gone (assuming that I've pointed the correct line of this error because you only specified row).
And so on.
I am having issues in getting my .bmp image displayed to change to another one on user input. The image can be successfully printed at the start (title.bmp), but is supposed to change when pressing 1 or 2 followed by enter (to introduction.bmp & start.bmp). I must be missing something!
Where this happens is around the bottom of the code from while (running == 1) { so skip down to there.
I am using loadImage("title.bmp"); to print my images (I change the filename appropriately of course), and cin >> menuSelection; to pause the program and wait until the user presses one or two followed by enter.
I've searched many, many pages on how to print and change images in WinAPI, and this is the closest I can get. If there is any other information I have missed please tell me and I will comment it. Thanks in advance for helping!
//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
//Defining the [global] variables that will be used throughout the program
int running = 1;
int menuSelection = 0;
int userInput;
int userInputDummy;
int intPointer;
//Starter variables used in creating a window and printing images. These are global.
HDC imageDC; // the DC to hold our image
HBITMAP imageBmp; // the actual bitmap which contains the image (will be put in the DC)
HBITMAP imageBmpOld; // the DC's old bitmap (for cleanup)
const int screenSize_X = 640;
const int screenSize_Y = 480;
//Functions! Sections of code to re-used in the program
// Function to load the image into our DC so we can draw it to the screen
void loadImage(const char* pathname)
{
imageDC = CreateCompatibleDC(NULL); // create an offscreen DC
imageBmp = (HBITMAP)LoadImageA( // load the bitmap from a file
NULL, // not loading from a module, so this is NULL
pathname, // the path we're loading from
IMAGE_BITMAP, // we are loading a bitmap
0, 0, // don't need to specify width/height
LR_DEFAULTSIZE | LR_LOADFROMFILE// use the default bitmap size (whatever the file is), and load it from a file
);
imageBmpOld = (HBITMAP)SelectObject(imageDC, imageBmp); // put the loaded image into our DC
}
// Function to clean up
void cleanUpImage()
{
SelectObject(imageDC, imageBmpOld); // put the old bmp back in our DC
DeleteObject(imageBmp); // delete the bmp we loaded
DeleteDC(imageDC); // delete the DC we created
}
// The function to draw our image to the display (the given DC is the screen DC)
void drawImage(HDC screen)
{
BitBlt(
screen, // tell it we want to draw to the screen
0, 0, // as position 0,0 (upper-left corner)
screenSize_X, // width of the rect to draw
screenSize_Y, // height of the rect
imageDC, // the DC to get the rect from (our image DC)
0, 0, // take it from position 0,0 in the image DC
SRCCOPY // tell it to do a pixel-by-pixel copy
);
}
// A callback to handle Windows messages as they happen
LRESULT CALLBACK wndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l)
{
// what kind of message is this?
switch (msg)
{
// we are interested in WM_PAINT, as that is how we draw
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC screen = BeginPaint(wnd, &ps); // Get the screen DC
drawImage(screen); // draw our image to our screen DC
EndPaint(wnd, &ps); // clean up
}break;
// we are also interested in the WM_DESTROY message, as that lets us know when to close the window
case WM_DESTROY:
PostQuitMessage(0);
break;
}
// for everything else, let the default window message handler do its thing
return DefWindowProc(wnd, msg, w, l);
}
// A function to create the window and get it set up
HWND createWindow(HINSTANCE inst)
{
WNDCLASSEX wc = { 0 }; // create a WNDCLASSEX struct and zero it
wc.cbSize = sizeof(WNDCLASSEX); // tell windows the size of this struct
wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); // tell it to use the normal arrow cursor for this window
wc.hInstance = inst; // give it our program instance
wc.lpfnWndProc = wndProc; // tell it to use our wndProc function to handle messages
wc.lpszClassName = TEXT("DisplayImage"); // give this window class a name.
RegisterClassEx(&wc); // register our window class with Windows
// the style of the window we want... we want a normal window but do not want it resizable.
int style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; // normal overlapped window with a caption and a system menu (the X to close)
// Figure out how big we need to make the window so that the CLIENT area (the part we will be drawing to) is
// the desired size
RECT rc = { 0,0,screenSize_X,screenSize_Y }; // desired rect
AdjustWindowRect(&rc, style, FALSE); // adjust the rect with the given style, FALSE because there is no menu
return CreateWindow( // create the window
TEXT("DisplayImage"), // the name of the window class to use for this window (the one we just registered)
TEXT("Display an Image"), // the text to appear on the title of the window
style | WS_VISIBLE, // the style of this window (OR it with WS_VISIBLE so it actually becomes visible immediately)
100, 100, // create it at position 100,100
rc.right - rc.left, // width of the window we want
rc.bottom - rc.top, // height of the window
NULL, NULL, // no parent window, no menu
inst, // our program instance
NULL); // no extra parameter
}
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// _________________________________________________________________________________________
// The actual entry point for the program!
// This is Windows' version of the 'main' function:
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show)
{
// load our image
loadImage("title.bmp");
// create our window
HWND wnd = createWindow(inst);
// Do the message pump! keep polling for messages (and respond to them)
// until the user closes the window.
MSG msg;
while (GetMessage(&msg, wnd, 0, 0)) // while we are getting non-WM_QUIT messages...
TranslateMessage(&msg); // translate them
DispatchMessage(&msg); // and dispatch them (our wndProc will process them)
{
while (running == 1) {
//Welcoming the user to the program, and asking them what they want to do (starts functions)
cin >> menuSelection;
//Selecting the introduction option
if (menuSelection == 1) {
loadImage("introduction.bmp");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the start option
else if (menuSelection == 2) {
loadImage("start");
cin >> userInputDummy;
menuSelection = 0;
}
//Selecting the exit option
else if (menuSelection == 3) {
menuSelection = 0;
running = 0;
}
}
// once the user quits....
cleanUpImage();
return 0;
return EXIT_SUCCESS;
}
}
you cannot use cin in win32 use an editbox then get the user's input from it as character string then if you want convert it to an integer value otherwise use the API:
GetDlgItemInt(...);
you are also handling only GetMessage in while-loop while you only handle dispatchmessage outside the loop which means you handle it only once, when getmessage fails (the end of program) so the result is a freezing windows as long as there's no one who takes messages from getmessage to the target windo.
the solution: make DispatchMessage inside while loop:
another thing: you pass hwnd to getmessage the result destroying the window won't make the application exit.
take a look at GetMessage() when passing a non-null value:
link text
the correct thing in your case:
while (GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
* don't load image inside loop just load at the time wanted:
make an edit box with style ES_NUMBER and another button names for example change image so when clicked take the content of edit box convert it to integer, check whether it is 1 or 2 then load imaged depending the value.
you may ask "why I can't use iostream input and output streams in win32" because I ask you "where is console windows?" and if it is here what is the role of while-loop (blocking waiting for messages)?
I'm working on creating a text based Windows game, and I am having a problem (I guess) with arrays not working the same within a class scope as within the main function. As far as I can tell it is some kind of interaction between a larger array class member (or large total amount of variables) and Windows creating a DC or other Windows API calls and/or variables.
What I want to do is a have a class called Map that contains a two dimensional array of Tiles. Tile is just a simple struct with basic tile information. I would like to make the array 256 x 256. This shouldn't be a problem as far as I can figure. Each Tile should be 32 bytes. That's 2 MB total for the array.
However, the game crashes when I declare a variable of the Map class in the main function, and then do things with Windows DCs. The return value seems to vary, In the current form, it usually returns 255, but I have also gotten "process terminated with status -1073741571". A 128 x 128 array does work in the class though. It also works fine if I remove either the array or the code in DisplayScreen. And as I implied, it also works if I just move the array of Tiles to the main function.
I'm honestly baffled. I have no idea what the difference would be. Nothing is going out of scope. Doesn't matter if it is a public or private member. Non dynamic class members should all get declared on the stack and it shouldn't work any differently in a class versus otherwise, right?
For other information, I am using Code::Blocks with the Min GW compiler. Everything is up to date. I am running Windows 10. My computer specs shouldn't be an issue either, but if it matters, I have 16 GB memory and a 4Ghz Athlon FX 8 core processor.
Edit: Here is the full code, so nothing is left out
Game.h:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
struct Tile
{
char chr[2];
int r[2], b[2], g[2];
bool solid;
bool translucent;
int opacity;
};
class Map
{
Tile tileMap[256][256];
public:
Map();
};
Map::Map()
{
int i, j;
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
main.cpp:
#include <windows.h>
#include "Game.h"
#define FRAMERATE 60
//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);
//Make the class name into a global variable
char strClassName[ ] = "GameApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd; //This is the handle for our window
MSG messages; //Here messages to the application are saved
WNDCLASSEX wndClassEx; //Data structure for the windowclass
Map test;
DWORD sysTimer;
DWORD sysPrevTime = 0;
DWORD timerDelta = 1000 / FRAMERATE;
//Get a handle for the whole screen
HDC hDC = GetDC(NULL);
//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL; //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));
//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;
//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName, //Class name
"Game Test", //Title Text
WS_OVERLAPPEDWINDOW, //default window type
0, //X pos of window at top left
0, //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP, //Child-window to desktop
NULL, //No menu
hThisInstance, //Program Instance handler
NULL); //No Window Creation data
//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);
//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}
TranslateMessage(&messages);
DispatchMessage(&messages);
}
sysTimer = timeGetTime();
if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}
}
}
//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}
void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);
HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);
SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));
//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World #", 15);
//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);
//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);
DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}
It crashes with even one instance of something creating a DC. It works fine otherwise creating and destroying the DCs and displaying the bitmap over and over again even if I leave it for an hour. Once I create that class with the large array in it though, it just dies.
I actually used to have the Display function as a class function and I moved it out because I thought that was the problem, but it wasn't.
Interestingly, if I change the declaration from 'Map test;' to 'Map* test = new Map;' and change the rest of the program appropriately, it works. Honestly though, doing that just seems kind of dumb, and I think that would slow everything down if I don't have a good reason to put everything on the heap. Plus, I don't like bandages. If there is a problem I'd rather fix it.
Any ideas?
You have a stack overflow (the condition, not the website).
The problem can be reproduced in this program:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}
It fails because it reaches stack limit.
Also tileMap[i][j].chr[2] is out of bound. It is declared as char chr[2]; valid index is 0 and 1. It can only go up to tileMap[i][j].chr[1]
Ditto b[], r[], and g[]
Change the Map class so that it allocates memory on heap and fix chr:
class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};
Map::Map()
{
int i, j;
tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];
for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X'; //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}
In a basic program, I need to know how to make a text display widget and image display that can both be changed to different strings and images on command. These will display on a basic GUI.
Any specific help would be tremendously appreciated as I have been stuck on this for more than 10 weeks! Asking online here is my last resort.
I am making a basic program that asks questions (which is my text I want to print) and images for the questions come up underneath it. I have successfully made this program in a console command window (the code I will share below) but this of course meant no images could be displayed, so I am having to remake it in a GUI that supports images.
This is my first project ever done in C++, and only know the basics (the full extent of my limited knowledge got me through making that console command window program without help).
I first used WinAPI as it came with my computer in microsoft visual studio, and tried many different suggestions by other's similar questions already answered, but always either had one of two problems; 1. The code they supplied had many errors of which most read "_ is undefined" or wasn't imported properly, or 2. created basic text successfully but didn't specify how to change it after it had been created (I have had no successful image prints so far). I have tried 3 question/answers from cplusplus.com and 3 from stack overflow (links will be below), and all of them have had these 2 problems that are created from my lack of C++ bug fixing skills.
Suggestions using WinAPI would be prefferred over QT as I have no idea what I am doing in Qt and get double digit numbers worth of errors when I import code (even though I import the correct directories), whereas WinAPI doesn't get importing errors.
Code for command console program:
//G-Learning
//#author: James Monk
//#completed: 7/6/16
//#version 1.0
//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
//Defining the [global] variables that will be used throughout the program
int running = 1;
int menuSelection;
int questionsLeft = 5;
int questionTextPicked;
int questionImagePicked;
int questionRandomised;
int score = 0;
int userInput;
int userInputDummy;
string stringPointer;
int intPointer;
string questionText[10] = {
"Would this most likely be, (1) an enemy (2) a player?\n",
"Is this (1) how many hearts the player has inside their body, or (2) a number of lives the player has?\n",
"Is this (1) a health bar, or (2) a set of red lights?\n",
"Is this (1) a money counter, or (2) a yellow ball counter?\n",
"Would this be a good object to touch with your character? (1) no or (2) yes?\n",
"What would this object likely have in it? (1) rewards, or (2) punishments\n",
"What does 'Game Over' mean? (1) your session has ended, or (2) the game is no longer playable\n",
"What would an icon like this likely be for? (1) show wheels, or (2) options\n",
"In a racing game, what would this be for? (1) health bar, or (2) fuel tank meter\n",
"What would this button likely do? (1) exit or cancel, or (2) mark a spot with an x\n" };
//Defining what happens with the different functions
void introduction() {
printf("\nG-Learning is a program built to teach people who know little about games the basic features of them. \n\n\
Questions will be asked, and you will need to answer them by choosing the correct answer.\n\
You will need to press 1, 2, or 3 followed by enter to choose.\n\n\
Press any number key followed by enter to return to the main menu.\n\n");
cin >> userInputDummy;
menuSelection = 0;
}
void start() {
printf("\nThe questions will now start, good luck!\n\n");
while (questionsLeft > 0) {
questionTextPicked = (rand() % 10);
if (questionTextPicked == 0) {
questionRandomised = (rand() % 4);
questionImagePicked = (7 + questionRandomised);
}
else if (questionTextPicked == 4) {
questionRandomised = (rand() % 3);
questionImagePicked = (11 + questionRandomised);
}
else {
questionImagePicked = questionTextPicked;
}
printf("after calculations, questionTextPicked is %d, questionRandomised is %d, and questionImagePicked is %d\n\n", questionTextPicked, questionRandomised, questionImagePicked);
//answering questions should be here
stringPointer = questionText[questionTextPicked];
intPointer = questionAnswer[questionImagePicked];
printf("answer is %d\n\n", intPointer);
printf("%s\n", stringPointer, intPointer);
printf("answer is %d\n\n", intPointer);
cin >> userInput;
if (userInput == questionAnswer[questionImagePicked]) {
printf("\nCorrect!\n\n");
score++;
}
else {
printf("\nIncorrect answer.\n\n");
}
questionsLeft--;
if (questionsLeft > 0) {
printf("%d questions to go!\n\n", questionsLeft);
}
if (questionsLeft == 0) {
printf("All questions have been answered, you scored %d/5.\n\nReturning you to the main menu\n\n", score);
score = 0;
}
} //end of start's while loop
menuSelection = 0;
} //end of start's function
void exit() {
menuSelection = 0;
running = 0;
}
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//Main function, where everything starts
int main(int argc, char ** argv) {
while (running == 1) {
//Welcoming the user to the program, and asking them what they want to do (starts functions)
printf("welcome to G-Learning! Press a key to get started.\n1: Instructions\n2: Start\n3: Exit\n\n");
questionsLeft = 5; //Resetting this so that the start function can begin again
cin >> menuSelection;
if (menuSelection == 1) {
introduction();
}
else if (menuSelection == 2) {
start();
}
else if (menuSelection == 3) {
exit();
}
else {
printf("Invalid input, please use the 1, 2, or 3 key.");
}
}
return 0;
return EXIT_SUCCESS;
} //end of main function
Code for my best working WinAPI iteration (can print text, but not again on command; also without image functionality. Would like to know how to improve this one!):
//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
int textHorizontal = 10;
int textVertical = 10;
//Variables used in making the program window
int numberInput;
char charictorInput;
string stringInput;
const char g_szClassName[] = "myWindowClass";
HINSTANCE hInstance;
// Function to get the size of the text
int GetTextSize(LPSTR a0)
{
for (int iLoopCounter = 0; ; iLoopCounter++)
{
if (a0[iLoopCounter] == '\0')
return iLoopCounter;
}
}
LPSTR TextArray[] = {
"Hello World"
};
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc,
// Location of the text
textHorizontal,
textVertical,
// Text to print
TextArray[0],
// Size of the text, my function gets this for us
GetTextSize(TextArray[0]));
EndPaint(hwnd, &ps);
}
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int WINAPI WinMain(HINSTANCE hInstanace, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX WindowClass;
WindowClass.cbClsExtra = 0;
WindowClass.cbWndExtra = 0;
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.lpszClassName = "1";
WindowClass.lpszMenuName = NULL;
WindowClass.lpfnWndProc = WndProc;
WindowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WindowClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WindowClass.style = 0;
WindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
RegisterClassEx(&WindowClass);
HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
"1",
"G-Learning by James Monk",
WS_OVERLAPPEDWINDOW,
315, 115,
1080, 720,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (VK_ESCAPE == msg.wParam)
break;
}
return 0;
}
I am limited to only 2 links, so to view the 3 cplusplus.com pages I tried and the 3 stack overflow pages I tried, the links to them are on a google document here:
https://docs.google.com/document/d/1IX2hxzAVka3UmVkaAgv-gXv_cwwmP3FkTYQuFWrrqyE/edit?usp=sharing
How I installed QT into Microsoft Visual Studio:
https://www.youtube.com/watch?v=P6Mg8FpFPS8
Thank you for reading through my issue and even more in advance for helping!
HINSTANCE hInstance;
int WINAPI WinMain(HINSTANCE hInstanace...
CreateWindowEx(... hInstance ...)
You have spelling errors here. hInstanace and hInstance are not the same. Visual Studio should give you warnings. Set the warning level to 4. Address all the warnings and fix them. Only in rare cases is it okay to ignore warnings.
Moreover, in declaration of WNDCLASSEX WindowClass; you missed initializing hInstance, so the code will go nowhere. In C++ 14 you can do this
WNDCLASSEX WindowClass = {0}
This will initialize all members to zero. Try to always do this when declaring data on stack. Also avoid putting random code in to message loop.
#include <cstdio>
#include <iostream>
#include <windows.h>
Above header files are for C input/output, C++ input/output, and WinAPI. Usually you don't need them all. Pick one.
LPSTR TextArray[] = {
"Hello World"
};
Above is a character array, or just "text". If you access TextArray[0] it gives you the character 'H'
int GetTextSize(LPSTR a0)
{
for (int iLoopCounter = 0; ; iLoopCounter++)
{
if (a0[iLoopCounter] == '\0')
return iLoopCounter;
}
}
Above code is the equivalent of strlen. Your code is all over the place. You have C++14 classes like std::string, C header files, useless functions like GetTextSize which is mostly for learning C/C++, more advanced WinAPI, and some mention of Qt cross development. I recommend you spend more time with a C++ book. Here is example of what you are trying to do:
#include <windows.h>
#include <string>
#include <vector>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND combobox;
static std::vector<std::string> vec = {
"Would this most likely be, (1) an enemy (2) a player?\n",
"Is this (1) how many hearts the player has inside their body, or (2) a number of lives the player has?\n",
"Is this (1) a health bar, or (2) a set of red lights?\n",
"Is this (1) a money counter, or (2) a yellow ball counter?\n",
"Would this be a good object to touch with your character? (1) no or (2) yes?\n",
"What would this object likely have in it? (1) rewards, or (2) punishments\n",
"What does 'Game Over' mean? (1) your session has ended, or (2) the game is no longer playable\n",
"What would an icon like this likely be for? (1) show wheels, or (2) options\n",
"In a racing game, what would this be for? (1) health bar, or (2) fuel tank meter\n",
"What would this button likely do? (1) exit or cancel, or (2) mark a spot with an x\n"
};
switch (msg)
{
case WM_CREATE:
combobox = CreateWindow("ComboBox", 0, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 0, 100, 700, 30, hwnd, HMENU(100), 0, 0);
for (auto line : vec) SendMessage(combobox, CB_ADDSTRING, 0, LPARAM(line.c_str()));
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
DestroyWindow(hwnd);
break;
case WM_COMMAND:
if (HIWORD(wParam) == CBN_SELCHANGE)
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
int sel = SendMessage(combobox, CB_GETCURSEL, 0, 0);
if (sel < 0) sel = 0;
TextOut(hdc, 0, 0, vec[sel].c_str(), vec[sel].size());
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcx = { 0 };
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpszClassName = "ClassName";
wcx.lpfnWndProc = WndProc;
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
RegisterClassEx(&wcx);
HWND hwnd = CreateWindowEx(0, wcx.lpszClassName, "G-Learning by James Monk", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0,0,800,600, NULL, NULL, hInstance, NULL);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I'm trying to teach myself the win32 API by making a window and attaching an OpenGL context to it. In order to fetch the appropriate pixel format a call to ChoosePixelFormat must be made which should return a pixel format that the system supports and best meets my needs. When I check for errors everything goes smoothly until this function is called which stops execution and logs error 1150-ERR_OLD_WIN_VERSION which is supposed to mean that my version of windows does not support this function. This is obviously not the case and msdn confirms that this function runs on all versions of windows since windows 2000. Right now I'm running windows 7 x64 on my desktop and I made sure my video driver and os were fully updated. Lots of people seem to have had trouble with the pixel format functions but I have not found any with my problem so I decided to post here for help. Here is my full code; I have not tested it on any machines other than my own.
WinMain.cpp (the only non-default msvc lib this is linked with is opengl32.lib)
#include"Display.h"
#include<iostream>
#include<fstream>
MSG message;
DWORD error;
int status;
LRESULT CALLBACK WndProc(HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam)
{ switch(message)
{case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch(wParam)
{case VK_ESCAPE:
PostQuitMessage(0);
return 0;}}
return DefWindowProc(hWindow, message, wParam, lParam);}
int MainLoop(Display d)
{
while((status = PeekMessage(&message, d.hWindow, 0, 0, PM_REMOVE)) != 0)
{
if (status == -1)
{
return -1;
}
DispatchMessage(&message);
}
return 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
std::ofstream file("log.txt", std::ios::trunc);
Display window("TEST", hInstance, WndProc, 50, 50, 50, 50, NULL, NULL);
if(window.status == -1)
{ error = GetLastError();
file << error;
return 1;}
ShowWindow(window.hWindow, SW_SHOWNORMAL);
EnableWindow(window.hWindow, true);
MainLoop(window);
return 0;
}
Display.h (problem occurs in the class constructor)
#include <Windows.h>
class Display
{public:
Display(const char*, HINSTANCE, WNDPROC, int, int, int, int, DWORD, DWORD);
~Display();
HWND hWindow;
int status;
private:
WNDCLASSEX data;
HDC hDeviceContext;
HGLRC hGLContext;
PIXELFORMATDESCRIPTOR PFD;
int x, y, width, height;};
Display::Display(const char* title, HINSTANCE InstanceHandle, WNDPROC WindowProcedure, int ScreenPositionX, int ScreenPositionY, int WindowWidth, int WindowHeight, DWORD StyleFlags, DWORD ExtendedStyleFlags)
{ data.cbSize = sizeof(WNDCLASSEX);
data.style = CS_OWNDC;
data.lpfnWndProc = WindowProcedure;
data.cbClsExtra = 0;
data.cbWndExtra = 0;
data.hInstance = InstanceHandle;
data.hIcon = NULL;
data.hCursor = NULL;
data.hbrBackground = NULL;
data.lpszMenuName = NULL;
data.lpszClassName = "WIN1";
data.hIconSm = NULL;
RegisterClassEx(&data);
hWindow = CreateWindowEx(ExtendedStyleFlags, data.lpszClassName, title, StyleFlags | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x = ScreenPositionX, y = ScreenPositionY, width = WindowWidth, height = WindowHeight, NULL, NULL, InstanceHandle, NULL);
PFD.nSize = sizeof(PIXELFORMATDESCRIPTOR);
PFD.nVersion = 1;
PFD.iPixelType = PFD_TYPE_RGBA;
PFD.iLayerType = PFD_MAIN_PLANE;
PFD.dwVisibleMask = 0;
PFD.dwLayerMask = 0;
PFD.dwDamageMask = 0;
PFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL;
PFD.cAuxBuffers = 0;
PFD.bReserved = 0;
PFD.cColorBits = 24;
PFD.cAccumBits = 0;
PFD.cDepthBits = 32;
PFD.cStencilBits = 0;
PFD.cAlphaBits = 0;
PFD.cAccumAlphaBits = 0;
PFD.cAlphaShift = 0;
PFD.cBlueBits = 0;
PFD.cAccumBlueBits = 0;
PFD.cBlueShift = 0;
PFD.cGreenBits = 0;
PFD.cAccumGreenBits = 0;
PFD.cGreenShift = 0;
PFD.cRedBits = 0;
PFD.cAccumRedBits = 0;
PFD.cRedShift = 0;
hDeviceContext = GetDC(hWindow);
int pf = ChoosePixelFormat(hDeviceContext, &PFD); //throws error 1150, next three throw error 2000 because of this failing
SetPixelFormat(hDeviceContext, pf, &PFD);
hGLContext = wglCreateContext(hDeviceContext);
wglMakeCurrent(hDeviceContext, hGLContext);
if(GetLastError() != ERROR_SUCCESS)
{status = -1;}
else
{status = 0;}
return;}
Display::~Display()
{ wglMakeCurrent(NULL, NULL);
wglDeleteContext(hGLContext);
DestroyWindow(hWindow);
UnregisterClass(data.lpszClassName, data.hInstance);}
After I have tried all mentioned solutions I still had the same problem with ERR_OLD_WIN_VERSION after ChoosePixelFormat. In my case the problem was about the graphics card driver:
The system I'm working on uses an EVGA card with a GTX 770 GPU and yesterday I installed driver version 331.65. After that I got the same problems as the questioner. Installing the current Version 337.88 fixed the issue in my case. However ERR_OLD_WIN_VERSION seams to lead us in the wrong direction.
In your Display constructor, it looks like you don't initialize the hWindow member before you use it. That would be the value returned by CreateWindowEx.
Instead of testing the address of the GetLastError function, you should be calling it and testing its return value against ERROR_SUCCESS. I think this may be an oversight when you pasted the code, as you seem to be getting meaningful results from GetLastError (...).
UPDATE:
You might want to try something like:
#ifndef WINVER
# define WINVER 0x0500
#endif
Before #include <Windows.h>
That tells it to include all of the fields in the data structures that are new in Windows NT 5.0 (Windows 2000). Many of these structures determine the version of Windows they are targeting by the sizeof your structure, which will vary depending on how you have WINVER defined.
I was not able to boot up my older machine, but I did discover something when looking through the source code of SDL. It seems that they defined their own version of ChoosePixelFormat that loops through all available pixel formats using DescribePixelFormat and then compares them to the desired pixel format before choosing the best one. Since this is the exact same definition of windows's ChoosePixelFormat I suspect they had a good reason to make their own. Perhaps they knew it gave trouble in certain situations. Unfortunately since Microsoft Developer support is a myth, and barely anyone seems to care, this is as good an answer as I'll get for now. And since I've stopped caring too, this is probably the closest this question will ever get to an answer. Thnaks to those of you who tried to help.