トップ回答者
backgroundworkerのRunWorkerCompletedで表示したモーダルウィンドウが移動不可となる場合がある

質問
-
form上のスタートボタンを押すとbackgroundworkerが動き、その完了を待ってメッセージボックスを表示するという単純なプログラムを作成しています。
以下の操作をすると、完了時に表示したメッセージボックスが移動できなくなる(ウィンドウタイトルをつかんで移動)問題があり、対応できずに悩んでいます。
XP,Windows7で動作確認しました。
①formからスタートボタンクリック
②backgroundworker動作中に、formのウィンドウタイトルをマウスでつかみっぱなしにする
③backgroundworker完了時にメッセージボックスが表示される。このとき表示されたウィンドウをマウスで
移動しようとしても移動できない。
以下、formのソースです。解決策があるのでしょうか?
#pragma once namespace backgroundAndMsgBox { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // } protected: /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> ~Form1() { if (components) { delete components; } } private: System::ComponentModel::BackgroundWorker^ backgroundWorker1; protected: private: System::Windows::Forms::Button^ button1; private: /// <summary> /// 必要なデザイナ変数です。 /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// デザイナ サポートに必要なメソッドです。このメソッドの内容を /// コード エディタで変更しないでください。 /// </summary> void InitializeComponent(void) { this->backgroundWorker1 = (gcnew System::ComponentModel::BackgroundWorker()); this->button1 = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // backgroundWorker1 // this->backgroundWorker1->DoWork += gcnew System::ComponentModel::DoWorkEventHandler(this, &Form1::backgroundWorker1_DoWork); this->backgroundWorker1->RunWorkerCompleted += gcnew System::ComponentModel::RunWorkerCompletedEventHandler(this, &Form1::backgroundWorker1_RunWorkerCompleted); // // button1 // this->button1->Location = System::Drawing::Point(106, 88); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(75, 23); this->button1->TabIndex = 0; this->button1->Text = L"START"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 266); this->Controls->Add(this->button1); this->Name = L"Form1"; this->Text = L"Form1"; this->ResumeLayout(false); } #pragma endregion private: System::Void backgroundWorker1_RunWorkerCompleted(System::Object^ sender, System::ComponentModel::RunWorkerCompletedEventArgs^ e) { button1->Enabled = true; MessageBox::Show("completed"); } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { button1->Enabled = false; backgroundWorker1->RunWorkerAsync(); } private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) { Threading::Thread::Sleep(3000); } }; }
回答
-
MFC のアプリでも再現できますし、.NET Framework 固有の問題ではないでしょう。
回避策があるかどうかの深掘りはしていませんが、たぶん難しいか、とっても変なことをしないといけなくなるかも?私がその問題を突きつけられた場合、「MFC でも再現可能なので Windows の仕様、あるいは制限と思われる」、「フォーム移動中という状況下に限定され、それによる被害も軽微なので調査工数がもったいない」、「ほかの不具合をなおす、あるいは要望に対応する方が効果が高い」といったところで対応不要の判断に持ち込みたいところです。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
- 回答としてマーク ym_dan 2012年3月3日 11:29
すべての返信
-
MFC のアプリでも再現できますし、.NET Framework 固有の問題ではないでしょう。
回避策があるかどうかの深掘りはしていませんが、たぶん難しいか、とっても変なことをしないといけなくなるかも?私がその問題を突きつけられた場合、「MFC でも再現可能なので Windows の仕様、あるいは制限と思われる」、「フォーム移動中という状況下に限定され、それによる被害も軽微なので調査工数がもったいない」、「ほかの不具合をなおす、あるいは要望に対応する方が効果が高い」といったところで対応不要の判断に持ち込みたいところです。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
- 回答としてマーク ym_dan 2012年3月3日 11:29
-
Win32APIで
case WM_COMMAND:
if(LOWORD(wParam) == CM_TEST)
SetTimer(hWnd, IDT_TIMER, 2000, 0);
break;
case WM_TIMER:
if(wParam == IDT_TIMER)
MessagBox(hWnd, "test", "test", MB_OK);
break;
これでタイトルバー上で左ボタンを押していると、MessageBoxは移動できなくなります。
原因は、左ボタンを押していると、WM_SYSCOMMANDの中のメッセージループから
WM_TIMER,MessageBoxが呼ばれることにあるようです。
MessageBoxを閉じたときにWM_SYSCOMMANDの終了します。
MessageBoxを移動しようとして2度目のWM_SYSCOMMANDを呼ぶと
こっちはマウスを少し移動しただけで終了してしまいます。
というわけで、最初のWM_SYSCOMMANDを終了する必要がありますが、やり方がまったくわかりませんです。
- 編集済み snao 2012年3月4日 3:58
-