質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

4736閲覧

タイマーの割り込み処理が正しく行われない。

TRON1216.

総合スコア37

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/02/23 20:27

編集2018/02/24 08:41
  • やりたいこと

 タイマー関数を用いて丸(円)が大きくなったり小さくなったりアニメーションのようなプログラムの作成。

  • 理想のプログラムの大まかな流れ

 0. ファイル(円の直径のデータが一行ずつ5000個入っている)を選択して、データを読み込み、一行ずつs[0]~s[4999]の配列に入れる。
0. タイマー関数を用い、一定時間ごとにk++(初期値k=0)を施し、WM_PAINT内でellipse関数を用い、そこにs[k]のデータを入れて、s[0]からs[4999]で順に描画していく。
0. マウスの左ボタンを押すと、タイマーが停止し、メッセージボックスが表示される。そこには、現在のデータが何番目かを表示(kの値)させる。
0. マウスの右ボタンを押すと、再びタイマーが作動し、続きから描画されていく。

  • 問題点

 プログラムはビルドでき、実行したところ、パッと見た感じでは円が大きくなったり小さくなったりして成功したように見える。左クリックで現在のデータの番号が表示されて、右クリックで再び続きのデータを描画が開始された。しかし、タイマーの間隔を1sや2sにして、データ一つひとつに対して見てみると、一個目の円が描画されたときのkの値が25、二個目の円のときは50など、kが0から1ずつ増えていかず、とびとびの値になる。

  • 試してみたこと

 WM_PAINT内で、ellipse()を書いたあとにメッセージボックスを加えて、kの値を表示するようにした。すると、実行した瞬間(ファイルを選択し、データを読み込む前から)画面に次々にメッセージボックスが出てきてkの値が大きくなっていった。データの読み込みが完了してからタイマーを作動さればよい、、、、?けどどうしたらよいかわからない。

以下は、ウィンドウプロシージャのswitch内のコードです。ファイルの選択、読み込みなどは別のソースファイルで行っています。

switch (msg) { case WM_CREATE: SetTimer(hWnd_2, ID_MYTIMER, 1000, NULL); break;      case WM_PAINT: hdc = BeginPaint(hWnd2, &ps); hPen_MOON = CreatePen(PS_DOT, 0, RGB(255, 255, 0)); h01dPen_MOON = (HPEN)SelectObject(hdc, hPen_MOON); hBrush_MOON = CreateSolidBrush(RGB(255, 255, 0)); h01dBrush_MOON = (HBRUSH)SelectObject(hdc, hBrush_MOON); Ellipse(hdc, 329.5-(s[k]*1000000/4*329.5+0.5), 247-(s[k]*1000000/4*329.5+0.5), 329.5+(s[k]*1000000/4*329.5+0.5), 247+(s[k]*1000000/4*329.5+0.5)); //円をEllipse()を用いて描画 DeleteObject(hPen_MOON); SelectObject(hdc, h01dPen_MOON); SelectObject(hdc, hBrush_MOON); SelectObject(hdc, h01dBrush_MOON); DeleteObject(hBrush_MOON); EndPaint(hWnd2, &ps); break;      case WM_TIMER: if (wp != ID_MYTIMER) return (DefWindowProc(hWnd_bitmap, msg, wp, lp)); ++k; if (++k > total_n) k = total_n - 1; InvalidateRect(hWnd_bitmap, NULL, FALSE); break; case WM_LBUTTONDOWN: KillTimer(hWnd2, 1); sprintf_s(szBuf, 256, "%d番目のデータ",k); MessageBox(NULL, szBuf, "データの番号", MB_OK); break; case WM_RBUTTONDOWN: SendMessage(hWnd2, WM_CREATE, 0,0); break; case WM_DESTROY: if( k = NULL){ KillTimer(hWnd2, ID_MYTIMER); } PostQuitMessage(0); break; default: return (DefWindowProc(hWnd2, msg, wp, lp)); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unz.hori

2018/02/24 00:19

ソースが見にくいです。コード(</>)を使って貼ってください。また質問もだらだら文章で書いてあってわかりずらいです。ポイントを箇条書きで書くなどシンプルに書いてください。回答する人達の事を考えないと見ただけで萎えますよ。
TRON1216.

2018/02/24 07:34

ありがとうございます。質問を修正してみました。またアドバイスあればよろしくお願いいたします。
unz.hori

2018/02/24 08:15

ソースの部分ですが、```ここにソースを貼る```とやればインデントが正しく反映されます
TRON1216.

2018/02/24 08:20

正しく反映されるよう修正しました。誠にありがとうございます。
guest

回答3

0

if (++k > total_n)```の部分ですが、++kとやる時点でkが加算されますがダブルカウントになってませんか?

投稿2018/02/24 08:19

unz.hori

総合スコア1057

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TRON1216.

2018/02/24 08:23

ダブルカウントとはどういうことですか? if(++k>total_n)の処理は消したほうがいいということですか?
unz.hori

2018/02/24 08:24

いや、まず最初の++kでkが加算され、if内部の++kで更に加算されるということです。
TRON1216.

2018/02/24 08:28

ifの処理は最後のデータ(k=4999)までは行われないのでそれまでは問題ないかと、、
unz.hori

2018/02/24 08:32

提示されたソースではmsg = WM_TIMERかつwp = ID_MYTIMERの場合、kが+2されていくのでは?(タイマーが1秒単位だとすると1秒単位に)。最後のデータまで行われないというのはどこで判定していますか?
TRON1216.

2018/02/24 08:46

申し訳ありません。まだ初心者でしてよく理解できていないです、、。この書き方だとに+2されていくのですね、、どう書けばよいかアドバイスいただければ幸いです。判定はまだしていないですが、実行して好きなタイミングで左クリックしてkの値を見ていると、どんどん大きくはなっていますが4999までは達しておらず、また右クリックして待っていると最終的に円が動かなくなり、そのとき左クリックでkをみると4999と表示されました。
unz.hori

2018/02/24 08:49

ifの外の++k;を削除すればいいのでは?
TRON1216.

2018/02/24 08:59

とてもバカなこと言っててあれなんですけど、いま++k;を消してビルドして実行すると、次々に描画されていきました。k++を書かなくても一定時間おきにkは増えていくのですね、、あと、まだ一回目の円の描画のときのkの値が20とかで、めちゃくちゃとびとびです、、
unz.hori

2018/02/24 09:11

ソースが多分一部しか公開されていないのでkがどこで初期化されているのかどこで定義されているのかさっぱりわからないので回答不能です。
TRON1216.

2018/02/24 09:15

kはグローバル変数として別のソースファイルで初期化しています。 kの初期化をウィンドウプロシージャ内で行うと、一定時間ごとにkが0から再スタートになってしまうまたはずっと0になってしまうので、ほかの場所で初期化したところ、いちおうアニメーションのように描画できました、、
unz.hori

2018/02/24 09:22

プログラムの構成がよく分からないのでなんとも言えませんが、グローバル変数はバグの元なのであまり使うことをお勧めしません。クラスのメンバ変数とすればいいのではと思います。
guest

0

一部分のソースなのであてずっぽうの指摘になります。

hWnd2、hWnd_bitmapは何ですか?
通常、ウィンドウプロシージャで渡されるHWND型の変数を使って各メッセージの処理を行います。
WindowProc - Microsoft
特にDefWindowProc関数に渡している第一引数が統一されていない時点でおかしいです。

WM_PAINTメッセージでBeginPaintの戻り値hdcをわざわざReleaseDCに渡していますが、渡さなくてよいです。ReleaseDCに渡すHDC変数はGetDC関数で取得したものだけです。

WM_RBUTTONDOWNメッセージでWM_CREATEを送信してますが、WM_CREATEはウィンドウが生成されたときに送られるメッセージです。つまり、自分で送るメッセージではありません

あなたは、一度猫でもわかるプログラミングの、Windows SDK編を順にやって正しいやり方を理解する必要があると思います。

投稿2018/02/24 08:35

phoenix3430025

総合スコア135

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TRON1216.

2018/02/24 08:39

hWnd_bitmapはコピペみすです。 三つ目の指摘ですが、タイマーを止めた後、再び途中からタイマーを再開するにはどうしたらよいのでしょうか、?はい、猫でもわかるウィンドウズプログラミングという本を使ってやっています、、まだまだ未熟ですが、よければ教えていただきたいです、、。
TRON1216.

2018/02/24 08:54

ありがとうございます。
guest

0

自己解決

kをグローバル変数としてほかのソースファイルにも利用していたので、kではなく別の変数に置き換えたところ、無事s[o]か順に描画されました。

投稿2018/02/24 10:39

TRON1216.

総合スコア37

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問