マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

ウィンドウ・システムの詳細を理解して、

「バックグラウンド・スレッドから上げた
モーダル・ダイアログがモーダルにならない理由」

などを理解できるようにする。

テンプレート

Windowsプログラムは、

から成り立つ。

そして(1)WinMain?の中は、

の4つのパートから成り立つ。

//(1)Winmain
 WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
  // ウィンドウクラス構造体を設定

  //(A) ウインドウクラスの登録
  RegisterClassEx

  //(B) ウインドウを作成
  CreateWindow

  //(C) ウインドウを表示
  ShowWindow
  UpdateWindow

  //(D) メッセージループ
}

//(2) ウィンドウプロシージャ
WndProc (
HWND hWnd,
UNIT message,
WPARAM wParam,
LPARAM lParam )
{
   ・・・
}

Windowsメッセージキューとメッセージループ

Windowsメッセージキュー

MSMQではなく、ウィンドウ メッセージ用のキュー。
ウィンドウ・システム(WindowsのGUI)の根幹をなすメカニズム。

作成方法

THREADINFO構造体
項目APIとの関連
ポストメッセージPostMessage()で送信されるメッセージ
送信メッセージキューSendMessage()で送信されるメッセージ、別スレッドの場合
応答メッセージキューSendMessage()で送信されるメッセージ、別スレッドの場合
仮想入力キュー(ハードウェア入力)
ウェイクフラグPostQuitMessage?()
nExitCode?PostQuitMessage?()
スレッドローカル・入力状態管理変数

作成単位

利用方法

後述のWin32APIを使用する。

その他の利用方法

などでも利用される。

メッセージループ

GetMessage?関数でWindowsメッセージキューから取り出したMSG 構造体を
DispatchMessage?関数でウィンドウ・プロシージャに渡す。

while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ */
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}

ウィンドウ的なもの

ウィンドウクラス

.NETで言う、FormもControlも全てが
ウィンドウ(hwnd:ウィンドウハンドルを持つ)。

Form的なもの

自前のウィンドウクラス名を持つウィンドウクラス(.NETで言う、Form的なもの)は、
WndProc?を用意して、WNDCLASS 構造体にまとめて、 RegisterClassEx?で登録する。
その時に 自前のウィンドウクラス名 を登録し、CreateWindowEXで、ウィンドウを作る。

そのイベントは、すべて、 WNDCLASS で登録した WndProc? へ来る(これについては後述)。

Control的なもの

あらかじめ登録されている既定のウィンドウクラスとしては

がある(.NETで言う、Control的なもの)。

これらは登録済みで個別用途のウィンドウクラスであるため
(例えばボタンウィンドウやエディットボックスなど)、
下記のRegisterClassEx?関数を使用せずに作成可能。

自前のウィンドウクラス(Form的な)の中へ、
既定のウィンドウクラス(Control的な)を貼り付けたければ、
自前で CreateWindow?す(自前のウィンドウクラス の hwnd,...)する。

ダイアログ

VC++のダイアログエディタで、ダイアログリソースを作ってCreateDialog?する。

ダイアログのイベントは、WndProc?ではなく、DlgProc? へ来る(これについては後述)。

ウィンドウプロシージャ

イベントハンドラみたいなもの。

以下のように、イベントハンドラを実装する。

WndProc?

//(2) ウィンドウプロシージャ
WndProc (
HWND hWnd,
UNIT message,
WPARAM wParam,
LPARAM lParam )
{
   ・・・
}

DlgProc?

???

サブクラス化

この既定のWndProc?を置き換えることで、
イベントの挙動(≠イベント・ハンドラ、ボタン押下時にボタンが凹む等)
をカスタマイズすることが可能である。

Win32PI

ウィンドウの生成

メッセージの送信

PostMessage

PostMessageはメッセージ・ループにキューイングする。  

SendMessage

SendMessageはウィンドウ・プロシージャ(WndProc?)を直接呼び出す。

以下は、SendMessageの同期呼出ハングの問題を回避するための関数(送信側)。

以下は、SendMessageの同期呼出ハングの問題を回避するための関数(受信側)。

メッセージ・ループで使用

GetMessage?

while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ */
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}

ウィンドウプロシージャで使用

WindowProc?

サブクラス化

ハードウェア入力モデル

関連するWin32API

フォーカス

アクティブ化

フォアグラウンド化

キー入力状態

カーソル入力状態

VIQの共有

については自分のものを使い続ける。

DLL注入とAPIフック

UIオートメーションの裏側。

ちなみに、操作ログの取得って

GetMessege?のフックと

AttachThreadInput?

の2つの方法がありそうですが、

現行はどっちを使用しているんでしょうか?

答えは、GetMessege?のフックらしい。

↓↓↓

例えばAttachThreadInput?SetWindowLongPtr?を使用して
別プロセスのウィンドウをサブクラス化できるか?と言うとこれは当然できない。
これは、呼び出し元のWndProc?のアドレスが呼び出し先のプロセスで有効でないから。

しかし、これを可能にする方法がある。「DLL注入」と「APIフック」である。

DLL注入

APIフック

別プロセスのウィンドウにGetMsgProc?フックプロシージャをインストールしてメッセージを監視する。
GetMsgProc?フックプロシージャは、前述のDLL注入のDLL中に実装しておく。

SetWindowsHookEx? 関数

http://msdn.microsoft.com/ja-jp/library/cc430103.aspx

フックタイプと関数ポインタ

スパイ

Spy++やWinspector Spyを使用すると、ウィンドウのメッセージの分析が可能。

Spy++

Winspector Spy

参考

書籍

msdn

標準 Windows API

Win32 API 階梯

Windowsプログラムの正しい雛形

WindowsAPI Programming

EternalWindows?

http://eternalwindows.jp/index.html


Tags: :Windows, :ウィンドウ・システム


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS