Haben wieder einmal ein wenig Zeit gefunden um an meinem kleinen simplen Spiel fortzufahren. In meinem Fenstercode verwende ich die IrgendeineWinApiFunktionW() ... Funktionen. Diese erwarten einen UTF-16 kodierten String. Ich habe aber einfach blos einen wchar_t String mittels L"" übergeben. Hier ein kurzer Überblick, wie ich mein Fenster erstelle.
Code: Alles auswählen
#include <exception>
#include <string>
#include <sstream>
#include <Windows.h>
namespace UnnamedProject
{
//-----------------------------------------------------------------------------------------------------------
// Bewirkt, dass eine Instanz weder kopiert noch zugweiesen werden kann.
//-----------------------------------------------------------------------------------------------------------
class INonCopyAssignable
{
protected:
//-----------------------------------------------------------------------------------------------------------
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
INonCopyAssignable()
{
return;
}
private:
//-----------------------------------------------------------------------------------------------------------
// Nicht implementiert.
//-----------------------------------------------------------------------------------------------------------
INonCopyAssignable(INonCopyAssignable const &);
//-----------------------------------------------------------------------------------------------------------
// Nicht implementiert.
//-----------------------------------------------------------------------------------------------------------
INonCopyAssignable & operator=(INonCopyAssignable const &);
};
}
namespace UnnamedProject
{
//-----------------------------------------------------------------------------------------------------------
// Eine unspezifische Ausnahme.
//-----------------------------------------------------------------------------------------------------------
class Exception : public std::exception
{
public:
//-----------------------------------------------------------------------------------------------------------
// Initialisiert die Ausnahme.
//-----------------------------------------------------------------------------------------------------------
explicit Exception(char const * description)
: exception(description)
{
return;
}
//-----------------------------------------------------------------------------------------------------------
// Gibt die Beschreibung zurück.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
char const * GetDescription() const
{
return what();
}
};
}
namespace UnnamedProject
{
namespace Windows
{
//-----------------------------------------------------------------------------------------------------------
// Wirft eine Windows-spezifische Ausnahme.
//-----------------------------------------------------------------------------------------------------------
void ThrowException(char const * message, ::DWORD const error = ::GetLastError())
{
std::stringstream format;
format
<< "Windows error ["
<< error
<< "] -> "
<< message;
throw Exception(format.str().c_str());
}
//-----------------------------------------------------------------------------------------------------------
// Eine unspezifische Fensterklasse.
//-----------------------------------------------------------------------------------------------------------
class WindowClass : private INonCopyAssignable
{
private:
::HINSTANCE const myModuleInstance;
std::wstring const myClassName;
public:
//-----------------------------------------------------------------------------------------------------------
// Registriert die Fensterklasse.
// Wirft eine Windows-spezifische Ausnahme bei einem Fehler.
//-----------------------------------------------------------------------------------------------------------
WindowClass(
::HINSTANCE const & moduleInstance,
::HICON const & icon,
::HCURSOR const & cursor,
::HBRUSH const & backgroundColor,
::WNDPROC const & windowProcedure,
::WCHAR const * className, // <---- UTF-16 String
::WCHAR const * menuName, // <---- UTF-16 String
::UINT const & style)
: myModuleInstance(moduleInstance)
, myClassName(className)
{
::WNDCLASSEXW description;
description.cbSize = sizeof(::WNDCLASSEXW);
description.cbClsExtra = 0;
description.cbWndExtra = 0;
description.hInstance = moduleInstance;
description.hIcon = icon;
description.hIconSm = icon;
description.hCursor = cursor;
description.hbrBackground = backgroundColor;
description.lpfnWndProc = windowProcedure;
description.lpszClassName = className;
description.lpszMenuName = menuName;
description.style = style;
if (::RegisterClassExW(&description) == 0)
ThrowException("::RegisterClassExW() failed.");
return;
}
//-----------------------------------------------------------------------------------------------------------
// Meldet die Fensterklasse ab.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
~WindowClass()
{
::UnregisterClassW(myClassName.c_str(), myModuleInstance);
return;
}
};
}
}
namespace UnnamedProject
{
namespace Windows
{
//-----------------------------------------------------------------------------------------------------------
// Ein unspezifisches Fenster.
//-----------------------------------------------------------------------------------------------------------
class Window : private INonCopyAssignable
{
private:
::HWND myWindow;
public:
//-----------------------------------------------------------------------------------------------------------
// Erstellt das Fenster.
// Wirft eine Windows-spezifische Ausnahme bei einem Fehler.
//-----------------------------------------------------------------------------------------------------------
Window(
::DWORD const style,
::DWORD const extendedStyle,
::WCHAR const * className, // <---- UTF-16 String
::WCHAR const * windowName, // <---- UTF-16 String
int const positionX,
int const positionY,
int const width,
int const height,
::HWND const & parentWindow,
::HMENU const & menu,
::HINSTANCE const & moduleInstance)
: myWindow(::CreateWindowExW(
extendedStyle,
className,
windowName,
style,
positionX,
positionY,
width,
height,
parentWindow,
menu,
moduleInstance,
nullptr))
{
if (myWindow == nullptr)
ThrowException("::CreateWindowExW() failed.");
return;
}
//-----------------------------------------------------------------------------------------------------------
// Zerstört das Fenster.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
~Window()
{
// Den Benutzerbereich des Fensters zurücksetzen. Dies, da in diesem möglicherweise eine Instanz
// gespeichert ist welche einen Nachrichtenhandler aufruft.
::SetWindowLongPtrW(myWindow, GWLP_USERDATA, reinterpret_cast<::LONG_PTR>(nullptr));
::DestroyWindow(myWindow);
return;
}
//-----------------------------------------------------------------------------------------------------------
// Erlaubt das Manipulieren der Instanz als ::HWND Handle.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
operator ::HWND & ()
{
return myWindow;
}
//-----------------------------------------------------------------------------------------------------------
// Erlaubt das Verwenden der Instanz als ::HWND Handle.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
operator ::HWND const & () const
{
return myWindow;
}
};
}
}
namespace UnnamedProject
{
//-----------------------------------------------------------------------------------------------------------
// Die Hauptanwendung.
//-----------------------------------------------------------------------------------------------------------
class Application : private INonCopyAssignable
{
private:
Windows::WindowClass const myWindowClass;
Windows::Window myWindow;
bool myRunningState;
bool myValidState;
public:
//-----------------------------------------------------------------------------------------------------------
// Initialisiert die Anwendung.
//-----------------------------------------------------------------------------------------------------------
explicit Application(::HINSTANCE const & moduleInstance)
// Bevor ein Fenster erstellt werden kann, muss eine entsprechende Fensterklasse registriert werden.
: myWindowClass(
moduleInstance,
::LoadIconW(nullptr, IDI_APPLICATION),
::LoadCursorW(nullptr, IDC_ARROW),
reinterpret_cast<::HBRUSH>(::GetStockObject(BLACK_BRUSH)),
&Application::WindowProcedure,
L"RenderWindow", // <---- UTF-16 ???
nullptr,
CS_DBLCLKS)
, myWindow(
WS_OVERLAPPEDWINDOW,
WS_EX_APPWINDOW,
L"RenderWindow", // <---- UTF-16 ???
L"Unnamed Project", // <---- UTF-16 ???
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
nullptr,
nullptr,
moduleInstance)
, myRunningState(true)
, myValidState(true)
{
// Dem Fenster die Anwendungsinstanz übergeben damit deren Nachrichtenhandler aufgerufen werden kann.
::SetWindowLongPtrW(myWindow, GWLP_USERDATA, reinterpret_cast<::LONG_PTR>(this));
::ShowWindow(myWindow, SW_SHOWNORMAL);
::SetForegroundWindow(myWindow);
// Nicht minimiert starten.
if (::IsIconic(myWindow))
{
::ShowWindow(myWindow, SW_RESTORE);
::Sleep(100);
}
return;
}
//-----------------------------------------------------------------------------------------------------------
// Führt die Anwendung aus.
//-----------------------------------------------------------------------------------------------------------
void Run()
{
if (!myValidState)
return;
::MSG message = { 0 };
while (myRunningState)
{
myValidState = false;
// Alle verarbeiteten Nachrichten anschliessend entfernen.
if (::PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessageW(&message);
}
else
Update();
// Keine Ausnahme aufgetreten.
myValidState = true;
}
return;
}
private:
//-----------------------------------------------------------------------------------------------------------
// Die Nachrichtenprozedur des Fensters.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
static ::LRESULT CALLBACK WindowProcedure(
::HWND window,
::UINT message,
::WPARAM firstParameter,
::LPARAM secondParameter)
{
// Die Anwendungsinstanz ermitteln damit deren Nachrichtenhandler aufgerufen werden kann.
auto const application = reinterpret_cast<Application *>(::GetWindowLongPtrW(window, GWLP_USERDATA));
// Wenn die Nachricht nicht weiterverarbeitet werden soll, '0' zurückgeben.
if (application && !application->MessageHandler(message, firstParameter, secondParameter))
return 0;
// WM_CLOSE nicht weiterverarbeiten da ansonsten ::DestroyWindow() aufegrufen werden würde.
// Dies aber erledigt bereits der Destruktor einer Windows::Window Instanz.
if (message == WM_CLOSE)
return 0;
return ::DefWindowProcW(window, message, firstParameter, secondParameter);
}
//-----------------------------------------------------------------------------------------------------------
// Verarbeitet die Fensternachrichten.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
bool MessageHandler(::UINT const message, ::WPARAM const firstParameter, ::LPARAM const secondParameter)
{
switch (message)
{
case WM_CLOSE:
myRunningState = false;
return false;
}
return true;
}
//-----------------------------------------------------------------------------------------------------------
// Aktualisiert die Anwendung.
//-----------------------------------------------------------------------------------------------------------
void Update()
{
return;
}
};
}
//-----------------------------------------------------------------------------------------------------------
// Der Haupteinstiegspunkt.
// Wirft unter keinen Umständen eine Ausnahme.
//-----------------------------------------------------------------------------------------------------------
int WINAPI WinMain(::HINSTANCE moduleInstance, ::HINSTANCE, ::LPSTR, int)
{
using namespace UnnamedProject;
try
{
Application application(moduleInstance);
application.Run();
}
catch (std::exception const & exception)
{
::MessageBoxA(
HWND_DESKTOP,
exception.what(),
"Unnamed Project - Unhandled exception",
MB_ICONERROR |
MB_SETFOREGROUND);
}
catch (...)
{
::MessageBoxA(
HWND_DESKTOP,
"System exception",
"Unnamed Project - Unhandled exception",
MB_ICONERROR |
MB_SETFOREGROUND);
}
return 0;
}
Soweit ich das verstanden habe, ist es durchaus möglich, einen UTF-8 kodierten String in einem std::string (const char *) abzuspeichern. Und ein std::wstring (const wchar_t *) ist einfach blos ein Widestring, welcher aber benutzt werden kann, um einen UTF-16 String zu speichern.
Nun bin ich auf zwei WinApi Funktionen gestossen (::WideCharToMultiByte() und ::MultiByteToWideChar()), welche UTF-8 sowie UTF-16 String erstellen können. Muss ich nun bei jedem Aufruf einer WinAPIW() Funktion einen std::string erstellen und diesen mit ::MultiByteToWideChar() in einen UTF-16 std::wstring umwandeln? Denn irgendwie scheint bei mir (Visual Studio 2012 RC) das C++ 11 Feature u"bla" nicht unterstützt zu werden.
Besten Dank