Problem
Eine C++ Anwendung hat als Konsolenanwendung den Einstiegspunkt
int main(void) {...}
aber als Win32-Anwendung den Einstiegspunkt
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {...}
Es wird nach einer Möglichkeit gesucht, die WinMain-Methode von einer Konsolen-Anwendung aus aufzurufen, um eine Hauptfenster in der Konsolenanwendung zu generieren.
Ansatz
MSDN definiert die WinMain()-Methode folgendermaßen:
- hInstance ist ein Element, das als „Handle für eine Instanz“ oder „Handle für ein Modul“ bezeichnet wird. Das Betriebssystem identifiziert mithilfe dieses Werts die ausführbare Datei (EXE), wenn diese in den Arbeitsspeicher geladen wird. Das Instanzhandle wird für bestimmte Windows-Funktionen benötigt—z. B. um Symbole oder Bitmaps zu laden.
- hPrevInstance hat keine Bedeutung. Es wurde in 16-Bit-Windows verwendet, es ist aber jetzt stets 0 (null).
- pCmdLine enthält die Befehlszeilenargumente als Unicode-Zeichenfolge.
- nCmdShow ist ein Flag, das angibt, ob das Hauptanwendungsfenster minimiert, maximiert oder in Normalgröße angezeigt wird.
Die WinMain()-Methode kann von der main()-Anwendung aufgerufen werden, wenn man ein hInstance Handle bekommt. Dies geht folgermaßen:
GetModuleHandle(NULL)
Lösung – Solution
// HelloWorld.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include <windows.h> // Das hier braucht man nur wenn man die test.wav abspielen will //#pragma comment(lib,"winmm.lib") //für MSV C++ const char g_szClassName[] = "myWindowClass"; // Step 4: the Window Procedure 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; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; 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 = (LPCWSTR) g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx(&wc)) { MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, (LPCWSTR) g_szClassName, L"Eine Mischung aus Console und Window App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if (hwnd == NULL) { MessageBox(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Step 3: The Message Loop while (GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } int main() { // Das hier spielt eine Datei test.wav im gleichen Verzeichnis //PlaySound(L"test.wav", NULL, SND_ASYNC); WinMain(GetModuleHandle(NULL), 0, 0, 1); printf("Se hams Fenster geschlossen!"); getchar(); return 0; }