回答編集履歴

1

他の回答に対する追加情報など追記

2017/05/31 05:48

投稿

hmmm
hmmm

スコア818

test CHANGED
@@ -61,3 +61,79 @@
61
61
  }
62
62
 
63
63
  ```
64
+
65
+
66
+
67
+ ---
68
+
69
+ いろいろ誤解があるような追加で記載しておきます。
70
+
71
+
72
+
73
+ MFCのDoModalのソースはVS2017であれば以下の場所にあります。
74
+
75
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.10.25017\atlmfc\src\mfc\dlgcore.cpp
76
+
77
+ DoModalの処理を最大限端折ってコピペすると以下のようになっています。
78
+
79
+
80
+
81
+ ``` c++
82
+
83
+ INT_PTR CDialog::DoModal()
84
+
85
+ {
86
+
87
+ //略
88
+
89
+
90
+
91
+ // disable parent (before creating dialog)
92
+
93
+ HWND hWndParent = PreModal();
94
+
95
+ ::EnableWindow(hWndParent, FALSE);
96
+
97
+
98
+
99
+ //略
100
+
101
+ CreateRunDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), AfxGetInstanceHandle());
102
+
103
+ //略
104
+
105
+
106
+
107
+ return m_nModalResult;
108
+
109
+ }
110
+
111
+ ```
112
+
113
+ CreateRunDlgIndirectがWindowを作成する処理です。今回のフリーズはその前のEnableWindowで固まっています。(バージョンによって違うかもしれませんが。)
114
+
115
+ CreateRunDlgIndirectはCreateDialogIndirectを呼び出してWindowを作成したのち、CWnd::RunModalLoopでメッセージループを回します。
116
+
117
+ CreateDialogIndirectは内部でCreateWindowExを呼んでいるとあります[(The CreateDialogIndirectParam function uses the CreateWindowEx function to create the dialog box)](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645441(v=vs.85).aspx)
118
+
119
+ ですので、DoModalがメインスレッド上でWindowを作っているとかではありません。
120
+
121
+
122
+
123
+ 他の方が指摘している「普通はメッセージループは一つにする」というのはあくまで、グローバル変数とかを使っていてActiveXとかサードパーティーのUIコントロールがマルチスレッド未対応だったりとかで、いろいろ問題があるのでUIフレームワークが1スレッドで操作されるのを前提としているのが「普通」というだけです。
124
+
125
+ EXPLORERをspyxx.exeで確認すると複数スレッドでメッセージループを回しているのが分かると思います。
126
+
127
+
128
+
129
+ ですので、MFCでは難しいかもしれないですが、固まっているUIスレッドに手を出さないように、マルチスレッドを注意しつつ進捗状況をメモリから直接取得し、Windowを作成して描画してあげればやりたいことが実現できると思います。
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+