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

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

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

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

Visual Studio

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

C++

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

Q&A

2回答

2929閲覧

ビットマップ形式での描画(月)の上から普通の図形(星)の描画をしたいができない

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グッド

2クリップ

投稿2018/10/20 04:09

編集2022/01/12 10:55

ビットマップ形式でペイントしたお月様の背景に星を描画したいと考えています。月を描画せずに星だけ描画することはできるのですが、ビットマップ形式で月とその背景の宇宙空間を描画し、その上から星を描画しようとすると、月と宇宙空間は正しく描画されますが星が描画されません。星は座標データを読み込みSetPixel関数を用いて十字架の形で描画させています。ビットマップ形式での描画とただの図形(星)の描画を同じウィンドウで行うには何か書き方のポイントとかがあるのでしょうか?(星を描画する関数の呼び出すタイミングがおかしいとか)何かアドバイスがあればよろしくお願い致します。

C++

1//様々な作業の中心となるダイアログ 2BOOL CALLBACK MyDlgProc( HWND hDlg, UINT msg, WPARAM wp, LPARAM lp ) 3{ 4 char *fname; // ファイル名 5 static FILE *fp; // FILEへのポインタ 6 static FILE *fp1; 7 8 int year, month, day, hour, min, sec; //ETを秒で求めたい年, 月, 日, 時, 分, 秒(UTC) 9 10 int i; 11 double Time; 12 double Time_now; 13 double dt; 14 double theta; 15 double RA, DEC; //赤経、赤 16 double koukei, koui; //黄経、黄緯 17 18 switch(msg){ 19 case WM_INITDIALOG: 20 21 //2019年12月26日12時0分0秒(UTC)に初期設定する。 22 SetDlgItemInt(hDlg, IDC_EDIT_Y, 2019, FALSE); 23 SetDlgItemInt(hDlg, IDC_EDIT_M, 12, FALSE); 24 SetDlgItemInt(hDlg, IDC_EDIT_D, 26, FALSE); 25 SetDlgItemInt(hDlg, IDC_EDIT_H, 12, FALSE); 26 SetDlgItemInt(hDlg, IDC_EDIT_MIN, 0, FALSE); 27 SetDlgItemInt(hDlg, IDC_EDIT_S, 0, FALSE); 28 29 CheckDlgButton( hDlg, IDC_CHECK_DISPLAY1, BST_UNCHECKED); 30 31 return TRUE; 32 33 case WM_COMMAND: 34 switch(LOWORD(wp)){ 35 case IDC_BUTTON_OPEN1: // CH1のファイルを開く処理 36 if( fname = filename() ){ 37 if ( fp ) fclose ( fp ); 38 fopen_s ( &fp, fname, "r" ); 39 //read_data(hDlg, fp, 1); 40 // MessageBox(NULL ,"座標ファイル読み込み成功", "CH1", MB_OK);// ファイルをテキスト読み込みモードで開く 41 42 43 44 if (fname = filename()) { 45 if (fp1) fclose(fp1); 46 fopen_s(&fp1, fname, "r"); 47 read_star(hDlg, fp1, 1); 48 //MessageBox(NULL, "星のデータ読み込み成功", "CH1", MB_OK); 49 fclose(fp1); 50 } 51 52 if (read_data(hDlg, fp, 1)) // CH1で読み込む 53 CheckDlgButton(hDlg, IDC_CHECK_DISPLAY1, BST_CHECKED);// チェックボタンを「表示」とする 54 55 fclose( fp ); 56 InvalidateRect(hWnd, NULL, TRUE); 57 } 58 59 60 return TRUE; 61 62 case ID_OK://OKボタンが押された 63 //MessageBox(NULL ,"座標ファイル読み込み成功", "CH1", MB_OK); 64 //Time = et(year, month, day, hour, min, sec)/*GetDlgItemInt(hDlg, IDC_EDIT_ET, NULL, FALSE)*/; 65 66 year = GetDlgItemInt(hDlg, IDC_EDIT_Y, NULL, FALSE); //エディットボックスから年を読み込む 67 month = GetDlgItemInt(hDlg, IDC_EDIT_M, NULL, FALSE); //以下同様 68 day = GetDlgItemInt(hDlg, IDC_EDIT_D, NULL, FALSE); 69 hour = GetDlgItemInt(hDlg, IDC_EDIT_H, NULL, FALSE); 70 min = GetDlgItemInt(hDlg, IDC_EDIT_MIN, NULL, FALSE); 71 sec = GetDlgItemInt(hDlg, IDC_EDIT_S, NULL, FALSE); 72 73 //関数etに上記を引数として渡すと、秒で表されたElapsed Timeが戻される。 74 Time = et(year, month, day, hour, min, sec); 75 76 for(i=0; i<=total_n; i++){ 77 if(rh[i].ET > Time){ 78 g = i-1; 79 dt = Time - rh[g].ET; 80 //sprintf_s(szBuf, 256, "%d", g); 81 //MessageBox(NULL, szBuf, "超える直前のデータの番号", MB_OK); 82 break; 83 } 84 85 } 86 87 //sprintf_s(szBuf, 256, "%d %lf",g , dt); 88 //MessageBox(NULL, szBuf, "データ", MB_OK); 89 90 //sprintf_s(szBuf, 256, "%lf", haET); 91 //MessageBox(NULL, szBuf, "元データ", MB_OK); 92 93 94 95 eql.x = rh[g].VXEQL * dt + rh[g].XEQL; 96 eql.y = rh[g].VYEQL * dt + rh[g].YEQL; 97 eql.z = rh[g].VZEQL * dt + rh[g].ZEQL; 98 99 moon.x = rh[g].VXMOON * dt + rh[g].XMOON; 100 moon.y = rh[g].VYMOON * dt + rh[g].YMOON; 101 moon.z = rh[g].VZMOON * dt + rh[g].ZMOON; 102 103 sun.x = rh[g].VXSUN * dt + rh[g].XSUN; 104 sun.y = rh[g].VYSUN * dt + rh[g].YSUN; 105 sun.z = rh[g].VZSUN * dt + rh[g].ZSUN; 106 107 earth.x = 0; 108 earth.y = 0; 109 earth.z = 0; 110 111 //sprintf_s(szBuf, 256, "%lf %lf %lf %lf %lf %lf", eql.x , eql.y, eql.z, moon.x, moon.y, moon.z); 112 //MessageBox(NULL, szBuf, "eql.x, moon.x", MB_OK); 113 114 EQL_MOON = sqrtf((moon.x - eql.x)*(moon.x - eql.x) + (moon.y - eql.y)*(moon.y - eql.y) + (moon.z - eql.z)*(moon.z - eql.z)); 115 SUN_MOON = sqrtf(sun.x * sun.x + sun.y * sun.y + sun.z * sun.z); 116 EARTH_MOON = sqrtf(moon.x * moon.x + moon.y * moon.y + moon.z * moon.z); 117 118 //t = 360*3474/(2*M_PI*EQL_MOON);//視直径を計算 119 s = (3474.0*0.00005) / EQL_MOON; //月の相対的な大きさを計算 120 121 //sprintf_s(szBuf, 256, "%lf %lf", EQL_MOON, s); 122 //MessageBox(NULL, szBuf, "EQL_MOON, s", MB_OK); 123 124 for(i=0; i<=total_n2; i++){ 125 RA = 2*M_PI*(h[i].RA_h + h[i].RA_m/60 + h[i].RA_s/3600)/24; //単位を時で統一 126 DEC = 2*M_PI*(h[i].Dec_d + h[i].Dec_m/60 + h[i].Dec_s/3600)/360; //単位を度で統一 127 if (h[i].Dec_sig == FALSE) { 128 DEC = -DEC; 129 } 130 koukei = atan2(sin(M_PI*23.43 / 180)*sin(DEC)+cos(M_PI*23.43 / 180)*cos(DEC)*sin(RA),cos(DEC)*cos(RA)); //単位はrad 131 if (koukei < 0) { 132 koukei = koukei + 2 * M_PI; //単位はrad 133 } 134 koui = asin(cos(M_PI*23.43 / 180)*sin(DEC) - sin(M_PI*23.43 / 180)*cos(DEC)*sin(RA)); 135 136 star[i].x = cos(koui)*cos(koukei); 137 star[i].y = cos(koui)*sin(koukei); 138 star[i].z = sin(koui); 139 } 140 141 142 //座標変換1 143 eql = Cordi_Trans1(eql, moon); 144 moon = Cordi_Trans1(moon, moon); 145 sun = Cordi_Trans1(sun, moon); 146 earth = Cordi_Trans1(earth, moon); 147 148 149 //座標変換2 150 theta = atan2(eql.y, eql.x); 151 eql = Cordi_Trans2(eql, theta); 152 sun = Cordi_Trans2(sun, theta); 153 earth = Cordi_Trans2(eql, theta); 154 for(i=0; i<=total_n2; i++){ 155 star[i] = Cordi_Trans2(star[i], theta); 156 } 157 158 //座標変換3 159 theta = atan2(eql.x, eql.z); 160 eql = Cordi_Trans3(eql,theta); 161 sun = Cordi_Trans3(sun,theta); 162 earth = Cordi_Trans3(earth,theta); 163 for(i=0; i<=total_n2; i++){ 164 star[i] = Cordi_Trans3(star[i], theta); 165 } 166 167 //座標変換4 168 theta = atan2(-sun.x, sun.y); 169 eql = Cordi_Trans2(eql,theta); 170 sun = Cordi_Trans2(sun,theta); 171 earth = Cordi_Trans2(earth,theta); 172 for(i=0; i<=total_n2; i++){ 173 star[i] = Cordi_Trans2(star[i], theta); 174 if(star[i].z < 0){ 175 star[i].x = star[i].x * (-50 / star[i].z); 176 star[i].y = star[i].y * (-50 / star[i].z); 177 178 star[i].x = (star[i].x) / 2 * (988.5 / 10); 179 star[i].y = (star[i].y) / 2 * (741 / 10); 180 } 181 } 182 183 if(sun.y > 0){ 184 theta = atan2(-sun.x, sun.y) + M_PI; 185 eql = Cordi_Trans2(eql,theta); 186 sun = Cordi_Trans2(sun,theta); 187 earth = Cordi_Trans2(earth,theta); 188 for(i=0; i<=total_n2; i++){ 189 star[i] = Cordi_Trans2(star[i], theta); 190 if(star[i].z < 0){ 191 star[i].x = star[i].x * (-50 / star[i].z); 192 star[i].y = star[i].y * (-50 / star[i].z); 193 194 star[i].x = (star[i].x) / 2 * (988.5 / 10); 195 star[i].y = (star[i].y) / 2 * (741 / 10); 196 } 197 } 198 } 199 200 201 //sprintf_s(szBuf, 256, "%lf %lf", star[5].x, star[5].y); 202 //MessageBox(NULL, szBuf, "変換後データ", MB_OK); 203 204 205 //g = GetDlgItemInt( hDlg, IDC_EDIT_header2, &number, FALSE ); 206 InvalidateRect(hWnd_bitmap, NULL, TRUE); 207 return TRUE; 208 209 210 case IDCANCEL: //右上の×クリックで終了 211 PostQuitMessage(0); 212 DestroyWindow (hWnd); 213 214 DestroyWindow (hDlg); 215 return TRUE; 216 217 } 218 return TRUE; 219 220 } 221 return FALSE; 222}

図1:月と星を同時に描画した時
イメージ説明
図2:星だけ描画した時
イメージ説明

star[i].x += (rect.right - rect.left) / 2;
star[i].y += (rect.bottom - rect.top) / 2;
と書き換えると
イメージ説明

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/10/20 05:22

星を描画するメソッドを記載したほうがよいかと。
TRON1216.

2018/10/20 05:36

追加しました。
退会済みユーザー

退会済みユーザー

2018/10/20 07:26

図2を見ると、星以外の箇所が白っぽくなってますよね。このあたりに原因があるのでは?
TRON1216.

2018/10/21 10:45

返信が遅れて申し訳有りません。つまり星を描画する関数の中身に問題があるということでしょうか、、
退会済みユーザー

退会済みユーザー

2018/10/21 10:48

コードを見ていないので憶測ですが、星は星の部分だけが白で描画されるのですよね。にもかかわらず、月が消え、背景がグレーになっているということは、全体を上書きしてしまっているのでは?と思いました。
TRON1216.

2018/10/23 14:59

そうです。星だけが白で描画されます。全体を上書きしているというコードの箇所を見つければ良い可能性があるということでしょうか?
退会済みユーザー

退会済みユーザー

2018/10/23 15:45

ですです。おそらくは…ですが。
guest

回答2

0

手続き的には問題ないように思います。
atata0319さんがおっしゃるように座標がおかしいのでは?

データの問題と手続きの問題を切り分けるために、まずは以下の
ように単純に横線だけを引くような処理が正しく動作することを確認し、
それからデータの検証をされてはいかがでしょうか?

C++

1 2// 星の座標データを1チャンネル分ウィンドウに表示する関数 3BOOL disp_star_xy(HDC hdc, RECT rect, HWND hDlg) //ただし、xy平面に描画する関数 4{ 5 COLORREF color; 6 HPEN hPen_xy; 7 int i; 8 9 color = RGB(255, 255, 255);/*RGB(255,241,0)*/ // チャンネル1は黄色 10 hPen_xy = CreatePen(PS_SOLID, 9, color); 11 SelectObject(hdc, hPen_xy); // hdcで上記のペンを使うために選ぶ 12 HBRUSH hBrush_xy, h01dBrush_xy; 13 hBrush_xy = CreateSolidBrush(color); 14 h01dBrush_xy = (HBRUSH)SelectObject(hdc, hBrush_xy); 15 16 int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める? 17 double ppd = (rect.bottom - rect.top) / 10.0; // 縦方向1div当たり何ピクセルか 18 19 20 //------------------------------------------------------- 21 //追記:横線描画 22 for (int i = 0; i < rect.right - rect.left; i++) 23 SetPixel(hdc, i, rect.bottom / 2, RGB(255, 0, 0)); 24 //------------------------------------------------------- 25 26 DeleteObject(hPen_xy); // ペンを破棄する 27 DeleteObject(hBrush_xy); 28 DeleteObject(h01dBrush_xy); 29 30 return TRUE; // 戻り値TRUEを返す 31}

投稿2018/10/24 23:40

ebiryo

総合スコア797

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

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

TRON1216.

2018/10/25 09:51

横線描画するとちゃんと描画されました。つまりデータに問題があると考えます。ここで、下のatata0319さんがアドバイスしてくださった、InvaridateRectを二回以上呼び出すとxが負になりという説明はどういう意味でしょうか?
guest

0

提示されているソースだけで実行することはできないので、完全な再現は不可能でした。

私が適当に動かした感じだと disp_star_xy の以下の部分で広域変数 star の座標が恒久的に変化するため、ありえない位置で星が描画されている感じですね。

C

1 star[i].x = star[i].x - (rect.right-rect.left)/2; 2 star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;

InvalidateRect を 2 回以上呼び出すと X 座標がマイナスとなって描画位置がウィンドウの範囲に入らずに消えています。該当関数を呼び出すかどうかでそのような差になっているのではないでしょうか?


2018/10/24 追記
すみません。最初に伝えるのを忘れてましたが、描画処理に関しては提示されている元のコードで問題なく星は描画できています。
サンプル画像
コード的に変えたのは月の描画部分はめんどくさいのでカットしています。星は移動しないように disp_star_xy 関数の座標更新部分を変更してあります。単色の星だと寂しいので、色が着くようにしてみました。それ以外の部分は提示されているコードのままです。これで問題がある場合、さらに提示されていない部分を提示していただければ、回答しやすいかと思います。

C++

1#include <windows.h> 2#include <math.h> 3 4#define MAX_LOADSTRING 100 5#define ID_MYTIMER 33 6#define MAX_STAR 520 7 8typedef struct { 9 HINSTANCE hInst_bitmap; 10 HWND hWnd_bitmap; 11 BYTE *lpBmpData; 12 BITMAPINFO bmi; 13 RGBQUAD dummy[3]; 14 char *fname; 15 int fsize; 16} IMG; 17 18struct STAR : public POINT { 19 double Mag; 20}; 21 22// グローバル変数: 23HINSTANCE hInst; 24WCHAR szTitle[] = L"teratail153158"; 25WCHAR szWindowClass[] = L"teratail153158"; 26STAR star[MAX_STAR]; 27 28// このコード モジュールに含まれる関数の宣言を転送します: 29ATOM MyRegisterClass(HINSTANCE hInstance); 30BOOL InitInstance(HINSTANCE, int); 31LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 32BOOL disp_star_xy(HDC hdc, RECT rect); 33 34int APIENTRY wWinMain(_In_ HINSTANCE hInstance, 35 _In_opt_ HINSTANCE hPrevInstance, 36 _In_ LPWSTR lpCmdLine, 37 _In_ int nCmdShow) 38{ 39 UNREFERENCED_PARAMETER(hPrevInstance); 40 UNREFERENCED_PARAMETER(lpCmdLine); 41 42 for (int i = 0; i < MAX_STAR; i++) { 43 star[i].x = 988 * rand() / RAND_MAX; 44 star[i].y = 741 * rand() / RAND_MAX; 45 star[i].Mag = 1.0 - 4.0 * rand() / RAND_MAX; 46 } 47 48 // グローバル文字列を初期化する 49 MyRegisterClass(hInstance); 50 51 // アプリケーション初期化の実行: 52 if (!InitInstance (hInstance, nCmdShow)) 53 { 54 return FALSE; 55 } 56 57 MSG msg; 58 59 // メイン メッセージ ループ: 60 while (GetMessage(&msg, nullptr, 0, 0)) 61 { 62 TranslateMessage(&msg); 63 DispatchMessage(&msg); 64 } 65 66 return (int) msg.wParam; 67} 68 69 70 71// 72// 関数: MyRegisterClass() 73// 74// 目的: ウィンドウ クラスを登録します。 75// 76ATOM MyRegisterClass(HINSTANCE hInstance) 77{ 78 WNDCLASSEXW wcex; 79 80 wcex.cbSize = sizeof(WNDCLASSEX); 81 82 wcex.style = CS_HREDRAW | CS_VREDRAW; 83 wcex.lpfnWndProc = WndProc; 84 wcex.cbClsExtra = 0; 85 wcex.cbWndExtra = 0; 86 wcex.hInstance = hInstance; 87 wcex.hIcon = NULL; 88 wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); 89 wcex.hbrBackground = (HBRUSH)(COLOR_3DSHADOW); 90 wcex.lpszMenuName = NULL; 91 wcex.lpszClassName = szWindowClass; 92 wcex.hIconSm = NULL; 93 94 return RegisterClassExW(&wcex); 95} 96 97// 98// 関数: InitInstance(HINSTANCE, int) 99// 100// 目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します 101// 102// コメント: 103// 104// この関数で、グローバル変数でインスタンス ハンドルを保存し、 105// メイン プログラム ウィンドウを作成および表示します。 106// 107BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 108{ 109 hInst = hInstance; // グローバル変数にインスタンス ハンドルを格納する 110 111 HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 112 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); 113 114 if (!hWnd) 115 { 116 return FALSE; 117 } 118 119 ShowWindow(hWnd, nCmdShow); 120 UpdateWindow(hWnd); 121 122 return TRUE; 123} 124 125// 126// 関数: WndProc(HWND, UINT, WPARAM, LPARAM) 127// 128// 目的: メイン ウィンドウのメッセージを処理します。 129// 130// WM_COMMAND - アプリケーション メニューの処理 131// WM_PAINT - メイン ウィンドウを描画する 132// WM_DESTROY - 中止メッセージを表示して戻る 133// 134// 135LRESULT CALLBACK WndProc(HWND hWnd_bitmap, UINT msg, WPARAM wp, LPARAM lp) 136{ 137 IMG g_img; 138 g_img.lpBmpData = NULL; 139 PAINTSTRUCT ps; 140 HDC hdc, hdc_mem; 141 HBITMAP hBmp; 142 int a, b, ab; 143 144 switch (msg) { 145 146 case WM_CREATE: 147 break; 148 149 case WM_PAINT: 150 //月をビットマップ形式で描画していく作業 151 g_img.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 152 g_img.bmi.bmiHeader.biWidth = 988; 153 g_img.bmi.bmiHeader.biHeight = 741; 154 g_img.bmi.bmiHeader.biPlanes = 1; 155 g_img.bmi.bmiHeader.biBitCount = 32; 156 g_img.bmi.bmiHeader.biCompression = BI_RGB; 157 g_img.bmi.bmiHeader.biSizeImage = 988 * 741 * 4; 158 g_img.bmi.bmiHeader.biXPelsPerMeter = 0; 159 g_img.bmi.bmiHeader.biYPelsPerMeter = 0; 160 g_img.bmi.bmiHeader.biClrUsed = 0; 161 g_img.bmi.bmiHeader.biClrImportant = 0; 162 163 g_img.lpBmpData = (BYTE *)malloc(988 * 741 * 4); 164 165 RECT rect; 166 167 hdc = BeginPaint(hWnd_bitmap, &ps); 168 GetClientRect(hWnd_bitmap, &rect); 169 hdc_mem = CreateCompatibleDC(hdc); 170 171 for (a = 0; a < 741; a++) { 172 for (b = 0; b < 988; b++) { 173 174 ab = a * (988 * 4) + b * 4; //始めの項が行数、次の項が左から何ビット目かを表す。(blueの位置を決めている) 175 176 // 以下は月の縁(円)の外側に対する処理(宇宙空間なので黒色で塗りつぶしている) 177 int centerX = 988 / 2; 178 int centerY = 741 / 2; 179 if (sqrt(pow(b - centerX, 2) + pow(a - centerY, 2)) < 250) { 180 g_img.lpBmpData[ab] = 0xff; 181 g_img.lpBmpData[ab + 1] = 0xff; 182 g_img.lpBmpData[ab + 2] = 0xff; 183 g_img.lpBmpData[ab + 3] = 0; 184 } else { 185 g_img.lpBmpData[ab] = 0; 186 g_img.lpBmpData[ab + 1] = 0; 187 g_img.lpBmpData[ab + 2] = 0; 188 g_img.lpBmpData[ab + 3] = 0; 189 190 } 191 } 192 } 193 194 hBmp = CreateDIBitmap(hdc, &(g_img.bmi.bmiHeader), CBM_INIT, g_img.lpBmpData, &(g_img.bmi), DIB_RGB_COLORS); 195 free(g_img.lpBmpData); 196 SelectObject(hdc_mem, hBmp); 197 SetStretchBltMode(hdc, COLORONCOLOR); 198 StretchBlt(hdc, 0, 0, 988, 741, hdc_mem, 0, 0, 988, 741, SRCCOPY); 199 200 //メモリ軸を描画する関数を作り、ここで呼び出している(これはうまく描画できた) 201 //disp_axes2(hdc, rect); 202 203 //星の座標データを描画する関数を作り、ここで呼び出している(月をビットマップ形式で描画しない時は星がちゃんと描画されるが、月をビットマップ形式で描画すると消える) 204 disp_star_xy(hdc, rect); 205 206 DeleteDC(hdc); 207 DeleteDC(hdc_mem); 208 DeleteObject(hBmp); 209 EndPaint(hWnd_bitmap, &ps); 210 ReleaseDC(hWnd_bitmap, hdc); 211 break; 212 213 case WM_DESTROY: 214 PostQuitMessage(0); 215 break; 216 217 default: 218 return (DefWindowProc(hWnd_bitmap, msg, wp, lp)); 219 220 } 221 222 return 0; 223 224} 225 226// 星の座標データを1チャンネル分ウィンドウに表示する関数 227BOOL disp_star_xy(HDC hdc, RECT rect) //ただし、xy平面に描画する関数 228{ 229 const int total_n2 = 40; 230 COLORREF color; 231 int i; 232 233 color = RGB(255, 255, 255);/*RGB(255,241,0)*/ // チャンネル1は黄色 234 int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める? 235 double ppd = (rect.bottom - rect.top) / 10.0; // 縦方向1div当たり何ピクセルか 236 237 for (i = 0; i <= MAX_STAR; i++) { 238// star[i].x = star[i].x - (rect.right - rect.left) / 2; 239// star[i].y = (rect.bottom - rect.top) / 2 - star[i].y; 240 int m; 241 if (star[i].Mag < 0.0) { 242 243 for (m = 0; m <= 8; m += 1) { 244 SetPixel(hdc, star[i].x - m, star[i].y, RGB(228, 0, 127)/*RGB(255, 255, 255)*/); 245 SetPixel(hdc, star[i].x, star[i].y - m, RGB(228, 0, 127)/*RGB(255, 255, 255)*/); 246 SetPixel(hdc, star[i].x, star[i].y, /*RGB(255, 255, 255)*/RGB(228, 0, 127)); 247 SetPixel(hdc, star[i].x + m, star[i].y, RGB(228, 0, 127)/* RGB(255, 255, 255)*/); 248 SetPixel(hdc, star[i].x, star[i].y + m, RGB(228, 0, 127)/*RGB(255, 255, 255)*/); 249 } 250 } 251 252 else if (star[i].Mag < 2.0) { 253 for (m = 0; m <= 6; m += 1) { 254 SetPixel(hdc, star[i].x - m, star[i].y, RGB(255, 255, 255)); 255 SetPixel(hdc, star[i].x, star[i].y - m, RGB(255, 255, 255)); 256 SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/); 257 SetPixel(hdc, star[i].x + m, star[i].y, RGB(255, 255, 255)); 258 SetPixel(hdc, star[i].x, star[i].y + m, RGB(255, 255, 255)); 259 } 260 } 261 262 else if (star[i].Mag < 4.0) { 263 for (m = 0; m <= 4; m += 1) { 264 SetPixel(hdc, star[i].x - m, star[i].y, RGB(255, 255, 255)); 265 SetPixel(hdc, star[i].x, star[i].y - m, RGB(255, 255, 255)); 266 SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/); 267 SetPixel(hdc, star[i].x + m, star[i].y, RGB(255, 255, 255)); 268 SetPixel(hdc, star[i].x, star[i].y + m, RGB(255, 255, 255)); 269 } 270 } 271 272 else { 273 SetPixel(hdc, star[i].x - 2, star[i].y, RGB(255, 255, 255)); 274 SetPixel(hdc, star[i].x, star[i].y - 2, RGB(255, 255, 255)); 275 SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/); 276 SetPixel(hdc, star[i].x + 2, star[i].y, RGB(255, 255, 255)); 277 SetPixel(hdc, star[i].x, star[i].y + 2, RGB(255, 255, 255)); 278 } 279 280 } 281 282 return TRUE; // 戻り値TRUEを返す 283}

2018/10/25 追記
ダイアログのコードを拝見しましたが、一見問題になりそうなところはありませんでした。

私が以前に指摘したのは disp_star_xy 関数における以下のコードブロックの一番下の 2 行です。おそらく星の X 座標を何らかの形で計算しているものと思われますが、X 座標から**(rect.right-rect.left)/2** つまりは画面の半分の幅を減算しているため、この関数が 2 回呼び出された場合、画面の表示範囲内に収まっている X 座標はすべて範囲外になるという指摘です。それが InvalidateRect を2回と言ってたわけですが、実際のところ InvalidateRect を呼び出す以外に WM_PAINT が発行されることがあるので、InvalidateRect だけに限定されるわけではありません。
y 座標の計算も怪しい感じがします。

C++

1// 星の座標データを1チャンネル分ウィンドウに表示する関数 2BOOL disp_star_xy(HDC hdc, RECT rect, HWND hDlg) //ただし、xy平面に描画する関数 3{ 4 COLORREF color; 5 HPEN hPen_xy; 6 int i; 7 8 color = RGB(255,255, 255);/*RGB(255,241,0)*/ // チャンネル1は黄色 9 hPen_xy = CreatePen(PS_SOLID, 9, color); 10 SelectObject(hdc, hPen_xy); // hdcで上記のペンを使うために選ぶ 11 HBRUSH hBrush_xy, h01dBrush_xy; 12 hBrush_xy = CreateSolidBrush(color); 13 h01dBrush_xy = (HBRUSH)SelectObject(hdc, hBrush_xy); 14 int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める? 15 double ppd = (rect.bottom - rect.top) / 10.0; // 縦方向1div当たり何ピクセルか 16 17 for(i=0; i<=total_n2; i++){ 18 star[i].x = star[i].x - (rect.right-rect.left)/2; 19 star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;

投稿2018/10/21 16:43

編集2018/10/25 10:55
atata0319

総合スコア881

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

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

TRON1216.

2018/10/23 15:06

星と月を同時に描画できない原因はそれなのでしょうか、、?星の座標の間違いは今は置いておいていいのかと、、。
atata0319

2018/10/23 17:15

回答に追記しました。完全に現象が再現可能なコードを提示していただけると解決は早いかと思います。
TRON1216.

2018/10/24 16:26

ダイアログプロシージャを載せました。
TRON1216.

2018/10/25 09:53

「InvalidateRect を 2 回以上呼び出すと X 座標がマイナスとなって描画位置がウィンドウの範囲に入らずに消えています。」に原因がありそうなのですが、文章がイマイチ理解できていません。よろしければもう少しだけわかりやすく説明お願い致します。自分の中でInvaridateRectは一回しか呼び出していないつもりになっています、、。
atata0319

2018/10/25 10:55

回答に追記してみました。ご確認ください。
TRON1216.

2018/10/25 11:02

星の元データを座標変換し、最終的な座標系としましてはウィンドウの中心を原点とする座標系です。ご指摘の二行は原点がウィンドウ左上からウィンドウ中心に持っていくための座標変換になります。なので間違いはないと考えております。実際、最近まで月と星を同時に描画できていたのですが、急に描画できなくなりました、、。
atata0319

2018/10/25 11:15

rect は単純に GetClientRect した結果が格納されているようですので、左上の座標を中心に移動させるのであれば、 star[i].x += (rect.right - rect.left) / 2; star[i].y += (rect.bottom - rect.top) / 2; となるのではないでしょうか? とは言っても断片的なコードでは結論を出すのは難しいですね。Github なりに上げていただければアドバイスしやすいとは思います。
TRON1216.

2018/10/25 11:44

その書き方で書き換えるといつでも十字架が中心にいるだけの描画となりました。 そうですよね、、githubの扱いにまだ慣れてないもので、、
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問