Visual Studio C++を用い、あるデータを読み込んで波形として表示するプログラムを作っています。読み込みまでできたのであとは描画するだけなのですが、ビルドはできるのですが描画できません。具体的には、描画する用の構造体(disp_xy)を一つのソースファイル(kobayashi_disp_xy.cpp)で作り、ウィンドウプロシージャ(kobayashi_WndProc3.cpp)でこの構造体を用いて描画させようとしています。なぜ描画されないのか検討もつきません。なにかアドバイスをいただけないでしょうか?
kobayashi_disp_xy.cpp
// 位置座標データを1チャンネル分ウィンドウに表示する関数
BOOL disp_xy( HDC hdc, RECT rect, HWND hDlg, int channel )
{
COLORREF color;
int i, j, y; // forで使う変数iと、縦横のグリッド線を引くときのx座標とy座標
double vpd, offset; // V/divとオフセット[div]
int temp; // GetDlgItemIntの値を一時的に保存する
if ( (channel < 1) || (channel > 4) ) return FALSE; // チャンネル指定が間違っていた場合
// プロット色を決める
if ( channel == 1 ) color = RGB(255,153,0)/*RGB(255,241,0)*/; // チャンネル1はYellow
if ( channel == 2 ) color = RGB(228,0,127); // チャンネル2はMagenta
if ( channel == 3 ) color = RGB(0,160,233); // チャンネル3はCyan
if ( channel == 4 ) color = RGB(51,153,102)/*RGB(0,255,0)*/; // チャンネル4は緑
HPEN hPen = CreatePen( PS_SOLID, 0, color);
SelectObject( hdc, hPen ); // hdcで上記のペンを使うために選ぶ
//int n = GetDlgItemInt( hDlg, IDC_EDIT_N, NULL, FALSE ); // 平滑化のための平均計算後のsample数をダイアログボックスから読み込む
int n = total_n;
// V/divを決める
if ( channel == 1 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_V1, NULL, TRUE );
if ( channel == 2 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_V2, NULL, TRUE );
if ( channel == 3 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_V3, NULL, TRUE );
if ( channel == 4 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_V4, NULL, TRUE );
vpd = (double)(temp);
/*sprintf_s(szBuf, 256, "%f", vpd);
MessageBox(NULL, szBuf, "vpd", MB_OK);*/
// オフセット[div]を決める
if ( channel == 1 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_O1, NULL, TRUE );
if ( channel == 2 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_O2, NULL, TRUE );
if ( channel == 3 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_O3, NULL, TRUE );
if ( channel == 4 ) temp = GetDlgItemInt( hDlg, IDC_EDIT_O4, NULL, TRUE );
offset = (double)(temp)/10.0;
int nop = rect.right - rect.left + 1;
//sprintf_s(szBuf, 256, "%d", nop);
//MessageBox(NULL, szBuf, "nop", MB_OK); // 横方向の描画点数
double spp = (double)(n - 1)/(double)(nop - 1);
/*sprintf_s(szBuf, 256, "%f", spp);
MessageBox(NULL, szBuf, "spp", MB_OK);*/ // 1ピクセル当たり何サンプルかを計算する
double ppd = (rect.bottom - rect.top)/8.0; // 縦方向1div当たり何ピクセルか
sprintf_s(szBuf, 256, "%f", ppd);
MessageBox(NULL, szBuf, "ppd", MB_OK);
MessageBox(NULL, szBuf, "n,total_n", MB_OK);*/
for ( i = 0; i < n; i++ ) {
j = (int)(((double)ET[i]/2800000-215.826/*216.026*/)*(nop/10.0) + 0.5);
if ( channel == 1 )
y = (int)( ((double)rect.bottom/2.0) - ((double)/*ETOK[i]*/EQL_MOON[i]/vpd+offset)*ppd + 0.5 );
//y = (int)( ((double)rect.bottom/2.0) - ((double)YEQL[i]/100000)*60 + 0.5 );
//y = (int)( ((double)rect.bottom/2.0) - ((double)ETOK[i]/vpd+offset)*ppd + 0.5 );
if ( channel == 2 )
//y = (int)( ((double)rect.bottom/2.0) - ((double)EQL_MOON[i]/vpd+offset)*ppd + 0.5 );
y = (int)( ((double)rect.bottom/2.0) - ((double)YMOON[i]/vpd+offset)*ppd + 0.5 );
if ( channel == 3 )
//y = (int)( ((double)rect.bottom/2.0) - ((double)EQL_MOON[i]/vpd+offset)*ppd + 0.5 );
y = (int)( ((double)rect.bottom/2.0) - ((double)deg2[i]/vpd+offset)*ppd + 0.5 );
if ( channel == 4 )
//y = (int)( ((double)rect.bottom/2.0) - ((double)EQL_MOON[i]/vpd+offset)*ppd + 0.5 );
y = (int)( ((double)rect.bottom/2.0) - ((double)Night[i]/vpd+offset)*ppd + 0.5 );
if ( i == 0 ) MoveToEx(hdc, j, y, NULL);
if ( i != 0 ) LineTo (hdc, j, y);
}
DeleteObject( hPen ); // ペンを破棄する
return TRUE; // 戻り値TRUEを返す
}
kobayashi_WndProc3.cpp
LRESULT CALLBACK WndProc3( HWND hWnd3, UINT msg, WPARAM wp, LPARAM lp )
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect; // ウィンドウの描画領域を格納する構造体
static BOOL bDraw; // マウスのボタンが押されている間だけTRUEにする
static SHORT x, x_old; // マウスで矩形領域を設定するのに使う。staticにしないとデータが消えてしまうようだ*/
switch (msg) {
case WM_PAINT:
hdc = BeginPaint( hWnd3, &ps ); // 画面のデバイスコンテキストを得て描画開始
GetClientRect( hWnd3, &rect ); // ウィンドウの描画領域を得る
PatBlt( hdc, 0, 0, rect.right, rect.bottom, BLACKNESS ); // 最初に黒く塗りつぶす
disp_axes2( hdc, rect );
if ( IsDlgButtonChecked( hDlg, IDC_CHECK_DISPLAY1 ) == BST_CHECKED ) disp_xy( hdc, rect, hDlg, 1 ); // データを表示する
if ( IsDlgButtonChecked( hDlg, IDC_CHECK_DISPLAY2 ) == BST_CHECKED ) disp_xy( hdc, rect, hDlg, 2 ); // データを表示する
if ( IsDlgButtonChecked( hDlg, IDC_CHECK_DISPLAY3 ) == BST_CHECKED ) disp_xy( hdc, rect, hDlg, 3 ); // データを表示する
if ( IsDlgButtonChecked( hDlg, IDC_CHECK_DISPLAY4 ) == BST_CHECKED ) disp_xy( hdc, rect, hDlg, 4 ); // データを表示する
EndPaint( hWnd3, &ps ); // 描画終り
ReleaseDC( hWnd3, hdc ); // 画面のデバイスコンテキストhdcを破棄する
break;
case WM_MOUSEMOVE:
GetClientRect( hWnd3, &rect ); // ウィンドウの描画領域を得る
x = MAKEPOINTS(lp).x; // マウス位置はWndProcの引数lpに入っている
if ( x < rect.left ) break; // マウス位置が表示外の場合
if ( x > rect.right) break; // マウス位置が表示外の場合
if ( bDraw == FALSE ) return 0; // マウスのボタンを押してなければここで終り
DrawLine( hWnd3, x_old ); // 古い線を逆の色で上書きして消す
DrawLine( hWnd3, x ); // 新しい線を引く
x_old = x; // 現在のxを古いxとする
break;
case WM_LBUTTONDOWN:
bDraw = TRUE;
x = x_old = MAKEPOINTS(lp).x;
DrawLine( hWnd3, x );
break;
case WM_LBUTTONUP:
if(bDraw){
GetClientRect( hWnd3, &rect ); // ウィンドウの描画領域を得る
xs = MAKEPOINTS(lp).x; // WndProcの引数lpに入っているマウス位置をxsとする
// 以下で左側の縦線(青)を引く
hdc = GetDC(hWnd3); // 画面のデバイスコンテキストをhdcに取得する
HPEN hPen = CreatePen( PS_SOLID, 0, RGB(0,0,255)); // 青色のペンを作る
SelectObject( hdc, hPen ); // hdcで上記のペンを使うために選ぶ
MoveToEx(hdc, xs, rect.top, NULL); //ペンを初期位置に移動する
LineTo(hdc, xs, rect.bottom); //縦線を引く
DeleteObject( hPen ); // ペンを破棄する
ReleaseDC(hWnd3, hdc);
bDraw = FALSE; // マウスボタンを押していない状態にする
} else {
return DefWindowProc( hWnd3, msg, wp, lp );
}
break;
case WM_RBUTTONDOWN:
bDraw = TRUE;
x = x_old = MAKEPOINTS(lp).x;
DrawLine( hWnd3, x );
break;
case WM_RBUTTONUP:
if(bDraw){
GetClientRect( hWnd3, &rect ); // ウィンドウの描画領域を得る
xe = MAKEPOINTS(lp).x; // WndProcの引数lpに入っているマウス位置をxeとする
// 以下で右側の縦線(赤)を引く
hdc = GetDC(hWnd3); // 画面のデバイスコンテキストをhdcに取得する
HPEN hPen = CreatePen( PS_SOLID, 0, RGB(255,0,0)); // 赤色のペンを作る
SelectObject( hdc, hPen ); // hdcで上記のペンを使うために選ぶ
MoveToEx(hdc, xe, rect.top, NULL); //ペンを初期位置に移動する
LineTo(hdc, xe, rect.bottom); //縦線を引く
DeleteObject( hPen ); // ペンを破棄する
ReleaseDC(hWnd3, hdc);
bDraw = FALSE; // マウスボタンを押していない状態にする
} else {
return DefWindowProc( hWnd3, msg, wp, lp );
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd3, msg, wp, lp));
}
return 0;
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
Windowsでの描画の基本ができていません。
・描画は基本的にWM_PAINTだけで行う。
・BeginPaintで得られたHDCはEndPaint以降は使用しない(ReleaseDCも不要)
・SelectObjectする際は、戻り値を保持しておき、後で戻す。
・SelectObjectでHDCに選択された状態のリソース(HPENなど)は、DeleteObjectで削除しようとしても削除されず、リソースリークを引き起こす。
・マウスボタンのON/OFFの判断をメッセージ(WM_LBUTTONDOWN/WM_LBUTTONUPなど)だけで行うと、ボタンを押したままウィンドウ外に移動してボタンを離して戻ってきた場合や、他のアプリなどがポップアップウィンドウを表示した場合に正しく処理できない。
特に、最後の部分については、ドラッグ中にポップアップウィンドウが表示されると、ボタンを離した状態でもドラッグ操作を続けてしまうバグを持つアプリをよく見かけます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/06/01 13:33
2017/06/01 22:39
また、提示されたソースではMessageBox関数呼び出しの後ろに「*/」だけが記述されているのでコンパイルエラーになると思います。そもそもWM_PAINT内でMessageBox関数は使うべきではありません。ウィンドウの描画が中途半端な状態で、別のウィンドウの描画に処理が奪われてしまいます。