二重起動を防止する方法について質問があります。
以下のソースでメニューからボタン3でnotepadが起動され
ボタン3は見ため上、押せないんですが、
この状態でボタン3を押すと、notepadが終了後に、
再度notepadが起動されます。
ボタンが押せない状態で押しても起動できないようにする方法を
誰か教えてください。よろしくお願いします。
void CMENUDlg::OnButton3()
{
char exe[] = "C:\\WINNT\\NOTEPAD.EXE";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
ZeroMemory( &pi, sizeof(pi) );
si.cb = sizeof(si);
m_Button3.EnableWindow( 0 ); //非表示
if( !CreateProcess(NULL, exe, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) {
MessageBox("起動失敗","error",MB_OK);
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
m_Button3.EnableWindow( 1 ); //表示
}
>ボタン3は見ため上、押せないんですが、
>この状態でボタン3を押すと、
押せないのに押せるとはどういうことでしょうか?
クリックのメッセージが溜まってしまっているということですか?
良い方法か分かりませんが
>m_Button3.EnableWindow( 1 ); //表示
の後でPeekMessageを使ってキューに溜まったメッセージを
クリアしてしまうとか。
>>ボタン3は見ため上、押せないんですが、
>>この状態でボタン3を押すと、
>押せないのに押せるとはどういうことでしょうか?
すみません。試したら再現しました。
(Win2000SP4, VC6SP6)
とおりさんの仰るとおり、メッセージが溜まってしまっているようです。
とりあえずは、
m_Button3.EnableWindow( 0 );
ではなく、
EnableWindow(FALSE);
でウィンドウ自体をディセーブルにすると良いようです。
ただこれだと、notepad が終了するまで呼び出し側が固まった状態で
(再描画等がされない)かっこ悪いので、私なら以下のようにします。
(動作確認はしていません。)
EnableWindow(FALSE) で呼び出し側アプリのウィンドウをディセーブルにする。
プロセス起動用スレッドを起動する。OnButton3 はスレッド起動後、すぐに処理を返す。
スレッド内でプロセスを起動し、WaitForSingleObject で待機する。
WaitForSingleObject から戻ったら、呼び出し側アプリのウィンドウをEnableWindow(TRUE) でイネーブルにする。
isshiさん、方法を教えていただきありがとうございます。
で、試してみたのですが、
スレッドを起動、プロセスを起動、
WaitForSingleObjectで待機、解放の一連の動作を
サンプルで教えていただきますでしょうか?
文章で書いたとおりそのままですが。
UINT ThreadProc( LPVOID pParam )
{
HWND hwnd = (HWND)pParam;
char exe[] = "C:\\WINNT\\NOTEPAD.EXE";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
ZeroMemory( &pi, sizeof(pi) );
si.cb = sizeof(si);
if( !CreateProcess(NULL, exe, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) {
MessageBox(hwnd, "起動失敗", "error", MB_OK);
}
else {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
EnableWindow(hwnd, TRUE);
return 0;
}
void CMENUDlg::OnButton3()
{
EnableWindow(FALSE);
AfxBeginThread(ThreadProc, (LPVOID)m_hWnd);
}
(WinXP Home SP1, VC7.1, MFC, ダイアログベースで動作確認済み)
isshiさん、サンプルを教えていただきありがとうございました。
たびたびでもうしわけありませんが、
コンパイル時に
error C2665: 'AfxBeginThread' : 2 のオーバーロードは 1 番目の引数を 'unsigned int (void)' から要求の型に変換できません。
と出力されてしまいます。
何か不備な部分があるのでしょうか?
(環境はWin2000,VC6.0です)
isshiさん
どうもすみませんでした。
こちらの記述ミスでした。
思った通りの動きができました。
いろいろとありがとうございました。
ツイート | ![]() |