ちょっと先の未来クイズ第4問

VC++ 2005 MFC ボタンの無効化
現在スレッドを使ったプログラムを作成しています。
あるボタンを押すと、

親スレッド
1、RS232C受信スレッドを作成
2、RS232Cにデータを送信
3、WaitSingleObjectでイベント待ち
4、受信状態に応じた処理

子スレッド
1、サムチェック等確認して、受信が完了すれば
  受信データを格納してCEventのSetEventを発行

というような処理の部分があるのですが、待っている間にウィンドウ内にある
ボタンが押せてしまいます。厳密には、イベント待ちを抜けた時点で待っている
間に押せてしまったボタンの処理が走ってしまうのですが。
EnableWindow(FALSE)をやっても駄目でした。
何かいい方法がありませんか??すいませんがよろしくお願いします。

A 回答 (3件)

>ちなみにワーカスレッドでイベントを待ってイベント受信でEnableWindow


>っていう形になるのでしょうか??
>どこで何をしてっていうのが、すいません想像付いていません。

ボタンのイベントハンドラに入ったら…
・EnableWindow(FALSE)として、ボタンを無効化します。
・ワーカースレッドを起動します。
 (ワーカースレッドにはボタンのHWNDを引き渡すようにします)
 スレッド起動時に引き渡せるのはLPVIODが1つだけですが、
 構造体のアドレスを渡すこともできますので、必要なデータを詰めた構造体のアドレスでも渡して下さい。
 # その構造体の寿命には注意。イベントハンドラ内のローカル変数だと危険です。
 # 動的確保して渡してワーカースレッド中で解放する等の工夫を。
・ワーカースレッドの起動が完了したらイベントハンドラは終了します。

ワーカースレッドは…元質問の「親スレッド」の内容を内包します。
終了してスレッドを終了する際に、EnableWindow(TRUE)でボタンを有効化します。

子スレッドはそのままでよいでしょう。


注意点としては…ワーカースレッドが終了する前にウィンドウを閉じられた場合の対策が必要。
BeginThread()ではCランタイムライブラリの使用が危険になる。
MFCの場合CWndなどはスレッドMatthewで受け渡しはできない(はず)。
などなど……。


まぁ、検索してみると、UIスレッドとワーカースレッドで切り離ししているサンプルとか見つかる…
でしょう。たぶん。
# よくあるネタですし。
    • good
    • 0

親スレッドの1~4までの処理が「イベントハンドラ内で」実行しているのであれば、


当然の動作です。
# イベントハンドラからの戻りが遅ければ、OSによって「応答なし」のラベルを付与して貰えるでしょう。

ボタンクリックが発生
->WM_COMMANDでイベント通知
->EnableWindow(FALSE)で、ボタンを無効化
->ループ処理などでイベント処理(この間もマウスボタン押下できますが、ソレはキューに溜められる(*1))
->EnableWindow(TRUE)で、ボタンを有効化
->キューに溜まってる処理を続行
->*1でのマウスボタン押下のメッセージから、ボタン押下を検出、WM_COMMANDがキューに入る(EnableWindow(TRUE)で有効化されているから)
->WM_COMMANDでまたまた通知

ボタン押下でループ処理を実行するワーカースレッドを起こして、そのスレッド側でEnableWindow()を使ってボタンの有効/無効をコントロールした方が良いでしょう。

なお、ワーカースレッド実行中にウィンドウが閉じられてしまう。という可能性もありますのでご注意を。

この回答への補足

返事が遅くなって申し訳ありません。
確かにそういった動きをしています。
EnableWindowではなくフラグでも同様の動きをしてしまいます。
ちなみにワーカスレッドでイベントを待ってイベント受信でEnableWindow
っていう形になるのでしょうか??
どこで何をしてっていうのが、すいません想像付いていません。

補足日時:2010/06/08 17:54
    • good
    • 0

ボタンクリックイベントハンドラに有効判定処理をいれて、その処理が開始したら、その処理が終了するまでクリックイベントを無視する方法はどうですか?



こんな感じです。

void CTestDialog::OnBtn1()
{
if(btn1.IsWindowEnabled())
{
btn1.EnableWindow(FALSE);

// ボタンクリック時処理

btn1.EnableWindow(TRUE);
}
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報