第二回目はウィンドウの作成方法について説明します まず、以下の用語は ウィンドウクラスとウィンドウスタイルは ウィンドウプロシージャとは では、早速作ってみましょう Win32プロジェクトを選択します 「次へ」を押して進んでください(完了を押してはいけません) ・Windowsアプリケーションにチェックがついているか確認して 次に、main.cppを作ります main.cppができたら #include <tchar.h> #include <windows.h> #include <windowsx.h> int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { MessageBox(NULL,_T("Hello World"),_T("Msg Box"),MB_OK); return 0; } ここで気づいてほしいことがあります また、起動してみるとコンソール画面(黒画面)は表示されません この関数でまず、いきなり変だと感じると思うのは__stdcallと書かれている部分です ではWinMain関数の引数について説明します 第3引数(lpCmdLine)はコマンドライン引数を格納してる文字列です では、 ・ウィンドウクラスを定義し、登録 ゆっくり順番に見ていけば大丈夫です // ウィンドウズバージョン指定 #define _WIN32_WINNT 0x0500 #include <stdio.h> #include <stdlib.h> #include <tchar.h> #include <windows.h> #include <windowsx.h> #include <commctrl.h> #pragma comment(lib,"comctl32.lib") #pragma comment(lib,"winmm.lib") // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { const TCHAR* szClassName = _T("Basic"); // ウィンドウクラス名 /********************************************************/ /* ウィンドウクラスの定義と作成 */ /********************************************************/ // 新規ウィンドウクラスの定義 WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); // ウィンドウクラスのサイズ wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // ウィンドウクラスのスタイル wc.lpfnWndProc = WndProc; // ウィンドウプロシージャへの関数ポインタ wc.cbClsExtra = 0; // 0(使わない) wc.cbWndExtra = 0; // 0(使わない) wc.hInstance = hInstance; // インスタンスハンドル wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // ウィンドウのアイコン wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // ウィンドウのカーソル wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景色(再描画のとき、この設定ブラシで塗りつぶしが行われる) wc.lpszMenuName = NULL; // メニュー名 wc.lpszClassName = (LPCTSTR)szClassName; // ウィンドウクラス名 wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);// 小さいアイコンが設定された場合の情報を記述 // ウィンドウクラスの登録 if(!RegisterClassEx(&wc)) return -1; // 登録失敗 /********************************************************/ /* ウィンドウの作成 */ /********************************************************/ HWND hWnd = CreateWindowEx( 0, //拡張ウィンドウスタイル szClassName, //ウィンドウクラス名 _T("タイトル"), //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウスタイル CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドルorリソースID hInstance, //インスタンスハンドル NULL); // ウィンドウ作成失敗 if (hWnd == NULL) return -1; // ウィンドウを可視状態にする ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); /********************************************************/ /* メッセージループ */ /********************************************************/ MSG msg = {}; while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); } else{ // メッセージ処理をしてないとき } } return 0; } // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return (DefWindowProc(hWnd, msg, wParam, lParam)); } 正直、冗長な部分も多いと思いますので // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); これはウィンドウに送られてきたメッセージを処理するための関数です メイン関数です int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) WINAPI、CALLBACKは__stdcallが#defineで置き換えられているだけです(ウィンドウズの関数なので__stdcall) WNDCLASSEX構造体の変数に色々代入し、 CS_HREDRAW、CS_VREDRAWは wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // ウィンドウクラスのスタイル ウィンドウへのメッセージを処理するプロシージャをセットします wc.lpfnWndProc = WndProc; // ウィンドウプロシージャへの関数ポインタ インスタンスハンドルをセットします wc.hInstance = hInstance; // インスタンスハンドル アイコンとカーソルをセットします wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // ウィンドウのアイコン wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // ウィンドウのカーソル ウィンドウの背景色をセットします wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景色(再描画のとき、この設定ブラシで塗りつぶしが行われる) メニューをセットします(ウィンドウを作成するときにもセットできるのでNULLで構いません) wc.lpszMenuName = NULL; // メニュー名 ウィンドウクラス名をセットします wc.lpszClassName = (LPCTSTR)szClassName; // ウィンドウクラス名 ウィンドウクラスを登録します // ウィンドウクラスの登録 if(!RegisterClassEx(&wc)) return -1; // 登録失敗 ウィンドウクラスに基づいて HWND hWnd = CreateWindowEx( 0, //拡張ウィンドウスタイル szClassName, //ウィンドウクラス名 _T("タイトル"), //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウスタイル CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドルorリソースID hInstance, //インスタンスハンドル NULL); ここで重要なのは 第1引数の拡張ウィンドウスタイルはウィンドウスタイルの拡張です X座標、Y座標、幅、高さに 第9引数は 第10引数は 第11引数はインスタンスハンドルを指定します ウィンドウを作成したら MSG msg = {}; while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); } else{ // メッセージ処理をしてないとき } } ウィンドウズのメッセージは while(msg.message != WM_QUIT) PeekMessage関数でメッセージキューからメッセージを取得します メッセージの処理はウィンドウプロシージャで書きます // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return (DefWindowProc(hWnd, msg, wParam, lParam)); } msgにウィンドウに送られたメッセージが入ります 今回はウィンドウが破棄されたときにメッセージループを抜けるために 残りのwParam,lParamにはメッセージに応じたパラメータが入っています かなり長くなってしまいましたがウィンドウズプログラミングにおいて あと、基本的なウィンドウを作る場合は長々と書きましたが また、ウィンドウは一度作ったあと(既存のウィンドウ)でも
|