Reputation: 161
I want to try and learn OpenGL, I know C++ and I found a site with C++/OpenGL tutorials, this site also teaches a few things about WinAPI,bcs "our" programms are going to be Windows applications. In this tutorial it has the code of "our" first Windows application. The code (it doesn't compile):
/* Trim fat from windows*/
#define WIN32_LEAN_AND_MEAN
#pragma comment(linker, "/subsystem:windows")
/* Pre-processor directives*/
#include "stdafx.h"
#include <windows.h>
/* Windows Procedure Event Handler*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT paintStruct;
/* Device Context*/
HDC hDC;
/* Text for display*/
char string[] = "Hello, World!";
/* Switch message, condition that is met will execute*/
switch(message)
{
/* Window is being created*/
case WM_CREATE:
return 0;
break;
/* Window is closing*/
case WM_CLOSE:
PostQuitMessage(0);
return 0;
break;
/* Window needs update*/
case WM_PAINT:
hDC = BeginPaint(hwnd,&paintStruct);
/* Set txt color to blue*/
SetTextColor(hDC, COLORREF(0x00FF0000));
/* Display text in middle of window*/
TextOut(hDC,150,150,string,sizeof(string)-1);
EndPaint(hwnd, &paintStruct);
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd,message,wParam,lParam));
}
/* Main function*/
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX windowClass; //window class
HWND hwnd; //window handle
MSG msg; //message
bool done; //flag saying when app is complete
/* Fill out the window class structure*/
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 = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = "MyClass";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
/* Register window class*/
if (!RegisterClassEx(&windowClass))
{
return 0;
}
/* Class registerd, so now create window*/
hwnd = CreateWindowEx(NULL, //extended style
"MyClass", //class name
"A Real Win App", //app name
WS_OVERLAPPEDWINDOW | //window style
WS_VISIBLE |
WS_SYSMENU,
100,100, //x/y coords
400,400, //width,height
NULL, //handle to parent
NULL, //handle to menu
hInstance, //application instance
NULL); //no extra parameter's
/* Check if window creation failed*/
if (!hwnd)
return 0;
done = false; //initialize loop condition variable
/* main message loop*/
while(!done)
{
PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE);
if (msg.message == WM_QUIT) //check for a quit message
{
done = true; //if found, quit app
}
else
{
/* Translate and dispatch to event queue*/
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
It didn't compile, it had a few errors so I changed it a bit:
/* Trim fat from windows*/
#define WIN32_LEAN_AND_MEAN
#pragma comment(linker, "/subsystem:windows")
/* Pre-processor directives*/
#include <tchar.h> //couldn't find stdafx.h
#include <windows.h>
/* Windows Procedure Event Handler*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT paintStruct;
/* Device Context*/
HDC hDC;
/* Text for display*/
wchar_t string[] = L"F*CK!!!! It doesn't work, why am I getting Kanji? WTF\0"; // fixed error: char not compatible, char -> wchar_t
/* Switch message, condition that is met will execute*/
switch (message)
{
/* Window is being created*/
case WM_CREATE:
return 0;
break;
/* Window is closing*/
case WM_CLOSE:
PostQuitMessage(0);
return 0;
break;
/* Window needs update*/
case WM_PAINT:
hDC = BeginPaint(hwnd, &paintStruct);
/* Set txt color to blue*/
SetTextColor(hDC, COLORREF(0x00FF0000));
/* Display text in middle of window*/
TextOut(hDC, 150, 150, string, sizeof(string) - 1);
EndPaint(hwnd, &paintStruct);
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
/* Main function*/
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX windowClass; //window class
HWND hwnd; //window handle
MSG msg; //message
bool done; //flag saying when app is complete
/* Fill out the window class structure*/
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 = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = L"MyClass"; // fixed error: char* not compatible with LPCWSTR
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
/* Register window class*/
if (!RegisterClassEx(&windowClass))
{
return 0;
}
/* Class registerd, so now create window*/
hwnd = CreateWindowEx(NULL, //extended style
L"MyClass", //class name | fixed error: char* not compatible with LPCWSTR
L"A Real Win App", //app name | fixed error: char* not compatible with LPCWSTR
WS_OVERLAPPEDWINDOW | //window style
WS_VISIBLE |
WS_SYSMENU,
100, 100, //x/y coords
400, 400, //width,height
NULL, //handle to parent
NULL, //handle to menu
hInstance, //application instance
NULL); //no extra parameter's
/* Check if window creation failed*/
if (!hwnd)
return 0;
done = false; //initialize loop condition variable
/* main message loop*/
while (!done)
{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT) //check for a quit message
{
done = true; //if found, quit app
}
else
{
/* Translate and dispatch to event queue*/
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
Now it compiles, but, I get this:
The "F*CK!!!! it doesn't work, why am I getting Kanji, WTF" is correct(Forgive me if it is not Kanji)
Thank you for listening(reading actually) to my problems
Upvotes: 0
Views: 123
Reputation: 597016
The last parameter of TextOut()
takes a character count, but you are passing it a byte count instead.
In the original code, the string
array used char
characters, and sizeof(char)
is 1 byte, so the two counts were the same numeric value. But you changed the code to use wchar_t
characters instead, and on Windows sizeof(wchar_t)
is 2 bytes.
So, by using TextOut(..., string, sizeof(string) - 1)
with a wchar_t
string, you are telling TextOut()
that there are 2 times as many wchar_t
s in the string
array as there really are, and thus TextOut()
goes out of bounds of the string
array printing out random garbage from surrounding memory (consider yourself lucky the code didn't just crash outright from accessing memory it didn't own).
If you are going to use sizeof()
in this manner, then to get the correct array element count, you need to divide the array's byte size by its element's byte size, eg:
TextOut(..., string, (sizeof(string) / sizeof(string[0])) - 1)
You can replace that with the _countof()
macro in Visual Studio (or equivalent in other compilers), eg:
TextOut(..., string, _countof(string) - 1)
In C++11 and later, you should use std::size()
instead, eg:
TextOut(..., string, std::size(string) - 1)
Note that if the string
array is ever replaced with a wchar_t*
pointer in the future, these solutions will not work anymore. The sizeof()
solution will still compile but will not produce the correct result. But the _countof()
and std::size()
solutions will fail to compile, which is a good thing. Then you will know that you need to replace it with a more appropriate solution, like lstrlenW()
, std::wstring::size()
, etc.
Upvotes: 1
Reputation: 25388
You need to replace this:
TextOut(hDC, 150, 150, string, sizeof(string) - 1);
with this:
TextOut(hDC, 150, 150, string, wcslen(string));
sizeof (string)
is in bytes, not characters.
Also, please don't spam language tags. Just pick the one(s) that are relevant.
Upvotes: 2
Reputation: 179981
You're using sizeof(string)
. That's the number of bytes, not the number of characters. Since you're using C++, use std::wstring::size()
.
Upvotes: 0