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

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

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

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

Visual Studio

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

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

C++

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

Q&A

解決済

1回答

2252閲覧

波形が画面に表示されません。

TRON1216.

総合スコア37

C

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

Visual Studio

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

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

C++

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

0グッド

0クリップ

投稿2017/05/31 07:32

編集2017/05/31 12:54

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; }

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

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

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

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

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

guest

回答1

0

ベストアンサー

Windowsでの描画の基本ができていません。

・描画は基本的にWM_PAINTだけで行う。
・BeginPaintで得られたHDCはEndPaint以降は使用しない(ReleaseDCも不要)
・SelectObjectする際は、戻り値を保持しておき、後で戻す。
・SelectObjectでHDCに選択された状態のリソース(HPENなど)は、DeleteObjectで削除しようとしても削除されず、リソースリークを引き起こす。
・マウスボタンのON/OFFの判断をメッセージ(WM_LBUTTONDOWN/WM_LBUTTONUPなど)だけで行うと、ボタンを押したままウィンドウ外に移動してボタンを離して戻ってきた場合や、他のアプリなどがポップアップウィンドウを表示した場合に正しく処理できない。

特に、最後の部分については、ドラッグ中にポップアップウィンドウが表示されると、ボタンを離した状態でもドラッグ操作を続けてしまうバグを持つアプリをよく見かけます。

投稿2017/06/01 02:30

編集2017/06/01 02:31
m-take

総合スコア249

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

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

TRON1216.

2017/06/01 04:33

丁寧な回答ありがとうございます。これはビルドできてもプロットが表示されない原因なのでしょうか、、?
m-take

2017/06/01 13:39

Windowsでは、描画内容が変更された場合には、InvalidateRectで再描画が必要な部分を無効領域に指定します。そうするとWM_PAINTメッセージが発生して再描画されるようになるのですが、その仕組みがうまく動くためには、描画をWM_PAINTだけで行う必要があります。なので、先にその部分を指摘しています。 また、提示されたソースではMessageBox関数呼び出しの後ろに「*/」だけが記述されているのでコンパイルエラーになると思います。そもそもWM_PAINT内でMessageBox関数は使うべきではありません。ウィンドウの描画が中途半端な状態で、別のウィンドウの描画に処理が奪われてしまいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問