Win32 APIでのエラー取得
Win32 APIの実行によりエラーが発生した場合,GetLastError関数(MSDNのドキュメント)でエラーコードを取得し,FormatMessage関数(MSDNのドキュメント)でメッセージを文字列に変換する.// 002_print_last_error.cpp #include <tchar.h> #include <Windows.h> #include <iostream> #include "using_console.h" using namespace std; //! Win32 APIでのエラーをコンソールに出力する void printLastError(); int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow ) { // cout, cinが使えるようにコンソールを割り当てる using_console uc; // 敢えて失敗するように未設定のウィンドウクラスの登録を行う WNDCLASSEX wcx = { 0 }; if(RegisterClassEx(&wcx) == 0){ printLastError(); cout << "終了します.何か入力してください." << endl; cin.get(); return 0; } return 0; } /*! * GetLastError()によるエラーコードをFormatMessage()により * 文字列に変換し,標準出力に出力する. */ void printLastError() { LPSTR pBuffer = NULL; DWORD error = GetLastError(); DWORD result = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&pBuffer), 0, NULL ); if(result > 0 && pBuffer){ cout << pBuffer << endl; LocalFree(pBuffer); } }
コンパイル
前回実装したコンソール割り当て用クラスのcppを追加し,User32.libをリンクする.
cl /EHsc 002_print_last_error.cpp using_console.cpp /link User32.lib
ウィンドウクラスの登録
エラーを確認するための準備が整ったので,実際にウィンドウを表示する.まずは,ウィンドウクラスのWNDCLASSEX構造体(MSDNのドキュメント)を登録する必要がある.
// 003_register_window_class.cpp #include <tchar.h> #include <Windows.h> #include <iostream> #include "using_console.h" using namespace std; //! Win32 APIでのエラーをコンソールに出力する void printLastError(); int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow ) { using_console uc; // 登録が成功するための最低限の設定 WNDCLASSEX wcx = { 0 }; // 構造体のサイズ wcx.cbSize = sizeof wcx; // ウィンドウクラス名 wcx.lpszClassName = TEXT("hello"); if(RegisterClassEx(&wcx) == 0){ printLastError(); cout << "終了します.何か入力してください." << endl; cin.get(); return 0; } return 0; } void printLastError() { /* 省略 */ }
コンパイル
cl /EHsc 003_register_window_class.cpp using_console.cpp /link User32.lib
ウィンドウの生成
ウィンドウクラスの登録に成功したら,そのウィンドウクラスを使ってウィンドウを生成する.ウィンドウの生成には,CreateWindow関数(MSDNのドキュメント)を使う.ただし,今の状態のウィンドウクラスでウィンドウを生成しようとすると,強制終了してしまう.
// 004_fail_to_create_window.cpp #include <tchar.h> #include <Windows.h> #include <iostream> #include "using_console.h" using namespace std; //! Win32 APIでのエラーをコンソールに出力する void printLastError(); int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow ) { using_console uc; /* ウィンドウクラスの登録 (003_register_window_class.cppと同じ) */ HWND hWnd = CreateWindow( wcx.lpszClassName, TEXT("hello"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if(!hWnd){ printLastError(); cin.get(); return 0; } return 0; } void printLastError() { /* 省略 */ }
このコードが動くようにするためには,WNDLCASSEX構造体の初期化時にウィンドウプロシージャを登録しておく必要がある.
// 005_create_window.cpp // 色々省略 WNDCLASSEX wcx = { 0 }; wcx.cbSize = sizeof wcx; wcx.lpszClassName = TEXT("hello"); wcx.lpfnWndProc = DefWindowProc;
Win32 APIに用意されているデフォルトのウィンドウプロシージャDefWindowProc(MSDNのドキュメント)を登録しておくことで,無事ウィンドウが生成される.
コンパイル
cl /EHsc 004_fail_to_create_window.cpp using_console.cpp /link User32.lib cl /EHsc 005_create_window.cpp using_console.cpp /link User32.lib
ウィンドウの表示
ウィンドウの生成に成功したら,ShowWindow関数(MSDNのドキュメント)を呼び出し,ウィンドウを表示する.初回の呼び出し時にはWinMain関数の引数のnCmdShowを与える必要がある.
// 006_show_window.cpp #include <tchar.h> #include <Windows.h> #include <iostream> #include "using_console.h" using namespace std; //! Win32 APIでのエラーをコンソールに出力する void printLastError(); int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow ) { using_console uc; WNDCLASSEX wcx = { 0 }; wcx.cbSize = sizeof wcx; wcx.lpszClassName = TEXT("hello"); wcx.lpfnWndProc = DefWindowProc; RegisterClassEx(&wcx); HWND hWnd = CreateWindow(/* 省略 */); if(!hWnd){ printLastError(); cin.get(); return 0; } ShowWindow(hWnd, nCmdShow); cout << "終了します.何かキーを入力してください." << endl; cin.get(); return 0; } void printLastError() { /* 省略 */ }
コンパイル
cl /EHsc 006_show_window.cpp using_console.cpp /link User32.lib
第二回まとめ
- ウィンドウを生成するにはまずRegisterClassExでウィンドウクラスを登録
- CreateWindowでウィンドウの生成
- ShowWindowでウィンドウの表示
遠回りなだけあってOpenGLが出てくるまでが長い.GLUTやGLEWが色々やってくれているのがよく分かる.
第三回へ
0 件のコメント:
コメントを投稿