Version 14.23
メッセージの復習
「今回は、ウィンドウとスレッドの組み合わせについて考えてみます」
『お、一番使いそうな例』
「そう、よく使いそうで、けれども難しい部分です」
『難しいの?』
「うん、ウィンドウの仕組みについてわかっていないといけないから。まず
そのために、 Version 10.01 ( No.179 ) の頃の、 MFC を使わないウィン
ドウプログラムを作ってみます」
『ウィンドウプロシージャとか作って中でメッセージの振り分けするヤツ
ね』
「そうそれ。まず【ファイル】−【新規作成】で【Win32 Application】
を選んでください。プロジェクト名は好きなもので」
『そういうの困る……』
「プロジェクトが完成したら【ファイルの新規作成】で Main.cpp という
ファイルを作ってください」
『その辺も Version 10.01 ( No.179 ) と同じね』
「ファイルを作ったら、その中にこう書き込んでください」
#include <Windows.h>
// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
( HWND p_hWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_DESTROY )
{
// ×ボタンが押されました。
PostQuitMessage( 0 );
return 0;
}
// 標準的な処理をします。
return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}
// メッセージループ。
int MessageLoop()
{
BOOL bRes;
MSG stMsg;
// メッセージループです。
while( 1 )
{
// メッセージをキューから取り出します。
bRes = GetMessage( &stMsg, NULL, 0, 0 );
if (
( bRes == 0 )
||
( bRes == -1 )
)
{
// 終了するのでループから抜けます。
break;
}
// メッセージを変換します。
TranslateMessage( &stMsg );
// ウィンドウプロシージャに送ります。
DispatchMessage( &stMsg );
}
return stMsg.wParam;
}
// ウィンドウクラスを登録します。
bool RegistWndClass
( const char *const p_pchWndClassName
, HINSTANCE p_hInstance
)
{
// ウィンドウクラス登録用構造体。
WNDCLASSEX stWndClassEx;
stWndClassEx.cbSize = sizeof( stWndClassEx );
stWndClassEx.style
= CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
stWndClassEx.lpfnWndProc = WndProc;
stWndClassEx.cbClsExtra = 0;
stWndClassEx.cbWndExtra = 0;
stWndClassEx.hInstance = p_hInstance;
stWndClassEx.hIcon = LoadIcon( NULL, IDI_EXCLAMATION );
stWndClassEx.hCursor = LoadCursor( NULL, IDC_ARROW );
stWndClassEx.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
stWndClassEx.lpszMenuName = NULL;
stWndClassEx.lpszClassName = p_pchWndClassName;
stWndClassEx.hIconSm = LoadIcon( NULL, IDI_EXCLAMATION );
// ウィンドウクラスを登録します。
if( RegisterClassEx( &stWndClassEx ) == 0 )
{
// 失敗しました。
return false;
}
return true;
}
// ウィンドウを作ります。
bool CreateAndShowWnd
( const char *const p_pchWndClassName
, HINSTANCE p_hInstance
, int p_iCmdShow
)
{
// ウィンドウを作ります。
HWND hWnd = CreateWindow
( p_pchWndClassName
, "テスト"
, WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0
, CW_USEDEFAULT
, 0
, NULL
, NULL
, p_hInstance
, NULL
);
if( hWnd == NULL )
{
// ウィンドウの作成に失敗しました。
return false;
}
// ウィンドウを表示します。
ShowWindow( hWnd, p_iCmdShow );
UpdateWindow( hWnd );
return true;
}
// 最初に呼ばれる関数です。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
const char pchWndClassName[] = "SimpleWindowClass";
bool bRes
= RegistWndClass( pchWndClassName, p_hInstance );
if( bRes == false )
{
return -1;
}
bRes
= CreateAndShowWnd
( pchWndClassName
, p_hInstance
, p_iCmdShow
);
if( bRes == false )
{
return -1;
}
// メッセージループ開始!
return MessageLoop();
}
『長!』
「このプログラム見て、 Version 10.04 ( No.182 ) を思い出して」
『メッセージキューの話だよね』
「今回のプログラムはメッセージループやウィンドウプロシージャといった
ウィンドウの一番基本的な部分を押さえてあります」
『メッセージループが MessageLoop() で、ウィンドウプロシージャが
WndProc() ね。でも、これってどこがマルチスレッドと関係あるの?』
「というわけで次回に続く!」
『早!』
/*
Preview Next Story!
*/
『今回はなんか勉強した気がしない……』
「でも、メッセージまわりって普段やらないから忘れてるとこない?」
『う”』
「そういうことなら復習復習」
『はいはい』
「特に、次回はメッセージループやウィンドウプロシージャに触れるから」
『その辺が鍵なんだ』
「というわけで次回」
< Version 14.24 メッセージループとスレッド >
『につづく!』
「その辺復習しておかないと来週きついよ?」
『スレッドだけでも難しいのにウィンドウも一緒……』