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 件のコメント:
コメントを投稿