
タイマーのつかい方が今ひとつ分かりません。
MFCでタイピングのゲームを作成しているのですが、
25問を解き、正解だった場合もしくは制限時間を超えてしまった場合、次の問題を表示したいと思っております。
下記がプログラム内容です。
void CProgramView::Loop1(CDC* pDC)
{
CProgramDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if((m_nRight<26)|(0<m_nRight))
{
m_nRight=0;//正解数
m_nQuestion=1;//問題数
}
Haikei(pDC);//問題表示領域の枠表示
Tokei(pDC);//時計の秒針が表示される枠表示
Moji(pDC);//問題文表示
OnChar(ch, count,flags);//入力
if(m_fTimer==FALSE)
{
SetTimer(123,250,NULL);//タイマーをセット
if(m_nQuestion<26)//25問以上問題を解いていないケース
{
m_fTimer = FALSE;
}
else m_fTimer = TRUE;//全問解いた場合
}
Loop0(pDC);//秒針の描画クラス
if(m_nx==715)//タイムアウトだった場合
{
KillTimer(123);
NGPaper(pDC);
m_nQuestion++;//問題をカウント
m_sAnser.Empty();//回答文字列をクリア
pDoc->GetNextSet();//次の問題を取得する
InvalidateRect(NULL);
}
if(m_nQuestion<m_nCount)//正解だった場合
{
KillTimer(123);//タイマーを切る
Tokei(pDC);//秒針の画像を消すために時計の画面を再描画
Right(pDC);//正解した場合の画像を描画
Haikei(pDC);//問題文・回答を消すために問題表示領域の枠を再描画
PartsPaper1(pDC);//正解した場合の壁紙を表示
m_nQuestion++;//問題数をカウント
m_sAnser.Empty();//回答文字列をクリアする
pDoc->GetNextSet();//次の問題を取得する
InvalidateRect(NULL);
}
}
そして、この動作を25問、解くまでループさせる関数として以下の関数を作成しました。
void CProgramView::Loop2(CDC* pDC)
{
if(m_fTimer==FALSE)
{
Loop1(pDC);
}
}
//タイマーの内容
void CProgramView::OnTimer(UINT nIDEvent)
{
// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください
if(nIDEvent == 123)
{
InvalidateRect(NULL);
}
CView::OnTimer(nIDEvent);
}
しかし、実際にこのプログラムを実行すると入力し、正解する間は次の問題が表示されるのですが、タイマーが切れません。
そして、制限時間になるとそこまで解いていた問題から凄い勢いで描画が始まり、止まりません。
おそらくタイマーが正常に使えていないという可能性が考えられるのですが・・・。
希望としては、25問を順次解き、解き終わった後は画像を描画し、次の問題を表示したいのですが、どうしたら良いか教えてください。
No.3ベストアンサー
- 回答日時:
Windowsアプリの場合 WM_何とかといったメッセージをWindowsから受け取って動作する仕組みになっています
ボタンを押したのであれば WM_COMMANDとどのボタンかのパラメータ
再描画なら WM_PAINTといった具合です
このメッセージポンプは CWinAppの派生クラスに実装されています
ですからボタンを押した際の処理を OnButton1 などのイベントハンドラと メッセージ振り分けようのメッセージマップでといった具合でMFCは構成されています
このポンプは1つ(または複数)の関数から抜け出た後に戻ることになっています
関数内ではポンプ機能は働きません
void OnButton1()
{
CString ss;
for( int n = 0; n <= 100; n++ ) {
ss.Format( "%d", n );
m_Static1.SetWindowText( ss );
}
}
といった関数があった場合 作者は ラベルの表示を 0から100まで変化させたかったとしても 実際には 100しか表示されないということになります
なぜなら コントロールの再描画がこの関数の中では一切そのチャンスがないからです
// ボタンの押した時は カウンタをリセット、フラグをセット、タイマーをセットするだけ
void OnButton1()
{
if ( m_bflag == FALSE ) {
m_myCnt = 0;
SetTimer( 100, 500, NULL );
}
m_myFlag = TRUE;
}
//ここでメッセージポンプへ返る
// 500msごとに呼び出されるタイマーイベントでラベルへの設定を変更する
void OnTimer( UINT nIDEvent )
{
if ( nIDEvent == 100 ) {
CSTring ss;
ss.Format( "%d" , m_myCnt );
// ラベルへデータを設定
m_Static1.SetWindowText( ss );
myCnt++;
if ( myCnt == 100 ) {
// カウンタが終了値になったなので タイマーを止め
// フラグをリセット
KillTimer( 100 );
m_bFlag = FALSE;
}
}
}
//次のイベント発生のためここでメッセージポンプへ返る
といった具合に作成します
No.2
- 回答日時:
Windowsのタイマーを使うのであれば メッセージポンプを動作させないといけないと思います
メッセージポンプとはウィンドウズの基本システムです
GetMessageやPeekMessage、DiapatchMessage/TranslateMessage
などで構成します
MFCを使うなら
AfxGetApp()->PumpMessage();
でいいようです
流れとしては
1) 問題文の選定
1-2) タイマーを設定 SetTimer
2) 入力値のチェック
2-1) 正解/不正解時のカウント
2-2) タイマーの停止
2-3) 25問未満の場合 1)へ戻って処理続行
3) タイマーイベントで時間切れの処理
3-1) 25問未満の場合 1)へ戻って処理続行
といった関数を用意して、それぞれの処理後関数から抜けるようにしましょう
この回答への補足
ご解答ありがとうございます。
メッセージポンプ・・・!?根本的な問題が解決していないのだと気付かされました。
そこで大変、申し訳ないのですが、具体的なメッセージポンプの利用方法を教えていただけないでしょうか。
No.1
- 回答日時:
★よく読んでいませんが…。
・単純に経過時間を計測したいのなら GetTickCount() 関数を使います。
(他にもGetTickCount64、timeGetTime、QueryPerformanceCounterなど)
サンプル:
DWORD m_dwStart; ←メンバ変数に加える
// 問題の出題開始時
m_dwStart = GetTickCount();
// 問題の出題終了時
DWORD dwDiff = (GetTickCount() - m_dwStart);
if ( dwDiff < (3 * 60 * 1000) ){
3分以内ならこちらで処理
}
else{
3分以上ならこちらで処理
}
このような感じで分岐すれば良いでしょう。
ご解答ありがとうございます。
言葉が足りなく申し訳ございません。
時間計測がしたいというよりも、時間経過後の再度、最初の動作に戻り、ループさせたいのです。
お手数をおかけし申し訳ございません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
ダイアログの表示位置の保存
C言語・C++・C#
-
静的でないメンバ関数の呼び出しが正しくありません
C言語・C++・C#
-
-
4
画面を強制的に再描画させる方法
C言語・C++・C#
-
5
CWnd::OnTimerのスレッドの取得
C言語・C++・C#
-
6
ボタンの表示の色、フォントを変更したい
C言語・C++・C#
-
7
ダイアログ表示時にチェックボックスにチェックされている状態にするには?
C言語・C++・C#
-
8
Visual C++からpingを実行してその結果を得る方法
C言語・C++・C#
-
9
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
10
EDITコントロールで入力できる文字を制限するには?
C言語・C++・C#
-
11
VC++から引数付きexeファイルの実行
C言語・C++・C#
-
12
MFCのワーカースレッドとUIスレッドの使い分け
C言語・C++・C#
-
13
VC++で文字列から任意の文字を削除するにはどうしたらいいですか?
C言語・C++・C#
-
14
適切な変換関数が存在しない???
C言語・C++・C#
-
15
CString から LPCTSTRの型に変換
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
矢印を描画するには
-
NVIDIAのシェーダーキャッシュ
-
プログレスバーでの経過状況表示
-
ローディング画面をマルチスレ...
-
C++ ダイアログ画面について
-
タブコントロール上のピクチャ...
-
windows7 VS2013 MFCの描画処理...
-
扇形などを描く方法
-
DirectX9.0での四角形の描画に...
-
OneNote 2010 文字と描画がずれる
-
PCで「使用可能な場合はグラフ...
-
Pascalで二次元配列、手続きを...
-
C# ゲーム作成 FPSと描画...
-
MFCタブコントロールのグラデー...
-
word
-
MFC XPでのTextOutのボヤケにつ...
-
この二つの違いは・・・?
-
DrawTextでの描画
-
OpenGLでの描画のタイミング
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
[VB.net] DataGridViewの列ヘッ...
-
word
-
TextBoxに文字を書いても表示さ...
-
VB6,リストボックスの特定行の...
-
NVIDIAのシェーダーキャッシュ
-
MFCでOnPaintのタイミング
-
panelのスクロール表示について
-
VC++プログラムをつかったBMP画...
-
Labelの文字をスクロールする際...
-
UpdateData( FALSE); による文...
-
VBAにGDI+を参照させる方法
-
CStaticコントロールの静的イメ...
-
FlexGridの一部のみ表示を更新...
-
Form1 Load で実行されない。
-
VB.netでのライン描画方法がわ...
-
重いグラフィックス処理
-
InvalidateRectの使い方について
-
SHGetFileInfoでアイコンが取得...
-
OneNote 2010 文字と描画がずれる
おすすめ情報