質問するログイン新規登録

回答編集履歴

3

指摘事項を追記しました。

2018/10/25 10:55

投稿

atata0319
atata0319

スコア881

answer CHANGED
@@ -296,4 +296,32 @@
296
296
 
297
297
  return TRUE; // 戻り値TRUEを返す
298
298
  }
299
+ ```
300
+ ---
301
+ **2018/10/25 追記**
302
+ ダイアログのコードを拝見しましたが、一見問題になりそうなところはありませんでした。
303
+
304
+ 私が以前に指摘したのは disp_star_xy 関数における以下のコードブロックの一番下の 2 行です。おそらく星の X 座標を何らかの形で計算しているものと思われますが、X 座標から**(rect.right-rect.left)/2** つまりは画面の半分の幅を減算しているため、この関数が 2 回呼び出された場合、画面の表示範囲内に収まっている X 座標はすべて範囲外になるという指摘です。それが InvalidateRect を2回と言ってたわけですが、実際のところ InvalidateRect を呼び出す以外に WM_PAINT が発行されることがあるので、InvalidateRect だけに限定されるわけではありません。
305
+ y 座標の計算も怪しい感じがします。
306
+
307
+ ```C++
308
+ // 星の座標データを1チャンネル分ウィンドウに表示する関数
309
+ BOOL disp_star_xy(HDC hdc, RECT rect, HWND hDlg) //ただし、xy平面に描画する関数
310
+ {
311
+ COLORREF color;
312
+ HPEN hPen_xy;
313
+ int i;
314
+
315
+ color = RGB(255,255, 255);/*RGB(255,241,0)*/ // チャンネル1は黄色
316
+ hPen_xy = CreatePen(PS_SOLID, 9, color);
317
+ SelectObject(hdc, hPen_xy); // hdcで上記のペンを使うために選ぶ
318
+ HBRUSH hBrush_xy, h01dBrush_xy;
319
+ hBrush_xy = CreateSolidBrush(color);
320
+ h01dBrush_xy = (HBRUSH)SelectObject(hdc, hBrush_xy);
321
+ int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める?
322
+ double ppd = (rect.bottom - rect.top) / 10.0; // 縦方向1div当たり何ピクセルか
323
+
324
+ for(i=0; i<=total_n2; i++){
325
+ star[i].x = star[i].x - (rect.right-rect.left)/2;
326
+ star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;
299
327
  ```

2

記載漏れを追記

2018/10/25 10:55

投稿

atata0319
atata0319

スコア881

answer CHANGED
@@ -11,7 +11,7 @@
11
11
  **2018/10/24 追記**
12
12
  すみません。最初に伝えるのを忘れてましたが、描画処理に関しては提示されている元のコードで問題なく星は描画できています。
13
13
  ![サンプル画像](6d56dc7557446f47f2c50d684af7faec.png)
14
- コード的に変えたのは月の描画部分はめんどくさいのでカットしています。星は移動しないように disp_star_xy 関数の座標更新部分を変更してあります。それ以外の部分は提示されているコードのままです。これで問題がある場合、さらに提示されていない部分を提示していただければ、回答しやすいかと思います。
14
+ コード的に変えたのは月の描画部分はめんどくさいのでカットしています。星は移動しないように disp_star_xy 関数の座標更新部分を変更してあります。単色の星だと寂しいので、色が着くようにしてみました。それ以外の部分は提示されているコードのままです。これで問題がある場合、さらに提示されていない部分を提示していただければ、回答しやすいかと思います。
15
15
  ```C++
16
16
  #include <windows.h>
17
17
  #include <math.h>

1

回答に追記しました。

2018/10/23 17:18

投稿

atata0319
atata0319

スコア881

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