
<プログラム環境>
Windows XP
VC++6.0
MFC AppWizard(exe)
ダイアログベース
<目的>
1.ダイアログにボタン1を配置する
2.処理A(無限ループ)を開始する
3.処理Aの先頭でボタン1が押されたか判断する
4.ボタン1が押された場合処理Aを終了し、処理Bを行う
というプログラムを作成する。
<質問>
目的のプログラムを作成するには、ボタン1が押された事を検知する
必要があると思うのですが、その方法が分かりません。
ボタンが押された事を検知するにはどうしたら良いのでしょうか?
宜しければご指摘お願い致します。
No.5
- 回答日時:
> ボタン2を押して無限ループを実行している最中にダイアログの
> ボタン1を押すと、砂時計のアイコンが出て、フリーズしました。
当然でしょう
ループで待っている部分にメッセージポンプが無いからです
WaitForSingleObjectの返り値が時間切れの場合に
MSG msg;
while( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) {
AfxGetApp()->PumpMessage();
}
といった具合でメッセージポンプを組みましょう
MFCアプリで CreateThradなど使うのは避けたほうがいいようです
MFCでマルチスレッドをしたいなら CWinThreadクラスを使いましょう
この回答への補足
redfox63様、有難うございます。
ご指摘頂いた通りに、コーディングしたのですが、
症状に変化はありませんでした・・。
データをPCに送信する機器の故障が無い限り、
データは延々と連続して送られてくるので、
WaitForSingleObjectの戻り値はWAIT_OBJECT_0になります。
もしくは、ReadFileの戻り値が0以外となって、受信成功です。
(この場合はWaitForSingleObjectは実行されない)
WaitForSingleObjectの戻り値が時間切れになる事は、まず無いので、
MSG msg;
while( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) {
AfxGetApp()->PumpMessage();
}
という処理には入らないと思います。
シングルスレッドでは不可能なのでしょうか?
宜しければ、ご指摘お願い致します。
No.4
- 回答日時:
うーん、申し訳ありません。
チョッと判りませんが、こんな感じ?//グローバルハンドル
static HANDLE g_hEvent = 0;
//スレッド関数
DWORD WINAPI ThreadProcA(void* p)
{
HANDLE hCom;//COMポートのハンドル
unsigned char Buf[4];//受信バッファ
DWORD dwOldTime = ::timeGetTime();
for( ; ; )
{
//一秒経過
if(::timeGetTime() - dwOldTime > 1000)
{
dwOldTime = 0;
return;
}
if(::ReadFile(hCom,Buf,1,NULL,&old) == 0)
{
return;
}
}
}
void ボタン1関数()
{
//スレッドは既に停止していた
if(g_hEvent == 0)return;
//スレッドの停止
::CloseHandle(g_hEvent);
g_hEvent = 0;
//B処理
}
void 起点()
{
DWORD dw;
g_hEvent = ::CreateThread(NULL, 0, &::ThreadProcA, NULL, 0, &dw);
}
この回答への補足
machongola様、有難うございます。
スレッド関数を使った事が無いので良く理解できていないのですが、
void 起点()
というのが、ボタン2関数の事ですよね?
g_hEvent = ::CreateThread(NULL, 0, &::ThreadProcA, NULL, 0, &dw);
というコードで、スレッド関数が実行されるということですか?
スレッド関数のコードでは
1秒経過すると受信が終わってしまうのではないでしょうか?
延々と受信を行い、任意にボタン1を押して、そのタイミングで
受信を止めたいと考えております。
if(::ReadFile(hCom,Buf,1,NULL,&old) == 0)
{
return;
}
というのは、受信が失敗した場合にスレッドを終了する、という
事ですよね?
データがPCに送られてくるのが遅れて、
少し(数ms)待たないと受信完了しない場合があるので、
ReadFileの戻り値が0の場合でも、WaitForSingleObjectなどで
受信完了まで少し待った方がいいと思うのですが、いかがでしょうか?
宜しければご指摘お願い致します。
No.3
- 回答日時:
挙げられたソースだけではなんとも判断できませんが、
・処理Bは無限ループ?それともAに戻ってくる?
Aに戻ってこないなら、Bの中でもイベント処理をしないと応答無しになってしまいます。
・Flagは0に戻してますか?
無限ループ処理内で Flag==1であることを関知したら、Flag=0に戻しましょう。
そうしないと、一度クリックしたら、いつまでもクリック時の処理を行うことになっていしまいます。
この回答への補足
mtaka2様、有難うございます。
ソースが未完全で申し訳ありませんでした。
処理Bは
Flag = 0;
break;
です。
よってAには戻りません。
Bの中でもイベント処理をする必要があるとの事ですが、
どのようにコーディングしてイベント処理をするのでしょうか?
宜しければご指摘お願い致します。
No.2
- 回答日時:
マルチスレッドにして、通常のメッセージループと無限ループ処理を別スレッドにするのがいいと思います。
あとは、「ボタン1がクリックされたかどうか」を表す変数を用意しておいて、
ボタン1のクリックイベントで変数に代入
無限ループ処理内では、その変数の内容チェック
を行えばいいでしょう。
あるいは、シングルスレッドでも、
無限ループ内でメッセージ処理してもいいでしょう。
http://msdn.microsoft.com/ja-jp/library/3dy7kd92 …
シングルスレッド方式の場合、無限ループ処理内で定期的にメッセージ処理を行う必要があります。
変数を介してクリック情報を取得するのは同じ。
この回答への補足
mtaka2様、有難うございます。
マルチスレッドの知識がまだ無いので、シングルスレッド方式で
メッセージ処理するようにコーディングしました。
ボタン2を押すと無限ループの処理(ボタン2関数)に入ります。
ボタン2関数では延々とデータを受信するように
なっています。(簡略に記述してます)
BYTE Flag = 0;//グローバル変数
ボタン2関数(){
HANDLE hCom;//COMポートのハンドル
unsigned char Buf[4];//受信バッファ
OVERLAPPED old;//オーバーラップ構造体
int i =0;
old.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
while(i != 1){//無限ループ
if(Flag == 1)処理B;
if(ReadFile(hCom,Buf,1,NULL,&old) == 0){
if(WaitForSingleObject(old.hEvent,1000) == WAIT_TIMEOUT){
return;
} } } }
ボタン1関数(){
Flag = 1;
}
ボタン2を押して無限ループを実行している最中にダイアログの
ボタン1を押すと、砂時計のアイコンが出て、フリーズしました。
なぜでしょうか?
宜しければご指摘お願い致します。
No.1
- 回答日時:
Windowsプログラミングするのであれば 無限ループによる処理は避けましょう
待ちを期待する処理ならWaitForSingleObjectなど使ってメッセージポンプを止めないような処理が必要です
無限ループなどの処理をした場合 コントロールで起きたイベントは
独自のメッセージポンプを実装しない限り 永遠に取得できません
ボタンが押された場合は BN_CLICKEDメッセージを処理するようにします
ダイアログエディタで ボタンをダブルクリックすればイベントハンドラを作成してくれます
この回答への補足
redfox63様、有難うございます。
無限ループはご指摘頂いた通りWaitForSingleObjectを使っています。
非同期でCOMポートからデータ受信を行い、1秒でタイムアウトする
設定です。タイムアウトしない限り延々とデータを受信します。
ダイアログエディタでイベントハンドラを作成すると、
Onから始まる名前の関数が作成されますが、
この関数では何も処理を行わないつもりです。
BN_CLICKEDメッセージを処理したいのですが、どのようにコーディング
するのでしょうか?
if(BN_CLICKED == TRUE){
処理
}
という感じでしょうか?
また、BN_CLICKEDだけでは、どのボタンが押されたか分からないのでは
ないでしょうか?
宜しければご指摘お願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
隣の枝がはみ出してきたら切ってもいい?最もやってはいけないことは?
「隣の木が越境してきて困るが、勝手に切ってはいけないと聞くし…」そう思っている方も多いだろう。実は、2023年4月1日に民法が改正され、この「越境枝」のルールが大きく変わった。 教えて!gooでも「境界から出て...
-
弁護士が解説!あなたの声を行政に届ける「パブリックコメント」制度のすべて
社会に対する意見や不満、疑問。それを発信する場所は、SNSやブログ、そしてニュースサイトのコメント欄など多岐にわたる。教えて!gooでも「ヤフコメ民について」というタイトルのトピックがあり、この投稿の通り、...
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
エクセルVBAでクリップボード内...
-
ACCESS側からEXCELの書式を設定...
-
VC++ MFC フォルダサイズの表示
-
サスペンド(休止やスタンバイ...
-
MFCのメニューバーのイベント取得
-
【MFC】イベントの無効化について
-
VB Loopを一時停止し再開あるい...
-
<input type="file">タグで「キ...
-
VBA kernel32 の意味
-
VBA メッセージボックスを自動...
-
【C#】 あるイベントから別イ...
-
シャットダウン時のExcel強制終...
-
PostMessageの連続送信
-
ファンクションキーのキャンセ...
-
Macターミナルで実行中のプログ...
-
C# シリアル通信でデータ受信...
-
家電製品の電力周波数を変える機械
-
「ヒープサイズの設定」て何?
-
VB.NETで起動させたExcelの多重...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
ACCESS側からEXCELの書式を設定...
-
メッセージボックスのボタン名変更
-
VBSで応答不要のメッセージボッ...
-
VBA kernel32 の意味
-
VBA、UserFormを前面に出力して...
-
PostMessageの連続送信
-
Excel VBA で処理中断(DoEvents...
-
【C#】 あるイベントから別イ...
-
Application.ScreenUpdating=Fa...
-
エクセルVBAでクリップボード内...
-
シャットダウン時のExcel強制終...
-
マウスのクリックを無視したい
-
Excel VBA 実行中に一瞬フリー...
-
ボタンが押された事を検知する...
-
Excel VBA 自動的に閉じるMsgBox
-
VCでウエイトをミリ秒でかけ...
-
VB Loopを一時停止し再開あるい...
-
「キャンセル」ボタン付きの処...
-
VB6 コマンドボタン クリック...
おすすめ情報