ウィンドウ・システム
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicros...
-[[戻る>Windows OSの基礎的トピック]]
* 目次 [#sb75d7ba]
#contents
*概要 [#od51b6e4]
ウィンドウ・システムの詳細を理解して、
>「バックグラウンド・スレッドから上げた~
モーダル・ダイアログがモーダルにならない理由」
などのさまざまな挙動を理解できるようにする。
*テンプレート [#s05a223e]
Windowsプログラムは、
-エントリポイント(プログラムの開始)である(1)WinMainと、
-Windowsから呼び出されて渡されたメッセージを処理する~
(2)ウインドウプロシ-ジャ(通常WinProcと書く)
から成り立つ。
そして(1)WinMainの中は、
-(A)ウインドウクラスの登録
-(B)ウィンドウの作成
-(C)ウインドウの表示
-(D)メッセージループ
の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メッセージキューとメッセージループ [#rf68c087]
**Windowsメッセージキュー [#z34491c0]
MSMQではなく、ウィンドウ メッセージ用のキュー。~
ウィンドウ・システム(WindowsのGUI)の根幹をなすメカニズ...
***作成方法 [#da9d8264]
-Windowsメッセージキューは、~
1つのスレッドが1つだけ保持できる。
--ウィンドウを作成したスレッドには、~
Windowsメッセージキューが与えられる。
--スレッドからメッセージ系のAPIを使用した場合も、~
Windowsメッセージキューが与えられる。
-この際、システムは、
--THREADINFO構造体を作成してスレッドに割り当てる。
--THREADINFO構造体はWindowsメッセージキューに関する情報を...
|>|THREADINFO構造体|h
|項目|APIとの関連|h
|ポストメッセージ|PostMessage()で送信されるメッセージ|
|送信メッセージキュー|SendMessage()で送信されるメッセージ...
|応答メッセージキュー|SendMessage()で送信されるメッセージ...
|仮想入力キュー(ハードウェア入力)|-|
|ウェイクフラグ|PostQuitMessage()|
|nExitCode|PostQuitMessage()|
|スレッドローカル・入力状態管理変数|-|
***作成単位 [#bff89f1a]
-Windowsメッセージキューは、複数のウィンドウ間で共有され...
--通常、1つのプロセスは、1つのUIスレッドで、複数(全て...
このため、通常、1プロセス、1UIスレッド、1Windowsメッセ...
--この理由は、1プロセスで、2つ以上のUIスレッドを持つ場...
画面間の通信をスレッドセーフに実装する必要があり実装し難...
***利用方法 [#j7fd3258]
後述のWin32APIを使用する。
-PostMessage()~
メッセージ・ループにキューイングする。
-SendMessage()~
ウィンドウ・プロシージャ(WndProc)を直接呼び出す。
***その他の利用方法 [#j7fd3258]
-プロセス間通信
-スレッド間通信
-COMのSTA(呼び出しの直列化)
などでも利用される。
**メッセージループ [#nca334b2]
GetMessage関数でWindowsメッセージキューから取り出したMSG ...
DispatchMessage関数でウィンドウ・プロシージャに渡す。
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ...
TranslateMessage(&msg);
DispatchMessage(&msg);
}
*ウィンドウ的なもの [#ibf9d3ef]
**ウィンドウクラス [#u8d37135]
.NETで言う、FormもControlも全てが~
ウィンドウ(hwnd:ウィンドウハンドルを持つ)。
-用語(7):ウィンドウクラスって?~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/winclass.html
>ウィンドウクラスとは、ウィンドウの雛形(テンプレート)の...
対応するウィンドウ関数・アイコン・カーソル・背景色など 基...
***Form的なもの [#qf9d4920]
自前のウィンドウクラス名を持つウィンドウクラス(.NETで言...
WndProcを用意して、WNDCLASS 構造体にまとめて、 RegisterCl...
その時に 自前のウィンドウクラス名 を登録し、CreateWindowE...
そのイベントは、すべて、 WNDCLASS で登録した WndProc へ来...
***Control的なもの [#hb30291b]
あらかじめ登録されている既定のウィンドウクラスとしては
-"BUTTON"
-"COMBOBOX"
-"EDIT"
-"LISTBOX"
-"MDICLIENT"
-"RichEdit"
-"RICHEDIT_CLASS"
-"SCROLLBAR"
-"STATIC"
がある(.NETで言う、Control的なもの)。
これらは登録済みで個別用途のウィンドウクラスであるため~
(例えばボタンウィンドウやエディットボックスなど)、~
下記のRegisterClassEx関数を使用せずに作成可能。
自前のウィンドウクラス(Form的な)の中へ、~
既定のウィンドウクラス(Control的な)を貼り付けたければ、~
自前で CreateWindowす(自前のウィンドウクラス の hwnd,...)...
**ダイアログ [#u0ed1ff6]
VC++のダイアログエディタで、ダイアログリソースを作ってCre...
ダイアログのイベントは、WndProcではなく、DlgProc へ来る(...
*ウィンドウプロシージャ [#ibfcede7]
イベントハンドラみたいなもの。
以下のように、イベントハンドラを実装する。
-Control的なウィンドウクラスの標準WndProcは、~
親ウィンドウクラスに対してSendMessageでWM_Commandを送るよ...
-Form的な親ウィンドウのカスタムWndProcに、~
WM_Commandを処理するカバレージをcase WM_COMMAND:等を使用...
-参考
--子ウインドウ~
http://eternalwindows.jp/control/controlbase/controlbase0...
**WndProc [#s2b8e69c]
//(2) ウィンドウプロシージャ
WndProc (
HWND hWnd,
UNIT message,
WPARAM wParam,
LPARAM lParam )
{
・・・
}
**DlgProc [#zb8aba2e]
???
**サブクラス化 [#n23e3ff2]
-GetWindowLong(hwnd, GWL_WNDPROC) を使って、今あるWndProc...
-SetWindowLong(hwnd, GWL_WNDPROC, 自前WndProc) で置き換え...
--元あったWndProcを呼ばなければ、そのイベントの処理を置き...
--自前WndProc の中で、 CallWndProc(取得したWndProc, pMsg)...
元のWndProcを呼ぶことで、WndProcのチェインに割って入る。
この既定のWndProcを置き換えることで、~
イベントの挙動(≠イベント・ハンドラ、ボタン押下時にボタン...
をカスタマイズすることが可能である。
*Win32PI [#m645932a]
**ウィンドウの生成 [#h0121534]
-WNDCLASS structure (Windows)~
http://msdn.microsoft.com/ja-jp/library/windows/desktop/m...
>ウィンドウクラスの属性を表します。
-RegisterClassEx 関数~
http://msdn.microsoft.com/ja-jp/library/cc410996.aspx
>ウィンドウクラスを登録します。
-CreateWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410713.aspx
>メモリ上にウィンドウを生成します。
-ShowWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411211.aspx
>ウィンドウを表示します。
-UpdateWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc428780.aspx
>ウィンドウを更新します。
-GetWindowThreadProcessId 関数~
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx
>指定されたウィンドウを作成したスレッドの ID を取得します。
**メッセージの送信 [#w1750e46]
***PostMessage [#p8157cb2]
PostMessageはメッセージ・ループにキューイングする。
-PostMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410952.aspx
--指定されたウィンドウのメッセージキューに 1 つのメッセー...
--対応するスレッドがメッセージを処理するのを待たずに制御...
-PostThreadMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410979.aspx
--指定されたスレッドのメッセージキューに 1 つのメッセージ...
--この関数は、スレッドがメッセージを処理するのを待たず、...
-PostQuitMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410954.aspx
>WM_NCLBUTTONDOWN メッセージなどを取得した場合に、~
WM_QUIT メッセージをメッセージキューにポストする。
***SendMessage [#v0311886]
SendMessageはウィンドウ・プロシージャ(WndProc)を直接呼...
-SendMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411022.aspx
--1 つまたは複数のウィンドウへ、指定されたメッセージを送...
--指定されたウィンドウのウィンドウプロシージャを呼び出し...
--ウィンドウプロシージャがメッセージを処理し終わった後で...
--基本的には、サブルーチン的にイベント実装を処理するため...
--スレッド跨ぎか否かで動作が大きく異なる。
---スレッド跨ぎでない場合、サブルーチン的にイベント実装を...
---スレッド跨ぎの場合、送信・応答メッセージキューを使用す...
--なお、処理の優先度は、PostMessageより高い。
以下は、SendMessageの同期呼出ハングの問題を回避するための...
-SendMessageTimeout 関数~
http://msdn.microsoft.com/ja-jp/library/cc411010.aspx
--SendMessage のタイムアウト機能付きバージョン。
--同一スレッドからの場合はタイムアウト地を無視する。
-SendMessageCallback 関数~
http://msdn.microsoft.com/ja-jp/library/cc411008.aspx
--SendMessage のCallback機能付き非同期版(即座に制御を返...
--オーバーラップウィンドウにメッセージをブロードキャスト...
-SendNotifyMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411012.aspx
--PostMessageに近いが、以下の点がPostMessageと異なる。
---PostMessageよりも優先度が高い(先にキューから取り出さ...
---スレッド跨ぎでない場合、SendMessage的に動作する。
以下は、SendMessageの同期呼出ハングの問題を回避するための...
-ReplyMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411016.aspx
--SendMessage送信側の応答メッセージキューに結果をポストし...
--スレッド跨ぎでない場合、何もしない(falseを返す)。
-InSendMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364787.aspx
--スレッド跨ぎでない場合、falseを返す。
--スレッド跨ぎの場合、trueを返す。
**メッセージ・ループで使用 [#y87a9a48]
***GetMessage [#q46270fc]
-MSG 構造体~
http://msdn.microsoft.com/ja-jp/library/vstudio/900ks98t....
>メッセージのデータを表します。
-GetMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364699.aspx
>Windowsメッセージキューからメッセージを MSG 構造体として...
-PeekMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410948.aspx
>GetMessage 関数とは異なり、~
メッセージキューにメッセージがなかった場合、~
メッセージがポストされるのを待たずに制御を返す。
-TranslateMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364841.aspx
>仮想キーメッセージを文字メッセージへ変換(ショートカット...
-DispatchMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410766.aspx
>GetMessage関数で取得したMSG 構造体をウィンドウ・プロシー...
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ...
TranslateMessage(&msg);
DispatchMessage(&msg);
}
-GetQueueStatus 関数~
http://msdn.microsoft.com/ja-jp/library/cc364726.aspx
>当該スレッドのWindowsメッセージキューの状態確認
*** [#t7db56f5]
-WaitForMultipleObjects
--
--
-WaitForMultipleObjectsEx
--
--
**ウィンドウプロシージャで使用 [#r203665c]
***WindowProc [#d3583459]
-WindowProc 関数
--http://msdn.microsoft.com/ja-jp/library/cc364868.aspx
--ウィンドウへ送信されたメッセージを処理する、アプリケー...
-DefWindowProc 関数
--http://msdn.microsoft.com/ja-jp/library/cc410753.aspx
--既定のウィンドウプロシージャを呼び出して、既定の処理を...
--この関数は、すべてのメッセージが処理されることを保証し...
-WM_DESTROY メッセージ
--ウィンドウプロシージャはその全てのメッセージに対応でき...
-PostQuitMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410954.aspx
--WM_NCLBUTTONDOWN メッセージなどを取得した場合に、~
WM_QUIT メッセージをメッセージキューにポストする。
--終了処理~
http://wisdom.sakura.ne.jp/system/winapi/win32/win11.html
***サブクラス化 [#he020548]
-IsWindowUnicode 関数~
http://msdn.microsoft.com/ja-jp/library/cc410878.aspx
>ウィンドウが Unicode のネイティブウィンドウであるかどう...
-SetWindowLongPtr 関数~
http://msdn.microsoft.com/ja-jp/library/cc411204.aspx
>WndProcのサブクラス化
-CallWindowProc 関数~
http://msdn.microsoft.com/ja-jp/library/cc410622.aspx
>元WndProcにメッセージを送信
-.etc
*ハードウェア入力モデル [#t3c890e8]
-用語
--SHIQ(system hardware input queue:システムハードウェア...
--RIT(raw input thread:生入力スレッド)/(SHIQを待機、...
--VIQ(virtual input queue:仮想入力キュー)/(THREADINFO...
-RITが接続するVIQのスレッドを識別する
--マウスポインタ:マウスカーソルの下のウィンドウのスレッド
--キーストローク:フォアグラウンド・ウィンドウのスレッド
--その他、Alt+Tabなどの特殊キー・シーケンスを処理する。
-スレッドローカル・入力状態管理変数(THREADINFO構造体内)
--キーボード入力、ウィンドウフォーカス情報
---フォーカス・ウィンドウ
---アクティブ・ウィンドウ
---押下されているキー
---キャレット(入力カーソル)の状態
--マウスカーソル管理情報
---形
---表示/非表示の状態
---キャプチャ
-マウスによる切り替え
--WM_KILLFOCUS
**関連するWin32API [#z42e3ae8]
***フォーカス [#b942a276]
-SetFocus 関数~
http://msdn.microsoft.com/ja-jp/library/cc411074.aspx
--WM_SETFOCUS
--VIQの切り替えはできない。
--通常、RITに接続されているときだけ呼び出す。
--スレッド1がRITに接続しているときに~
スレッド2が自身のウィンドにSetFocusを~
呼び出すと2つのフォーカス矩形が現れ問題。~
(RITに接続するVIQは切り替わらないので)
-GetFocus 関数~
http://msdn.microsoft.com/ja-jp/library/cc364641.aspx
>ローカル入力状態からフォーカスを持つウィンドウのHWNDを返...
***アクティブ化 [#y2b1c07d]
-SetActiveWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411014.aspx
--ウィンドウをアクティブにする。~
--RITに接続するVIQの切り替えはできない。
--通常、RITに接続されているときだけ呼び出す。
-GetActiveWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410861.aspx
>ローカル入力状態からアクティブなウィンドウのHWNDを返す。
***フォアグラウンド化 [#db2fc325]
-BringWindowToTop 関数~
http://msdn.microsoft.com/ja-jp/library/cc410618.aspx
>HWND_TOPを指定しSetWindowPosを呼び出す(RITに接続するVIQ...
-SetWindowPos 関数~
http://msdn.microsoft.com/ja-jp/library/cc411206.aspx
>ウィンドウをアクティブにしてサイズ、位置、Zオーダを変更...
-GetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc364732.aspx
>フォアグラウンド・ウィンドウのHWNDを返す。
-SetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411039.aspx
--ウィンドウをフォアグラウンドに移動する(RITに接続するVI...
--このAPIは、プログラマによって乱用されたため、~
MSはRITに接続されているか、RITに接続されている別スレッド...
入力を受け取っていない場合にのみ成功するように機能を追加...
--失敗の際は、タスクバーをフラッシュさせる。
-AllowSetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc430255.aspx
>指定したプロセスのスレッドがSetForgroundWindowを呼び出す...
-LockSetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410898.aspx
>他のSetForgroundWindow呼出をロックする(Windowsスタート...
***キー入力状態 [#x7b0f1a6]
-GetKeyState 関数~
http://msdn.microsoft.com/ja-jp/library/cc364676.aspx
--最後のキー入力を返す。
--入力フォーカスを持ったウィンドウを持ってる必要はない。
-GetAsyncKeyState 関数~
http://msdn.microsoft.com/ja-jp/library/cc364583.aspx
--キーが押されているか?前回の呼び出し以降にキーが押され...
--入力フォーカスを持ったウィンドウを持ていること。
***カーソル入力状態 [#p8d7129e]
-SetCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc411027.aspx
>マウス・カーソルのセット(砂時計など)
-ShowCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc364876.aspx
>マウス・カーソルの表示・非表示
-ClipCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc410663.aspx
>マウス・カーソルの範囲を指定する(非同期的なアクティブ化...
-SetCapture 関数~
http://msdn.microsoft.com/ja-jp/library/cc411051.aspx
--マウス・カーソルがウィンドウの範囲内にあるかどうか~
に関わり無く、すべてのマウス入力を受け取る。
--一度に 1 つのウィンドウだけがマウスをキャプチャできる。
--通常はマウスのボタン押下後に呼び出す。
-ReleaseCapture 関数~
http://msdn.microsoft.com/ja-jp/library/cc410990.aspx
>上記のマウスのキャプチャを停止する。
***VIQの共有 [#ifd6b3ff]
-AttachThreadInput 関数~
http://msdn.microsoft.com/ja-jp/library/cc429027.aspx
>複数のスレッドに複数のVIQとローカル入力状態を共有させる。
--ただし、THREADINFO構造体の、
---ポストメッセージ
---送信メッセージキュー
---応答メッセージキュー
---ウェイクフラグ
>については自分のものを使い続ける。
--このAPIはシステムの強度を損なう可能性がある。
--用途としてはジャーナルの記録・再生フックをインストール...
---RE#2347:アプリケーションの切替方法について~
http://www.gizcollabo.jp/vbtomo/log/archive/vbqanda_2302_...
>AttachThreadInput API関数で無理やり現在アクティブなスレ...
その間にBringWindowToTop API関数で自分のフォームを前面に...
その後もう一度AttachThreadInputAPI関数でデタッチして解除...
もちろん、Windowsの仕様に反しますが。
*DLL注入とAPIフック [#d5dfeb5c]
[[UIオートメーション]]の裏側。
-ちなみに、操作ログの取得って
--GetMessegeのフックと
--AttachThreadInputの
>2つの方法がありそうですが、~
現行はどっちを使用しているんでしょうか?
-答えは、GetMessegeのフックらしい。
>例えばAttachThreadInputでSetWindowLongPtrを使用して~
別プロセスのウィンドウをサブクラス化できるか?と言うとこ...
これは、呼び出し元のWndProcのアドレスが呼び出し先のプロセ...
>しかし、これを可能にする方法がある。~
「[[DLL注入>#qdb30fde]]」と「[[APIフック>#le7d156d]]」で...
**DLL注入 [#qdb30fde]
-AppInit_DLLs による DLL インジェクション~
http://keicode.com/windows/win08.php
>レジストリエントリを使用してDLLを注入する。~
ただし、問題としては汎用性がない点が挙げられる。~
DLLを注入してSetWindowLongPtrを実行する。
**APIフック [#le7d156d]
別プロセスのウィンドウにGetMsgProcフックプロシージャをイ...
GetMsgProcフックプロシージャは、前述のDLL注入のDLL中に実...
***SetWindowsHookEx 関数 [#f3186672]
http://msdn.microsoft.com/ja-jp/library/cc430103.aspx
-第一引数:インストール対象のフックタイプ
-第二引数:関数ポインタ(フックタイプにより可変)
-第三引数:上記関数を格納するDLLのモジュールハンドル
-第四引数:フックすべきスレッド
-ウィンドウのスレッドを取得するには、~
FindWindow→GetWindowThreadProcessId 関数を使用する。
--FindWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc364634.aspx
--GetWindowThreadProcessId 関数~
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx
***フックタイプと関数ポインタ [#p8555cb5]
-フックタイプにはWH_GETMESSAGEを指定する。
--メッセージキューへポストされた~
メッセージを監視する1個のフックプロシージャをインストー...
--フックは、メッセージ系を処理するものが多数である。~
その他、シェル、デバッガ、CBT用途のフックなどがある。
-関数ポインタには、GetMsgProcフックプロシージャを指定する...
詳細については、GetMsgProcフックプロシージャの説明を参照。
--GetMsgProcフックプロシージャ~
http://msdn.microsoft.com/ja-jp/library/cc429822.aspx~
---システムは、 または関数がアプリケーションのメッセージ...
---システムは、取得したメッセージを目的のウィンドウプロシ...
---GetMsgProcを実装したDLLは、呼出元プロセスと同じ位置に...
同じ位置でなければ、システムが自動的に呼出先プロセスの関...
---これにより、「呼出先プロセス」でSetWindowLongPtrを実行...
---(ただし本来の用途とは異なる。通常は、メッセージを処理...
--Windowsに土足で乱入?! ~ フック関数の使い方~
http://dsas.blog.klab.org/archives/50829204.html~
>・所定のプロセスに対する Windows メッセージの監視・捕捉~
・所定のプロセスでの特定のイベントに呼応する自作コードの...
・既存のアプリケーションの所作を変更 .etc~
--また、フックチェーンを実装することもできる。
---フックチェーンを実装(CallNextHookEx)~
http://msdn.microsoft.com/ja-jp/library/cc429591.aspx
*スパイ [#v1243eda]
Spy++やWinspector Spyを使用すると、ウィンドウのメッセージ...
-イベントの順番を確認する。
-欲しいイベントのメッセージが来ているか?調べる。
-当該イベントではどのようなメッセージが来るのか?調べる。
-SetCaptureにより別のマウスイベントが来てしまっていないか...
-SendMessage/PostMessageどちらで送られてきているか?確認...
-IMEの漢字入力で挙動不振の場合、イベントの順番、WM_CHAR W...
-当該ウィンドウの
--ウィンドウ名を確認する。
--ウィンドウクラス名を確認する。
--ウィンドウ位置、大きさを確認する。
--WndProc の値が変わっているかを確認する。
**Spy++ [#le2a0891]
-Spy++ ヘルプ~
http://msdn.microsoft.com/ja-jp/library/vstudio/dd460760....
**Winspector Spy [#r034c8c7]
-窓の杜 - 【NEWS】クラス名から~
各種ウィンドウ内のオブジェクトを検索できる「Winspector」...
http://www.forest.impress.co.jp/article/2004/05/18/winspe...
*別スレッド [#ed1408fa]
**別スレッドでウィンドウが起動する例 [#i6a6c87b]
-スレッドを明示的に起動して、そこからForm等、新規ウィンド...
-以下は、暗黙的に、別スレッドからウィンドウを起動する例。
-[[async/await]]を使用する。
-System.Timers.Timerを使用する。
--System.Timers.Timer は制度が高い反面、別スレッドで実行...
--[参考] C# の Timer 種類別 特徴 と 使い方~
https://garafu.blogspot.jp/2015/01/c-timer.html
**発生する問題の例 [#od2c91ab]
ここまで、色々と説明してきたように、スレッド関係で色々な...
***サーバーの同期呼出でUIがハングする。 [#tfaa56f4]
メッセージループを持つスレッドで同期呼出を行うと、~
同一のスレッド(メッセージループ)を共有する全てのスレッ...
そのため、サーバー呼出を別スレッドで処理を行うことがある...
以下の様な問題が発生するため、基本的に、[[UI処理はUIスレ...
***モーダル・ダイアログがモーダルにならない。 [#o4165f4d]
バックグラウンド・スレッドから上げたモーダル・ダイアログ...
これは、UIスレッドと別スレッドのメッセージループが異なる...
スレッド間のウィンドウはモーダル・ダイアログ的な動作にな...
***IME制御がおかしくなる。 [#p6d8f316]
-IMEはスレッド単位の初期化が必要になる。
-基本的には、[[UI処理は、UIスレッドから処理するようにする...
-止む無く、別スレッドから処理する場合。
--IMEを制御する方法~
http://www7a.biglobe.ne.jp/~tsuneoka/win32tech/7.html
--他のスレッドのFormを表示した後にSPREADのImeModeを切り替...
SPREAD for Windows Forms 5.0J - ナレッジベースの詳細 | G...
https://www.grapecity.com/tools/support/technical/knowled...
**UI処理をUIスレッドで処理する方法 [#l3b4d072]
非同期処理が必要になっても、UI処理はUIスレッドで処理する...
それには以下の技術を使用できる。
***[[Control.Invoke、.BeginInvoke>非同期処理#x24ad95f]] [...
***[[async/await>非同期処理#ae25c1af]] [#bb1866c2]
*参考 [#c6769d79]
**書籍 [#x5c74f4e]
-Amazon.co.jp: Advanced Windows 改訂第4版~
ジェフリー リッチャー, Jeffrey Richter, 長尾 高弘, ロング...
http://www.amazon.co.jp/Advanced-Windows-%E6%94%B9%E8%A8%...
--第6部:ウィンドウシステム
**msdn [#wf269b0d]
-C++ による Windows プログラミングの学習 (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff381399.aspx
--モジュール 1. 初めての Windows プログラム (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff381409.aspx
--Windows プログラミングの学習 サンプル コード (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff485845.aspx
-hilo Windows 7 対応 C++ アプリケーションの開発 (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff708696.aspx
**標準 Windows API [#ide08338]
-http://wisdom.sakura.ne.jp/system/winapi/win32/
--メッセージ~
http://wisdom.sakura.ne.jp/system/winapi/win32/win9.html
--ウィンドウプロシージャ~
http://wisdom.sakura.ne.jp/system/winapi/win32/win10.html
--終了処理~
http://wisdom.sakura.ne.jp/system/winapi/win32/win11.html
**Win32 API 階梯 [#c95b15b1]
-C による GUI アプリケーション開発~
http://www.wgag.net/winapi/index.html
--2. ウィンドウ
---1.ウィンドウの生成~
http://www.wgag.net/winapi/0008.html
---2.メッセージループ~
http://www.wgag.net/winapi/0009.html
---3.ウィンドウプロシージャ~
http://www.wgag.net/winapi/0010.html
---4.メッセージのふるい分け~
http://www.wgag.net/winapi/0011.html
---5.スケルトンプログラム~
http://www.wgag.net/winapi/0012.html
**Windowsプログラムの正しい雛形 [#z9e2b594]
-前編~
http://www.geocities.co.jp/SiliconValley-Bay/7437/cpp/cre...
-中編~
http://www.geocities.co.jp/SiliconValley-Bay/7437/cpp/cre...
**WindowsAPI Programming [#g5de7233]
-第1章 ~スケルトンプログラム~~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~その2~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~ その3~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~その4~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
**EternalWindows [#q79b9cca]
http://eternalwindows.jp/index.html
-コントロール基礎
http://eternalwindows.jp/control/controlbase/controlbase0...
--子ウインドウ~
http://eternalwindows.jp/control/controlbase/controlbase0...
--サブクラス化~
http://eternalwindows.jp/control/controlbase/controlbase0...
--新しいサブクラス化~
http://eternalwindows.jp/control/controlbase/controlbase0...
--オーナードロー~
http://eternalwindows.jp/control/controlbase/controlbase0...
--カスタムドロー~
http://eternalwindows.jp/control/controlbase/controlbase0...
----
Tags: [[:Windows]], [[:ウィンドウ・システム]], [[:プログ...
終了行:
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicros...
-[[戻る>Windows OSの基礎的トピック]]
* 目次 [#sb75d7ba]
#contents
*概要 [#od51b6e4]
ウィンドウ・システムの詳細を理解して、
>「バックグラウンド・スレッドから上げた~
モーダル・ダイアログがモーダルにならない理由」
などのさまざまな挙動を理解できるようにする。
*テンプレート [#s05a223e]
Windowsプログラムは、
-エントリポイント(プログラムの開始)である(1)WinMainと、
-Windowsから呼び出されて渡されたメッセージを処理する~
(2)ウインドウプロシ-ジャ(通常WinProcと書く)
から成り立つ。
そして(1)WinMainの中は、
-(A)ウインドウクラスの登録
-(B)ウィンドウの作成
-(C)ウインドウの表示
-(D)メッセージループ
の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メッセージキューとメッセージループ [#rf68c087]
**Windowsメッセージキュー [#z34491c0]
MSMQではなく、ウィンドウ メッセージ用のキュー。~
ウィンドウ・システム(WindowsのGUI)の根幹をなすメカニズ...
***作成方法 [#da9d8264]
-Windowsメッセージキューは、~
1つのスレッドが1つだけ保持できる。
--ウィンドウを作成したスレッドには、~
Windowsメッセージキューが与えられる。
--スレッドからメッセージ系のAPIを使用した場合も、~
Windowsメッセージキューが与えられる。
-この際、システムは、
--THREADINFO構造体を作成してスレッドに割り当てる。
--THREADINFO構造体はWindowsメッセージキューに関する情報を...
|>|THREADINFO構造体|h
|項目|APIとの関連|h
|ポストメッセージ|PostMessage()で送信されるメッセージ|
|送信メッセージキュー|SendMessage()で送信されるメッセージ...
|応答メッセージキュー|SendMessage()で送信されるメッセージ...
|仮想入力キュー(ハードウェア入力)|-|
|ウェイクフラグ|PostQuitMessage()|
|nExitCode|PostQuitMessage()|
|スレッドローカル・入力状態管理変数|-|
***作成単位 [#bff89f1a]
-Windowsメッセージキューは、複数のウィンドウ間で共有され...
--通常、1つのプロセスは、1つのUIスレッドで、複数(全て...
このため、通常、1プロセス、1UIスレッド、1Windowsメッセ...
--この理由は、1プロセスで、2つ以上のUIスレッドを持つ場...
画面間の通信をスレッドセーフに実装する必要があり実装し難...
***利用方法 [#j7fd3258]
後述のWin32APIを使用する。
-PostMessage()~
メッセージ・ループにキューイングする。
-SendMessage()~
ウィンドウ・プロシージャ(WndProc)を直接呼び出す。
***その他の利用方法 [#j7fd3258]
-プロセス間通信
-スレッド間通信
-COMのSTA(呼び出しの直列化)
などでも利用される。
**メッセージループ [#nca334b2]
GetMessage関数でWindowsメッセージキューから取り出したMSG ...
DispatchMessage関数でウィンドウ・プロシージャに渡す。
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ...
TranslateMessage(&msg);
DispatchMessage(&msg);
}
*ウィンドウ的なもの [#ibf9d3ef]
**ウィンドウクラス [#u8d37135]
.NETで言う、FormもControlも全てが~
ウィンドウ(hwnd:ウィンドウハンドルを持つ)。
-用語(7):ウィンドウクラスって?~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/winclass.html
>ウィンドウクラスとは、ウィンドウの雛形(テンプレート)の...
対応するウィンドウ関数・アイコン・カーソル・背景色など 基...
***Form的なもの [#qf9d4920]
自前のウィンドウクラス名を持つウィンドウクラス(.NETで言...
WndProcを用意して、WNDCLASS 構造体にまとめて、 RegisterCl...
その時に 自前のウィンドウクラス名 を登録し、CreateWindowE...
そのイベントは、すべて、 WNDCLASS で登録した WndProc へ来...
***Control的なもの [#hb30291b]
あらかじめ登録されている既定のウィンドウクラスとしては
-"BUTTON"
-"COMBOBOX"
-"EDIT"
-"LISTBOX"
-"MDICLIENT"
-"RichEdit"
-"RICHEDIT_CLASS"
-"SCROLLBAR"
-"STATIC"
がある(.NETで言う、Control的なもの)。
これらは登録済みで個別用途のウィンドウクラスであるため~
(例えばボタンウィンドウやエディットボックスなど)、~
下記のRegisterClassEx関数を使用せずに作成可能。
自前のウィンドウクラス(Form的な)の中へ、~
既定のウィンドウクラス(Control的な)を貼り付けたければ、~
自前で CreateWindowす(自前のウィンドウクラス の hwnd,...)...
**ダイアログ [#u0ed1ff6]
VC++のダイアログエディタで、ダイアログリソースを作ってCre...
ダイアログのイベントは、WndProcではなく、DlgProc へ来る(...
*ウィンドウプロシージャ [#ibfcede7]
イベントハンドラみたいなもの。
以下のように、イベントハンドラを実装する。
-Control的なウィンドウクラスの標準WndProcは、~
親ウィンドウクラスに対してSendMessageでWM_Commandを送るよ...
-Form的な親ウィンドウのカスタムWndProcに、~
WM_Commandを処理するカバレージをcase WM_COMMAND:等を使用...
-参考
--子ウインドウ~
http://eternalwindows.jp/control/controlbase/controlbase0...
**WndProc [#s2b8e69c]
//(2) ウィンドウプロシージャ
WndProc (
HWND hWnd,
UNIT message,
WPARAM wParam,
LPARAM lParam )
{
・・・
}
**DlgProc [#zb8aba2e]
???
**サブクラス化 [#n23e3ff2]
-GetWindowLong(hwnd, GWL_WNDPROC) を使って、今あるWndProc...
-SetWindowLong(hwnd, GWL_WNDPROC, 自前WndProc) で置き換え...
--元あったWndProcを呼ばなければ、そのイベントの処理を置き...
--自前WndProc の中で、 CallWndProc(取得したWndProc, pMsg)...
元のWndProcを呼ぶことで、WndProcのチェインに割って入る。
この既定のWndProcを置き換えることで、~
イベントの挙動(≠イベント・ハンドラ、ボタン押下時にボタン...
をカスタマイズすることが可能である。
*Win32PI [#m645932a]
**ウィンドウの生成 [#h0121534]
-WNDCLASS structure (Windows)~
http://msdn.microsoft.com/ja-jp/library/windows/desktop/m...
>ウィンドウクラスの属性を表します。
-RegisterClassEx 関数~
http://msdn.microsoft.com/ja-jp/library/cc410996.aspx
>ウィンドウクラスを登録します。
-CreateWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410713.aspx
>メモリ上にウィンドウを生成します。
-ShowWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411211.aspx
>ウィンドウを表示します。
-UpdateWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc428780.aspx
>ウィンドウを更新します。
-GetWindowThreadProcessId 関数~
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx
>指定されたウィンドウを作成したスレッドの ID を取得します。
**メッセージの送信 [#w1750e46]
***PostMessage [#p8157cb2]
PostMessageはメッセージ・ループにキューイングする。
-PostMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410952.aspx
--指定されたウィンドウのメッセージキューに 1 つのメッセー...
--対応するスレッドがメッセージを処理するのを待たずに制御...
-PostThreadMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410979.aspx
--指定されたスレッドのメッセージキューに 1 つのメッセージ...
--この関数は、スレッドがメッセージを処理するのを待たず、...
-PostQuitMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410954.aspx
>WM_NCLBUTTONDOWN メッセージなどを取得した場合に、~
WM_QUIT メッセージをメッセージキューにポストする。
***SendMessage [#v0311886]
SendMessageはウィンドウ・プロシージャ(WndProc)を直接呼...
-SendMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411022.aspx
--1 つまたは複数のウィンドウへ、指定されたメッセージを送...
--指定されたウィンドウのウィンドウプロシージャを呼び出し...
--ウィンドウプロシージャがメッセージを処理し終わった後で...
--基本的には、サブルーチン的にイベント実装を処理するため...
--スレッド跨ぎか否かで動作が大きく異なる。
---スレッド跨ぎでない場合、サブルーチン的にイベント実装を...
---スレッド跨ぎの場合、送信・応答メッセージキューを使用す...
--なお、処理の優先度は、PostMessageより高い。
以下は、SendMessageの同期呼出ハングの問題を回避するための...
-SendMessageTimeout 関数~
http://msdn.microsoft.com/ja-jp/library/cc411010.aspx
--SendMessage のタイムアウト機能付きバージョン。
--同一スレッドからの場合はタイムアウト地を無視する。
-SendMessageCallback 関数~
http://msdn.microsoft.com/ja-jp/library/cc411008.aspx
--SendMessage のCallback機能付き非同期版(即座に制御を返...
--オーバーラップウィンドウにメッセージをブロードキャスト...
-SendNotifyMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411012.aspx
--PostMessageに近いが、以下の点がPostMessageと異なる。
---PostMessageよりも優先度が高い(先にキューから取り出さ...
---スレッド跨ぎでない場合、SendMessage的に動作する。
以下は、SendMessageの同期呼出ハングの問題を回避するための...
-ReplyMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc411016.aspx
--SendMessage送信側の応答メッセージキューに結果をポストし...
--スレッド跨ぎでない場合、何もしない(falseを返す)。
-InSendMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364787.aspx
--スレッド跨ぎでない場合、falseを返す。
--スレッド跨ぎの場合、trueを返す。
**メッセージ・ループで使用 [#y87a9a48]
***GetMessage [#q46270fc]
-MSG 構造体~
http://msdn.microsoft.com/ja-jp/library/vstudio/900ks98t....
>メッセージのデータを表します。
-GetMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364699.aspx
>Windowsメッセージキューからメッセージを MSG 構造体として...
-PeekMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410948.aspx
>GetMessage 関数とは異なり、~
メッセージキューにメッセージがなかった場合、~
メッセージがポストされるのを待たずに制御を返す。
-TranslateMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc364841.aspx
>仮想キーメッセージを文字メッセージへ変換(ショートカット...
-DispatchMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410766.aspx
>GetMessage関数で取得したMSG 構造体をウィンドウ・プロシー...
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ...
TranslateMessage(&msg);
DispatchMessage(&msg);
}
-GetQueueStatus 関数~
http://msdn.microsoft.com/ja-jp/library/cc364726.aspx
>当該スレッドのWindowsメッセージキューの状態確認
*** [#t7db56f5]
-WaitForMultipleObjects
--
--
-WaitForMultipleObjectsEx
--
--
**ウィンドウプロシージャで使用 [#r203665c]
***WindowProc [#d3583459]
-WindowProc 関数
--http://msdn.microsoft.com/ja-jp/library/cc364868.aspx
--ウィンドウへ送信されたメッセージを処理する、アプリケー...
-DefWindowProc 関数
--http://msdn.microsoft.com/ja-jp/library/cc410753.aspx
--既定のウィンドウプロシージャを呼び出して、既定の処理を...
--この関数は、すべてのメッセージが処理されることを保証し...
-WM_DESTROY メッセージ
--ウィンドウプロシージャはその全てのメッセージに対応でき...
-PostQuitMessage 関数~
http://msdn.microsoft.com/ja-jp/library/cc410954.aspx
--WM_NCLBUTTONDOWN メッセージなどを取得した場合に、~
WM_QUIT メッセージをメッセージキューにポストする。
--終了処理~
http://wisdom.sakura.ne.jp/system/winapi/win32/win11.html
***サブクラス化 [#he020548]
-IsWindowUnicode 関数~
http://msdn.microsoft.com/ja-jp/library/cc410878.aspx
>ウィンドウが Unicode のネイティブウィンドウであるかどう...
-SetWindowLongPtr 関数~
http://msdn.microsoft.com/ja-jp/library/cc411204.aspx
>WndProcのサブクラス化
-CallWindowProc 関数~
http://msdn.microsoft.com/ja-jp/library/cc410622.aspx
>元WndProcにメッセージを送信
-.etc
*ハードウェア入力モデル [#t3c890e8]
-用語
--SHIQ(system hardware input queue:システムハードウェア...
--RIT(raw input thread:生入力スレッド)/(SHIQを待機、...
--VIQ(virtual input queue:仮想入力キュー)/(THREADINFO...
-RITが接続するVIQのスレッドを識別する
--マウスポインタ:マウスカーソルの下のウィンドウのスレッド
--キーストローク:フォアグラウンド・ウィンドウのスレッド
--その他、Alt+Tabなどの特殊キー・シーケンスを処理する。
-スレッドローカル・入力状態管理変数(THREADINFO構造体内)
--キーボード入力、ウィンドウフォーカス情報
---フォーカス・ウィンドウ
---アクティブ・ウィンドウ
---押下されているキー
---キャレット(入力カーソル)の状態
--マウスカーソル管理情報
---形
---表示/非表示の状態
---キャプチャ
-マウスによる切り替え
--WM_KILLFOCUS
**関連するWin32API [#z42e3ae8]
***フォーカス [#b942a276]
-SetFocus 関数~
http://msdn.microsoft.com/ja-jp/library/cc411074.aspx
--WM_SETFOCUS
--VIQの切り替えはできない。
--通常、RITに接続されているときだけ呼び出す。
--スレッド1がRITに接続しているときに~
スレッド2が自身のウィンドにSetFocusを~
呼び出すと2つのフォーカス矩形が現れ問題。~
(RITに接続するVIQは切り替わらないので)
-GetFocus 関数~
http://msdn.microsoft.com/ja-jp/library/cc364641.aspx
>ローカル入力状態からフォーカスを持つウィンドウのHWNDを返...
***アクティブ化 [#y2b1c07d]
-SetActiveWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411014.aspx
--ウィンドウをアクティブにする。~
--RITに接続するVIQの切り替えはできない。
--通常、RITに接続されているときだけ呼び出す。
-GetActiveWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410861.aspx
>ローカル入力状態からアクティブなウィンドウのHWNDを返す。
***フォアグラウンド化 [#db2fc325]
-BringWindowToTop 関数~
http://msdn.microsoft.com/ja-jp/library/cc410618.aspx
>HWND_TOPを指定しSetWindowPosを呼び出す(RITに接続するVIQ...
-SetWindowPos 関数~
http://msdn.microsoft.com/ja-jp/library/cc411206.aspx
>ウィンドウをアクティブにしてサイズ、位置、Zオーダを変更...
-GetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc364732.aspx
>フォアグラウンド・ウィンドウのHWNDを返す。
-SetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc411039.aspx
--ウィンドウをフォアグラウンドに移動する(RITに接続するVI...
--このAPIは、プログラマによって乱用されたため、~
MSはRITに接続されているか、RITに接続されている別スレッド...
入力を受け取っていない場合にのみ成功するように機能を追加...
--失敗の際は、タスクバーをフラッシュさせる。
-AllowSetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc430255.aspx
>指定したプロセスのスレッドがSetForgroundWindowを呼び出す...
-LockSetForgroundWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc410898.aspx
>他のSetForgroundWindow呼出をロックする(Windowsスタート...
***キー入力状態 [#x7b0f1a6]
-GetKeyState 関数~
http://msdn.microsoft.com/ja-jp/library/cc364676.aspx
--最後のキー入力を返す。
--入力フォーカスを持ったウィンドウを持ってる必要はない。
-GetAsyncKeyState 関数~
http://msdn.microsoft.com/ja-jp/library/cc364583.aspx
--キーが押されているか?前回の呼び出し以降にキーが押され...
--入力フォーカスを持ったウィンドウを持ていること。
***カーソル入力状態 [#p8d7129e]
-SetCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc411027.aspx
>マウス・カーソルのセット(砂時計など)
-ShowCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc364876.aspx
>マウス・カーソルの表示・非表示
-ClipCursor 関数~
http://msdn.microsoft.com/ja-jp/library/cc410663.aspx
>マウス・カーソルの範囲を指定する(非同期的なアクティブ化...
-SetCapture 関数~
http://msdn.microsoft.com/ja-jp/library/cc411051.aspx
--マウス・カーソルがウィンドウの範囲内にあるかどうか~
に関わり無く、すべてのマウス入力を受け取る。
--一度に 1 つのウィンドウだけがマウスをキャプチャできる。
--通常はマウスのボタン押下後に呼び出す。
-ReleaseCapture 関数~
http://msdn.microsoft.com/ja-jp/library/cc410990.aspx
>上記のマウスのキャプチャを停止する。
***VIQの共有 [#ifd6b3ff]
-AttachThreadInput 関数~
http://msdn.microsoft.com/ja-jp/library/cc429027.aspx
>複数のスレッドに複数のVIQとローカル入力状態を共有させる。
--ただし、THREADINFO構造体の、
---ポストメッセージ
---送信メッセージキュー
---応答メッセージキュー
---ウェイクフラグ
>については自分のものを使い続ける。
--このAPIはシステムの強度を損なう可能性がある。
--用途としてはジャーナルの記録・再生フックをインストール...
---RE#2347:アプリケーションの切替方法について~
http://www.gizcollabo.jp/vbtomo/log/archive/vbqanda_2302_...
>AttachThreadInput API関数で無理やり現在アクティブなスレ...
その間にBringWindowToTop API関数で自分のフォームを前面に...
その後もう一度AttachThreadInputAPI関数でデタッチして解除...
もちろん、Windowsの仕様に反しますが。
*DLL注入とAPIフック [#d5dfeb5c]
[[UIオートメーション]]の裏側。
-ちなみに、操作ログの取得って
--GetMessegeのフックと
--AttachThreadInputの
>2つの方法がありそうですが、~
現行はどっちを使用しているんでしょうか?
-答えは、GetMessegeのフックらしい。
>例えばAttachThreadInputでSetWindowLongPtrを使用して~
別プロセスのウィンドウをサブクラス化できるか?と言うとこ...
これは、呼び出し元のWndProcのアドレスが呼び出し先のプロセ...
>しかし、これを可能にする方法がある。~
「[[DLL注入>#qdb30fde]]」と「[[APIフック>#le7d156d]]」で...
**DLL注入 [#qdb30fde]
-AppInit_DLLs による DLL インジェクション~
http://keicode.com/windows/win08.php
>レジストリエントリを使用してDLLを注入する。~
ただし、問題としては汎用性がない点が挙げられる。~
DLLを注入してSetWindowLongPtrを実行する。
**APIフック [#le7d156d]
別プロセスのウィンドウにGetMsgProcフックプロシージャをイ...
GetMsgProcフックプロシージャは、前述のDLL注入のDLL中に実...
***SetWindowsHookEx 関数 [#f3186672]
http://msdn.microsoft.com/ja-jp/library/cc430103.aspx
-第一引数:インストール対象のフックタイプ
-第二引数:関数ポインタ(フックタイプにより可変)
-第三引数:上記関数を格納するDLLのモジュールハンドル
-第四引数:フックすべきスレッド
-ウィンドウのスレッドを取得するには、~
FindWindow→GetWindowThreadProcessId 関数を使用する。
--FindWindow 関数~
http://msdn.microsoft.com/ja-jp/library/cc364634.aspx
--GetWindowThreadProcessId 関数~
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx
***フックタイプと関数ポインタ [#p8555cb5]
-フックタイプにはWH_GETMESSAGEを指定する。
--メッセージキューへポストされた~
メッセージを監視する1個のフックプロシージャをインストー...
--フックは、メッセージ系を処理するものが多数である。~
その他、シェル、デバッガ、CBT用途のフックなどがある。
-関数ポインタには、GetMsgProcフックプロシージャを指定する...
詳細については、GetMsgProcフックプロシージャの説明を参照。
--GetMsgProcフックプロシージャ~
http://msdn.microsoft.com/ja-jp/library/cc429822.aspx~
---システムは、 または関数がアプリケーションのメッセージ...
---システムは、取得したメッセージを目的のウィンドウプロシ...
---GetMsgProcを実装したDLLは、呼出元プロセスと同じ位置に...
同じ位置でなければ、システムが自動的に呼出先プロセスの関...
---これにより、「呼出先プロセス」でSetWindowLongPtrを実行...
---(ただし本来の用途とは異なる。通常は、メッセージを処理...
--Windowsに土足で乱入?! ~ フック関数の使い方~
http://dsas.blog.klab.org/archives/50829204.html~
>・所定のプロセスに対する Windows メッセージの監視・捕捉~
・所定のプロセスでの特定のイベントに呼応する自作コードの...
・既存のアプリケーションの所作を変更 .etc~
--また、フックチェーンを実装することもできる。
---フックチェーンを実装(CallNextHookEx)~
http://msdn.microsoft.com/ja-jp/library/cc429591.aspx
*スパイ [#v1243eda]
Spy++やWinspector Spyを使用すると、ウィンドウのメッセージ...
-イベントの順番を確認する。
-欲しいイベントのメッセージが来ているか?調べる。
-当該イベントではどのようなメッセージが来るのか?調べる。
-SetCaptureにより別のマウスイベントが来てしまっていないか...
-SendMessage/PostMessageどちらで送られてきているか?確認...
-IMEの漢字入力で挙動不振の場合、イベントの順番、WM_CHAR W...
-当該ウィンドウの
--ウィンドウ名を確認する。
--ウィンドウクラス名を確認する。
--ウィンドウ位置、大きさを確認する。
--WndProc の値が変わっているかを確認する。
**Spy++ [#le2a0891]
-Spy++ ヘルプ~
http://msdn.microsoft.com/ja-jp/library/vstudio/dd460760....
**Winspector Spy [#r034c8c7]
-窓の杜 - 【NEWS】クラス名から~
各種ウィンドウ内のオブジェクトを検索できる「Winspector」...
http://www.forest.impress.co.jp/article/2004/05/18/winspe...
*別スレッド [#ed1408fa]
**別スレッドでウィンドウが起動する例 [#i6a6c87b]
-スレッドを明示的に起動して、そこからForm等、新規ウィンド...
-以下は、暗黙的に、別スレッドからウィンドウを起動する例。
-[[async/await]]を使用する。
-System.Timers.Timerを使用する。
--System.Timers.Timer は制度が高い反面、別スレッドで実行...
--[参考] C# の Timer 種類別 特徴 と 使い方~
https://garafu.blogspot.jp/2015/01/c-timer.html
**発生する問題の例 [#od2c91ab]
ここまで、色々と説明してきたように、スレッド関係で色々な...
***サーバーの同期呼出でUIがハングする。 [#tfaa56f4]
メッセージループを持つスレッドで同期呼出を行うと、~
同一のスレッド(メッセージループ)を共有する全てのスレッ...
そのため、サーバー呼出を別スレッドで処理を行うことがある...
以下の様な問題が発生するため、基本的に、[[UI処理はUIスレ...
***モーダル・ダイアログがモーダルにならない。 [#o4165f4d]
バックグラウンド・スレッドから上げたモーダル・ダイアログ...
これは、UIスレッドと別スレッドのメッセージループが異なる...
スレッド間のウィンドウはモーダル・ダイアログ的な動作にな...
***IME制御がおかしくなる。 [#p6d8f316]
-IMEはスレッド単位の初期化が必要になる。
-基本的には、[[UI処理は、UIスレッドから処理するようにする...
-止む無く、別スレッドから処理する場合。
--IMEを制御する方法~
http://www7a.biglobe.ne.jp/~tsuneoka/win32tech/7.html
--他のスレッドのFormを表示した後にSPREADのImeModeを切り替...
SPREAD for Windows Forms 5.0J - ナレッジベースの詳細 | G...
https://www.grapecity.com/tools/support/technical/knowled...
**UI処理をUIスレッドで処理する方法 [#l3b4d072]
非同期処理が必要になっても、UI処理はUIスレッドで処理する...
それには以下の技術を使用できる。
***[[Control.Invoke、.BeginInvoke>非同期処理#x24ad95f]] [...
***[[async/await>非同期処理#ae25c1af]] [#bb1866c2]
*参考 [#c6769d79]
**書籍 [#x5c74f4e]
-Amazon.co.jp: Advanced Windows 改訂第4版~
ジェフリー リッチャー, Jeffrey Richter, 長尾 高弘, ロング...
http://www.amazon.co.jp/Advanced-Windows-%E6%94%B9%E8%A8%...
--第6部:ウィンドウシステム
**msdn [#wf269b0d]
-C++ による Windows プログラミングの学習 (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff381399.aspx
--モジュール 1. 初めての Windows プログラム (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff381409.aspx
--Windows プログラミングの学習 サンプル コード (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff485845.aspx
-hilo Windows 7 対応 C++ アプリケーションの開発 (Windows)~
http://msdn.microsoft.com/ja-jp/library/ff708696.aspx
**標準 Windows API [#ide08338]
-http://wisdom.sakura.ne.jp/system/winapi/win32/
--メッセージ~
http://wisdom.sakura.ne.jp/system/winapi/win32/win9.html
--ウィンドウプロシージャ~
http://wisdom.sakura.ne.jp/system/winapi/win32/win10.html
--終了処理~
http://wisdom.sakura.ne.jp/system/winapi/win32/win11.html
**Win32 API 階梯 [#c95b15b1]
-C による GUI アプリケーション開発~
http://www.wgag.net/winapi/index.html
--2. ウィンドウ
---1.ウィンドウの生成~
http://www.wgag.net/winapi/0008.html
---2.メッセージループ~
http://www.wgag.net/winapi/0009.html
---3.ウィンドウプロシージャ~
http://www.wgag.net/winapi/0010.html
---4.メッセージのふるい分け~
http://www.wgag.net/winapi/0011.html
---5.スケルトンプログラム~
http://www.wgag.net/winapi/0012.html
**Windowsプログラムの正しい雛形 [#z9e2b594]
-前編~
http://www.geocities.co.jp/SiliconValley-Bay/7437/cpp/cre...
-中編~
http://www.geocities.co.jp/SiliconValley-Bay/7437/cpp/cre...
**WindowsAPI Programming [#g5de7233]
-第1章 ~スケルトンプログラム~~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~その2~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~ その3~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
-第1章 ~スケルトンプログラム~その4~
http://yonex1.cis.ibaraki.ac.jp/~yonekura/lecture01/lectu...
**EternalWindows [#q79b9cca]
http://eternalwindows.jp/index.html
-コントロール基礎
http://eternalwindows.jp/control/controlbase/controlbase0...
--子ウインドウ~
http://eternalwindows.jp/control/controlbase/controlbase0...
--サブクラス化~
http://eternalwindows.jp/control/controlbase/controlbase0...
--新しいサブクラス化~
http://eternalwindows.jp/control/controlbase/controlbase0...
--オーナードロー~
http://eternalwindows.jp/control/controlbase/controlbase0...
--カスタムドロー~
http://eternalwindows.jp/control/controlbase/controlbase0...
----
Tags: [[:Windows]], [[:ウィンドウ・システム]], [[:プログ...
ページ名: