Windowsの「コピー中」ダイアログのように、
ダイアログでの処理中に「キャンセル」を受け付けたいのですが、
キャンセルボタンが触れなくなってしまい、うまく動きません。
良い方法は無いでしょうか?
実現したい処理の内容は下記です。
1)ダイアログ出現
2)OKを押したら、繰り返し処理開始(ダイアログは閉じない)
3)途中でキャンセルを押したら処理内容を破棄してダイアログを閉じる
ソースは以下のようになっています。
void CTestDlg::OnOK()
{
PostMessage(START, ...);
// CDialog::OnOK(); /* ダイアログ閉じない */
}
void CTestDlg::OnCancel()
{
PostMessage(CANCELED, ...);
CDialog::OnCancel();
}
LRESULT CTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch(msg){
case START:
/* ここで初期化処理を行う */
PostMessage(CONTINUE, ...);
break;
case CONTINUE:
Shori1(); /* キャンセルが押されるまでこの処理を繰り返したい */
PostMessage(CONTINUE, ...);
break;
case CANCELED:
/* ここで終了処理を行う */
break;
}
return;
}
よろしくお願いいたします。
WindowProcには飛び込みますか?
Shori1()には飛び込みますか?
Shori1()での処理は十分に短い時間で完了しますか?
はい。
「CONTINUE」の処理が継続される状態です。
追記いたします。
>WindowProcには飛び込みますか?
>Shori1()には飛び込みますか?
はい。
WindowProc()にもShori1()にも飛び込みます。
>Shori1()での処理は十分に短い時間で完了しますか?
Shori1()は1回で約1秒程度かかる処理です。
現在は未実装のため、forループなどで仮処理を入れてあります。
実際に動作が始まると、処理は動いているのですが
画面に触っても「キャンセル」他に触れず、アクションが起きません。
> 実際に動作が始まると、処理は動いているのですが
> 画面に触っても「キャンセル」他に触れず、アクションが起きません。
「触れない」とは? grayになるってことですか? クリックに反応しないってことですか?
あれ? START/CONTINUE/CANCELED以外のメッセージはどうやって処理してるんでしょ?
CDialog::WindowProc()を呼んであげないかんのとちゃいますか?
たびたび記述不足で申し訳ありません。
>「触れない」とは? grayになるってことですか? クリックに反応しないってことです
か?
「クリックに反応しない」ということです。
全体が何も反応しなくなるため、
キャンセルボタンが凹んだりもしません。
grayにはなっていません。
>CDialog::WindowProc()を呼んであげないかんのとちゃいますか?
すみません、記述漏れです。
return CDialog::WindowProc(message, wParam, lParam);
は呼んであります。
(初期生成状態のままです。)
普通にShori1()よんだら、
スレッドでないから終るまでそこの状態になるのでは?
case CONTINUE:
Shori1(); /* キャンセルが押されるまでこの処理を繰り返したい */
// Shori1()から戻ってこないと次に進まないよ普通は
PostMessage(CONTINUE, ...);
break;
>普通にShori1()よんだら、
>スレッドでないから終るまでそこの状態になるのでは?
>
> case CONTINUE:
> Shori1(); /* キャンセルが押されるまでこの処理を繰り返したい */
>// Shori1()から戻ってこないと次に進まないよ普通は
> PostMessage(CONTINUE, ...);
> break;
本来であれば下記のような処理でよいのですが、
for(cnt = 0; cnt < 1000; cnt++){
shori1();
}
時間がかかるため、途中キャンセルも可能にしたいのです。
(Shori1()の途中で中断する必要はありません。)
> case CONTINUE:
> Shori1(); /* キャンセルが押されるまでこの処理を繰り返したい */
> PostMessage(CONTINUE, ...);
これだと、メッセージキューが絶対に空にならないので、
まずいような気がします。
タイマーを使った方がよいのでは。
>タイマーを使った方がよいのでは。
タイマーというものを使ったことがないのですが、
タイマーで指定時間経過毎にPostMessage(CONTINUE, ...)を
呼ぶようにするというイメージなのでしょうか?
SetTimerと言う関数を調べてください。
あと、WM_TIMERというウインドウメッセージも。
WM_TIMERの処理の中でShori1を呼んだ方がすっきりしそうです。
STARTでSetTimerしてその後は、WM_TIMERの方で処理が進みます。
CANCELEDでKillTimerすれば、処理の中断が出来ます。
Shori1の返却値か何かで処理が終了できるようにしておいて
処理そのものが終わった時もKillTimerと言う流れで良いと思います。
詳しい部分はご自分で考えてください。
長い処理をワーカースレッドで処理させて、メインスレッド側でGUIの制御を
行うようにし、キャンセルのオペレーションでワーカースレッドに中断を
通知すると言う手もあります。
今後、Windowsのプログラミングを続けていくのであれば、スレッドについても
勉強してみた方が良いと思います。
タイマーを使用してみました。
なんとかうまく行きそうです!
επιστημηさん、
Blueさん、
dairygoodsさん、
PATIOさん、
どうもありがとうございました!