ホームページ  >  記事  >  運用・保守  >  Win32 SDKの基礎 (11) メッセージキューとGetMessage/PeekMessage、SendMessage/Postmesageの詳細説明

Win32 SDKの基礎 (11) メッセージキューとGetMessage/PeekMessage、SendMessage/Postmesageの詳細説明

黄舟
黄舟オリジナル
2017-06-06 10:09:435741ブラウズ

1. メッセージキュー

1.1 メッセージキュー

メッセージキューは、メッセージをキューに格納するために使用されるキューであり、すべてのウィンドウプログラムはメッセージキューを持っています。待ち行列。

1.2 メッセージ キューの種類

システム メッセージ キュー: オペレーティング システムによって維持されるメッセージ キュー。マウスやキーボードのメッセージなど、システムによって生成されたメッセージが保存されます。

プログラム メッセージ キュー: 各アプリケーション (スレッド) に属し、アプリケーションによって維持されるメッセージ キュー。

マウス、キーボードなどのメッセージが生成されると、メッセージはまずシステム メッセージ キューに保存され、次にオペレーティング システムが保存されたメッセージに基づいて対応するウィンドウのメッセージ キューを見つけて、メッセージをウィンドウのメッセージキュー。

1.3 キューメッセージと非キューメッセージ

キューメッセージ: メッセージは送信後、まずキューに入れられ、次にメッセージ ループ を通じて取得されます。一般的なキュー メッセージ: キーボード、マウス、タイマーメッセージなど。

非キューメッセージ: メッセージ送信後、ウィンドウのメッセージ処理関数を直接見つけて、メッセージキューを経由せずにメッセージ処理関数を呼び出して処理します。一般的なキュー以外のメッセージ: WM_PAINT、WM_SIZE など。

2. メッセージ ループと GetMessage/PeekMessage

2.1 メッセージ ループ

一般的なメッセージ ループは次のとおりです:

void Message(HWND hWnd)  
{  
	MSG nMsg = { 0 };
	while (GetMessage(&nMsg, hWnd, 0, 0))  
	{  
		TranslateMessage(&nMsg);  
		DispatchMessage(&nMsg);  

		if(nMsg.message == WM_PAINT)
		{
			char buff[30]={};
			sprintf(buff,"处理消息%d\n",nMsg.message);
			WriteConsole(hOutput,buff,sizeof(buff),NULL,NULL);
		}
	}  
}

GetMessage/PeekMessage: プログラムのメッセージ キューからメッセージを取得します。

TranslateMessage: キーボードのキー押下などのメッセージを文字メッセージに翻訳します。

DispatchMessage: 翻訳されたメッセージをプログラムのメッセージ キューに再度入れます。

2.2 GetMessage と PeekMessage

GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
)

lpMsg: スレッドのメッセージ キューからメッセージ情報を受け取る MSG 構造体へのポインター。 hWnd: メッセージを取得するウィンドウのハンドル。値が NULL の場合、GetMessage は呼び出し側スレッドに属する任意のウィンドウのメッセージを取得し、スレッド メッセージは PostThreadMessage を通じて呼び出し側スレッドに送信されます。 wMsgFilterMin: 取得するメッセージの最小値を指定する
整数
wMsgFilterMax: 取得するメッセージの最大値を指定する整数。 戻り値: 関数が WM_QUIT 以外のメッセージを取得した場合、ゼロ以外の値を返します。関数が WM_QUIT メッセージを取得した場合、戻り値は 0 です。エラーが発生した場合、戻り値は -1 です。たとえば、hWnd が無効なウィンドウ ハンドルであるか、lpMsg が無効なポインタである場合です。さらに詳しい
エラー情報
を取得したい場合は、GetLastError 関数を呼び出してください。

BOOL PeekMessage(
LPMSG IpMsg,
HWND hWnd,
UINT wMSGfilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
lpMsg: メッセージ情報を受信するための MSG 構造体ポインター。

hWnd: メッセージがチェックされるウィンドウ ハンドル。

wMsgFilterMin: メッセージ範囲内のチェックする最初のメッセージを指定します。
wMsgFilterMax: チェックするメッセージ範囲内の最後のメッセージを指定します。
wRemoveMsg: メッセージがどのように処理されるかを決定します。このパラメータは次の値のいずれかをとります:

値 意味 PM_NOREMOVE PeekMessage が処理された後、メッセージはキューから削除されません。

PM_REMOVE

PeekMessage が処理された後、メッセージはキューから削除されます。

PM_NOYIELD

このフラグにより​​、システムは呼び出し側プログラムがアイドルになるのを待っているスレッドを解放しなくなります。 PM_NOYIELD は、PM_NOREMOVE または PM_REMOVE に自由に組み合わせることができます。


GetMessage和PeekMessage的主要区别在于:GetMessage是阻塞函数,它会在消息循环中会一直阻塞直到消息队列中出现了消息可以被获取,而PeekMessage是非阻塞函数,不管有没有获取到消息队列中的消息,它都会返回。PeekMessage更多用来检测消息队里中是否有消息,它的最后一个参数可以用来指定获取到消息后要不要把消息从消息队列中移除,通常情况下通过PeekMessage检测到消息队列有消息之后,再调用GetMessage区获取。

2.3 GetMessage/PeekMessage获取消息的过程

1、先在程序的消息队列中查找消息,如果有队列消息,就取出消息。

2、如果程序的消息队列中没有消息,向系统的消息队列获取属于本程序的消息。如果系统的消息队列中有属于本程序的消息,系统的消息队列会将消息分发到本程序的消息队列中。

3、如果系统的消息队列也没有消息,检查窗口需要绘制的区域是否需要重绘,如果发现有需要重绘的区域,产生WM_PAINT消息。

4、如果没有重新绘制区域,检查是否具有到时的定时器,如果有产生WM_TIMER定时器消息。

5、如果没有到时的定时器,整理程序的资源、内存等等。

三、SendMessage和PostMessage

LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM IParam
)

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

BOOL WINAPI PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);

hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:
HWND_BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、 被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口
NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样
Msg:指定被寄送的消息。
wParam:指定附加的消息特定的信息。
LParam:指定附加的消息特定的信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零

1、SendMessage

       发送消息到指定的窗口,并等候对方将消息处理,为阻塞函数,获取消息的执行结果后返回。主要需要发送非队列消息,发送的消息不经过消息队列。

2、PostMessage

        发送消息到程序的消息队列,不管消息有没有被处理都会立即返回,用于队列消息的发送

以上がWin32 SDKの基礎 (11) メッセージキューとGetMessage/PeekMessage、SendMessage/Postmesageの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。