1 #include <petscsys.h>
2 #include <petsc/private/drawimpl.h>
3 #include <../src/sys/classes/draw/impls/win32/win32draw.h>
4
5 #define IDC_FOUR 109
6 #define IDI_FOUR 107
7 #define IDM_EXIT 105
8 #define IDR_POPUP 103
9 #define MAX_LOADSTRING 100
10
11 #if !defined(SelectPen)
12 #define SelectPen(hdc, hpen) ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
13 #endif
14 #if !defined(SelectFont)
15 #define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
16 #endif
17 #if !defined(SelectBrush)
18 #define SelectBrush(hdc, hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
19 #endif
20 #if !defined(GetStockBrush)
21 #define GetStockBrush(i) ((HBRUSH)GetStockObject(i))
22 #endif
23
24 #define XTRANS(draw, win, x) (int)(((win)->w) * ((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl))))
25 #define YTRANS(draw, win, y) (int)(((win)->h) * (1.0 - (draw)->port_yl - (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl))))
26
27 HINSTANCE hInst;
28 HANDLE g_hWindowListMutex = NULL;
29 WindowNode WindowListHead = NULL;
30
31 /* Hard coded color hue until hue.c works with this */
32 unsigned char RedMap[] = {255, 0, 255, 0, 0, 0, 255, 127, 34, 255, 238, 165, 255, 255, 190, 255, 255, 238, 0, 255, 105, 154, 135, 0, 0, 244, 152, 176, 220, 216, 50, 255};
33 unsigned char GreenMap[] = {255, 0, 0, 255, 255, 0, 0, 255, 139, 165, 130, 42, 182, 127, 190, 255, 215, 162, 197, 246, 105, 205, 206, 100, 0, 164, 245, 224, 17, 191, 205, 240};
34 unsigned char BlueMap[] = {255, 0, 0, 0, 255, 255, 225, 212, 34, 0, 238, 42, 193, 80, 190, 0, 0, 173, 205, 143, 105, 50, 235, 0, 128, 96, 255, 230, 120, 216, 50, 245};
35
36 /* Forward declarations of functions included in this code module: */
37 LRESULT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
38 static PetscErrorCode TranslateColor_Win32(PetscDraw, int);
39 static PetscErrorCode AverageColorRectangle_Win32(PetscDraw, int, int, int, int);
40 static PetscErrorCode AverageColorTriangle_Win32(PetscDraw, int, int, int);
41 static PetscErrorCode deletemouselist_Win32(WindowNode);
42 static void OnPaint_Win32(HWND);
43 static void OnDestroy_Win32(HWND);
44 static PetscErrorCode MouseRecord_Win32(HWND, PetscDrawButton);
45 static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw, PetscDraw *);
46
PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)47 static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
48 {
49 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
50 HDC hdc = GetDC(windraw->hWnd);
51
52 PetscFunctionBegin;
53 windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
54 windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc, windraw->w, windraw->h);
55 windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer, windraw->node->DoubleBufferBit);
56 /* Fill background of second buffer */
57 ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
58 /* Copy current buffer into second buffer and set window data as double buffered */
59 BitBlt(windraw->node->DoubleBuffer, 0, 0, windraw->w, windraw->h, windraw->node->Buffer, 0, 0, SRCCOPY);
60
61 windraw->node->DoubleBuffered = PETSC_TRUE;
62 ReleaseDC(windraw->hWnd, hdc);
63 PetscFunctionReturn(PETSC_SUCCESS);
64 }
65
PetscDrawFlush_Win32(PetscDraw draw)66 static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
67 {
68 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
69 HDC hdc = GetDC(windraw->hWnd);
70
71 PetscFunctionBegin;
72 /* flush double buffer into primary buffer */
73 BitBlt(windraw->node->Buffer, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
74 /* flush double buffer into window */
75 BitBlt(hdc, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
76 ReleaseDC(windraw->hWnd, hdc);
77 PetscFunctionReturn(PETSC_SUCCESS);
78 }
79
deletemouselist_Win32(WindowNode deletelist)80 static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
81 {
82 /* Called upon window close. Frees memory of linked list of stored mouse commands */
83 MouseNode node;
84
85 while (deletelist->MouseListHead) {
86 node = deletelist->MouseListHead;
87 if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
88 PetscFree(node);
89 }
90 deletelist->MouseListHead = deletelist->MouseListTail = NULL;
91 if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
92 if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
93 PetscFree(deletelist);
94 return PETSC_SUCCESS;
95 }
96
PetscDrawGetMouseButton_Win32(PetscDraw draw,PetscDrawButton * button,PetscReal * x_user,PetscReal * y_user,PetscReal * x_phys,PetscReal * y_phys)97 static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button, PetscReal *x_user, PetscReal *y_user, PetscReal *x_phys, PetscReal *y_phys)
98 {
99 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
100 WindowNode current;
101 MouseNode node = 0;
102
103 PetscFunctionBegin;
104 /* Make sure no other code is using the linked list at this moment */
105 WaitForSingleObject(g_hWindowListMutex, INFINITE);
106 /* Look for the node that matches the window you are using */
107 current = WindowListHead;
108 while (current) {
109 if (current->hWnd == windraw->hWnd) {
110 current->IsGetMouseOn = TRUE;
111 break;
112 } else current = current->wnext;
113 }
114 /* If no actions have occurred, wait for one */
115 node = current->MouseListHead;
116 if (!node) {
117 ReleaseMutex(g_hWindowListMutex);
118 WaitForSingleObject(current->event, INFINITE);
119 WaitForSingleObject(g_hWindowListMutex, INFINITE);
120 }
121 /* once we have the information, assign the pointers to it */
122 *button = current->MouseListHead->Button;
123 *x_user = current->MouseListHead->user.x;
124 *y_user = current->MouseListHead->user.y;
125 /* optional arguments */
126 if (x_phys) *x_phys = current->MouseListHead->phys.x;
127 if (y_phys) *y_phys = current->MouseListHead->phys.y;
128 /* remove set of information from sub linked-list, delete the node */
129 current->MouseListHead = current->MouseListHead->mnext;
130 if (!current->MouseListHead) {
131 ResetEvent(current->event);
132 current->MouseListTail = NULL;
133 }
134 if (node) PetscFree(node);
135
136 /* Release mutex so that other code can use
137 the linked list now that we are done with it */
138 ReleaseMutex(g_hWindowListMutex);
139 PetscFunctionReturn(PETSC_SUCCESS);
140 }
141
PetscDrawPause_Win32(PetscDraw draw)142 static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
143 {
144 PetscFunctionBegin;
145 PetscSleep(draw->pause);
146 PetscFunctionReturn(PETSC_SUCCESS);
147 }
148
TranslateColor_Win32(PetscDraw draw,int color)149 static PetscErrorCode TranslateColor_Win32(PetscDraw draw, int color)
150 {
151 /* Maps single color value into the RGB colors in our tables */
152 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
153 windraw->currentcolor = RGB(RedMap[color], GreenMap[color], BlueMap[color]);
154 return PETSC_SUCCESS;
155 }
156
AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2,int c3,int c4)157 static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw, int c1, int c2, int c3, int c4)
158 {
159 /* Averages colors given at points of rectangle and sets color from color table
160 will be changed once the color gradient problem is worked out */
161 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
162 windraw->currentcolor = RGB((RedMap[c1] + RedMap[c2] + RedMap[c3] + RedMap[c4]) / 4, (GreenMap[c1] + GreenMap[c2] + GreenMap[c3] + GreenMap[c4]) / 4, (BlueMap[c1] + BlueMap[c2] + BlueMap[c3] + BlueMap[c4]) / 4);
163 return PETSC_SUCCESS;
164 }
165
AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)166 static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw, int c1, int c2, int c3)
167 {
168 /* Averages colors given at points of rectangle and sets color from color table
169 will be changed once the color gradient problem is worked out */
170 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
171 windraw->currentcolor = RGB((RedMap[c1] + RedMap[c2] + RedMap[c3]) / 3, (GreenMap[c1] + GreenMap[c2] + GreenMap[c3]) / 3, (BlueMap[c1] + BlueMap[c2] + BlueMap[c3]) / 3);
172 return PETSC_SUCCESS;
173 }
174
PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)175 static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
176 {
177 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
178 HBRUSH hbrush;
179 RECT rect;
180 int x1, yone, x2, y2;
181 HDC hdc;
182
183 PetscFunctionBegin;
184 x1 = XTRANS(draw, windraw, xl);
185 x2 = XTRANS(draw, windraw, xr);
186 yone = YTRANS(draw, windraw, yl);
187 y2 = YTRANS(draw, windraw, yr);
188 SetRect(&rect, x1, y2, x2, yone);
189 if (c1 == c2 && c2 == c3 && c3 == c4) TranslateColor_Win32(draw, c1);
190 else AverageColorRectangle_Win32(draw, c1, c2, c3, c4);
191 hbrush = CreateSolidBrush(windraw->currentcolor);
192
193 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
194 else hdc = windraw->node->Buffer;
195
196 FillRect(hdc, &rect, hbrush);
197 /* Forces a WM_PAINT message and erases background */
198 InvalidateRect(windraw->hWnd, NULL, TRUE);
199 UpdateWindow(windraw->hWnd);
200 PetscFunctionReturn(PETSC_SUCCESS);
201 }
202
PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)203 static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int color)
204 {
205 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
206 HPEN hpen;
207 int x1, yone, x2, y2;
208 HDC hdc;
209
210 PetscFunctionBegin;
211 TranslateColor_Win32(draw, color);
212 x1 = XTRANS(draw, windraw, xl);
213 x2 = XTRANS(draw, windraw, xr);
214 yone = YTRANS(draw, windraw, yl);
215 y2 = YTRANS(draw, windraw, yr);
216 hpen = CreatePen(PS_SOLID, windraw->linewidth, windraw->currentcolor);
217 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
218 else hdc = windraw->node->Buffer;
219
220 SelectPen(hdc, hpen);
221 MoveToEx(hdc, x1, yone, NULL);
222 LineTo(hdc, x2, y2);
223 /* Forces a WM_PAINT message and erases background */
224 InvalidateRect(windraw->hWnd, NULL, TRUE);
225 UpdateWindow(windraw->hWnd);
226 PetscFunctionReturn(PETSC_SUCCESS);
227 }
228
PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)229 static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw, PetscReal width)
230 {
231 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
232 int averagesize, finalwidth;
233 RECT rect;
234
235 PetscFunctionBegin;
236 GetClientRect(windraw->hWnd, &rect);
237 averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
238 finalwidth = (int)PetscFloorReal(averagesize * width);
239 if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
240
241 windraw->linewidth = finalwidth;
242 PetscFunctionReturn(PETSC_SUCCESS);
243 }
244
PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal * width)245 static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width)
246 {
247 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
248
249 PetscFunctionBegin;
250 *width = (PetscReal)windraw->linewidth;
251 PetscFunctionReturn(PETSC_SUCCESS);
252 }
253
PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)254 static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color)
255 {
256 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
257 HBRUSH hbrush;
258 HRGN hrgn;
259 int radius;
260 int x1, yone;
261 HDC hdc;
262
263 PetscFunctionBegin;
264 TranslateColor_Win32(draw, color);
265 x1 = XTRANS(draw, windraw, x);
266 yone = YTRANS(draw, windraw, y);
267 hbrush = CreateSolidBrush(windraw->currentcolor);
268 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
269 else hdc = windraw->node->Buffer;
270
271 /* desired size is one logical pixel so just turn it on */
272 if (windraw->pointdiameter == 1) SetPixelV(hdc, x1, yone, windraw->currentcolor);
273 else {
274 /* draw point around position determined */
275 radius = windraw->pointdiameter / 2; /* integer division */
276 hrgn = CreateEllipticRgn(x1 - radius, yone - radius, x1 + radius, yone + radius);
277 FillRgn(hdc, hrgn, hbrush);
278 }
279 /* Forces a WM_PAINT and erases background */
280 InvalidateRect(windraw->hWnd, NULL, TRUE);
281 UpdateWindow(windraw->hWnd);
282 PetscFunctionReturn(PETSC_SUCCESS);
283 }
284
PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)285 static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw, PetscReal width)
286 {
287 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
288 int averagesize, diameter;
289 RECT rect;
290
291 PetscFunctionBegin;
292 GetClientRect(windraw->hWnd, &rect);
293 averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
294 diameter = (int)PetscFloorReal(averagesize * width);
295 if (diameter < 1) diameter = 1;
296 windraw->pointdiameter = diameter;
297 PetscFunctionReturn(PETSC_SUCCESS);
298 }
299
PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char * text)300 static PetscErrorCode PetscDrawString_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
301 {
302 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
303 RECT r;
304 HFONT hfont;
305 LOGFONT logfont;
306 int x1, yone;
307 HDC hdc;
308
309 PetscFunctionBegin;
310 x1 = XTRANS(draw, windraw, x);
311 yone = YTRANS(draw, windraw, y);
312 r.bottom = yone;
313 r.left = x1;
314 r.right = x1 + 1;
315 r.top = yone + 1;
316
317 logfont.lfHeight = windraw->stringheight;
318 logfont.lfWidth = windraw->stringwidth;
319 logfont.lfEscapement = 0;
320 logfont.lfOrientation = 0;
321 logfont.lfCharSet = 0;
322 logfont.lfClipPrecision = 0;
323 logfont.lfItalic = 0;
324 logfont.lfOutPrecision = 0;
325 logfont.lfPitchAndFamily = DEFAULT_PITCH;
326 logfont.lfQuality = DEFAULT_QUALITY;
327 logfont.lfStrikeOut = 0;
328 logfont.lfUnderline = 0;
329 logfont.lfWeight = FW_NORMAL;
330
331 hfont = CreateFontIndirect(&logfont);
332 TranslateColor_Win32(draw, color);
333 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
334 else hdc = windraw->node->Buffer;
335
336 SelectFont(hdc, hfont);
337 SetTextColor(hdc, windraw->currentcolor);
338 DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP);
339 DeleteObject(hfont);
340 /* Forces a WM_PAINT message and erases background */
341 InvalidateRect(windraw->hWnd, NULL, TRUE);
342 UpdateWindow(windraw->hWnd);
343 PetscFunctionReturn(PETSC_SUCCESS);
344 }
345
PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char * text)346 static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
347 {
348 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
349 RECT r;
350 HFONT hfont;
351 LOGFONT logfont;
352 int x1, yone;
353 HDC hdc;
354
355 PetscFunctionBegin;
356 x1 = XTRANS(draw, windraw, x);
357 yone = YTRANS(draw, windraw, y);
358 r.left = x1;
359 r.bottom = yone + 30;
360 r.right = x1 + 1;
361 r.top = yone - 30;
362
363 logfont.lfEscapement = 2700; /* Causes vertical text drawing */
364 logfont.lfHeight = windraw->stringheight;
365 logfont.lfWidth = windraw->stringwidth;
366 logfont.lfOrientation = 0;
367 logfont.lfCharSet = DEFAULT_CHARSET;
368 logfont.lfClipPrecision = 0;
369 logfont.lfItalic = 0;
370 logfont.lfOutPrecision = 0;
371 logfont.lfPitchAndFamily = DEFAULT_PITCH;
372 logfont.lfQuality = DEFAULT_QUALITY;
373 logfont.lfStrikeOut = 0;
374 logfont.lfUnderline = 0;
375 logfont.lfWeight = FW_NORMAL;
376
377 hfont = CreateFontIndirect(&logfont);
378 TranslateColor_Win32(draw, color);
379 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
380 else hdc = windraw->node->Buffer;
381
382 SelectFont(hdc, hfont);
383 SetTextColor(hdc, windraw->currentcolor);
384 DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP | DT_SINGLELINE);
385 DeleteObject(hfont);
386 /* Forces a WM_PAINT message and erases background */
387 InvalidateRect(windraw->hWnd, NULL, TRUE);
388 UpdateWindow(windraw->hWnd);
389 PetscFunctionReturn(PETSC_SUCCESS);
390 }
391
PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)392 static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height)
393 {
394 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
395 int w, h;
396
397 PetscFunctionBegin;
398 w = (int)(windraw->w * width * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl));
399 h = (int)(windraw->h * height * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl));
400 if (h < 1) h = 1;
401 if (w < 1) w = 1;
402 windraw->stringheight = h;
403 windraw->stringwidth = w;
404 PetscFunctionReturn(PETSC_SUCCESS);
405 }
PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal * width,PetscReal * height)406 static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw, PetscReal *width, PetscReal *height)
407 {
408 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
409 double scaleX = (draw->coor_xr - draw->coor_xl) / (draw->w) * (draw->port_xr - draw->port_xl);
410 double scaleY = (draw->coor_yr - draw->coor_yl) / (draw->h) * (draw->port_yr - draw->port_yl);
411
412 PetscFunctionBegin;
413 if (height) *height = (double)windraw->stringheight * scaleY;
414 if (width) *width = (double)windraw->stringwidth * scaleX;
415 PetscFunctionReturn(PETSC_SUCCESS);
416 }
417
PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)418 static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h)
419 {
420 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
421 RECT r;
422
423 PetscFunctionBegin;
424 GetWindowRect(windraw->hWnd, &r);
425 MoveWindow(windraw->hWnd, r.left, r.top, (int)w, (int)h, TRUE);
426 /* set all variable dealing with window dimensions */
427 windraw->node->bitheight = windraw->h = draw->h = h;
428 windraw->node->bitwidth = windraw->w = draw->w = w;
429 /* set up graphic buffers with the new size of window */
430 SetBitmapDimensionEx(windraw->node->BufferBit, w, h, NULL);
431 if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit, w, h, NULL);
432 windraw->haveresized = PETSC_TRUE;
433 PetscFunctionReturn(PETSC_SUCCESS);
434 }
435
PetscDrawCheckResizedWindow_Win32(PetscDraw draw)436 static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
437 {
438 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
439
440 PetscFunctionBegin;
441 PetscCheck(windraw->haveresized != 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for resizing windows on Microsoft Windows");
442 PetscFunctionReturn(PETSC_SUCCESS);
443 }
444
PetscDrawSetTitle_Win32(PetscDraw draw,const char title[])445 static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
446 {
447 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
448
449 PetscFunctionBegin;
450 SetWindowText(windraw->hWnd, title);
451 PetscFunctionReturn(PETSC_SUCCESS);
452 }
453
PetscDrawClear_Win32(PetscDraw draw)454 static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
455 {
456 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
457
458 PetscFunctionBegin;
459 /* clear primary buffer */
460 ExtFloodFill(windraw->node->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
461 /* if exists clear secondary buffer */
462 if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
463
464 /* force WM_PAINT message so cleared buffer will show */
465 InvalidateRect(windraw->hWnd, NULL, TRUE);
466 UpdateWindow(windraw->hWnd);
467 PetscFunctionReturn(PETSC_SUCCESS);
468 }
469
PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)470 static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw, PetscReal x1, PetscReal yone, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
471 {
472 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
473 HBRUSH hbrush;
474 HPEN hpen;
475 int p1x, p1y, p2x, p2y, p3x, p3y;
476 HDC bit;
477
478 PetscFunctionBegin;
479 AverageColorTriangle_Win32(draw, c1, c2, c3);
480 hbrush = CreateSolidBrush(windraw->currentcolor);
481 hpen = CreatePen(PS_SOLID, 0, windraw->currentcolor);
482 p1x = XTRANS(draw, windraw, x1);
483 p2x = XTRANS(draw, windraw, x2);
484 p3x = XTRANS(draw, windraw, x3);
485 p1y = YTRANS(draw, windraw, yone);
486 p2y = YTRANS(draw, windraw, y2);
487 p3y = YTRANS(draw, windraw, y3);
488
489 if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
490 else bit = windraw->node->Buffer;
491
492 BeginPath(bit);
493 MoveToEx(bit, p1x, p1y, NULL);
494 LineTo(bit, p2x, p2y);
495 LineTo(bit, p3x, p3y);
496 LineTo(bit, p1x, p1y);
497 EndPath(bit);
498 SelectPen(bit, hpen);
499 SelectBrush(bit, hbrush);
500 StrokeAndFillPath(bit);
501 /* Forces a WM_PAINT message and erases background */
502 InvalidateRect(windraw->hWnd, NULL, TRUE);
503 UpdateWindow(windraw->hWnd);
504 PetscFunctionReturn(PETSC_SUCCESS);
505 }
506
PetscDrawSetVisible_Win32(PetscDraw draw,PetscBool visible)507 static PetscErrorCode PetscDrawSetVisible_Win32(PetscDraw draw, PetscBool visible)
508 {
509 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
510
511 PetscFunctionBegin;
512 ShowWindow(windraw->hWnd, visible ? SW_SHOWNA : SW_HIDE);
513 PetscFunctionReturn(PETSC_SUCCESS);
514 }
515
PetscDrawDestroy_Win32(PetscDraw draw)516 static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
517 {
518 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
519
520 PetscFunctionBegin;
521 SendMessage(windraw->hWnd, WM_DESTROY, 0, 0);
522 PetscFree(draw->data);
523 PetscFunctionReturn(PETSC_SUCCESS);
524 }
525
MessageLoopThread_Win32(PetscDraw draw)526 static void MessageLoopThread_Win32(PetscDraw draw)
527 {
528 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
529 MSG msg;
530 HWND hWnd = NULL;
531 const char classname[] = "PETSc Window Class";
532 WNDCLASSEX wclass;
533 LPVOID lpMsgBuf;
534
535 /* initialize window class parameters */
536 wclass.cbSize = sizeof(WNDCLASSEX);
537 wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
538 wclass.lpfnWndProc = (WNDPROC)PetscWndProc;
539 wclass.cbClsExtra = 0;
540 wclass.cbWndExtra = 0;
541 wclass.hInstance = NULL;
542 wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
543 wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
544 wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
545 wclass.lpszMenuName = NULL;
546 wclass.lpszClassName = classname;
547 wclass.hIconSm = NULL;
548
549 RegisterClassEx(&wclass);
550
551 hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL);
552
553 if (!hWnd) {
554 lpMsgBuf = (LPVOID) "Window Not Successfully Created";
555 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
556 LocalFree(lpMsgBuf);
557 exit(0);
558 }
559 windraw->hWnd = hWnd;
560 /* display and update new window */
561 ShowWindow(hWnd, SW_SHOWNORMAL);
562 UpdateWindow(hWnd);
563 SetEvent(windraw->hReadyEvent);
564
565 while (GetMessage(&msg, hWnd, 0, 0)) {
566 TranslateMessage(&msg);
567 DispatchMessage(&msg);
568 }
569 return;
570 }
571
572 static struct _PetscDrawOps DvOps = {PetscDrawSetDoubleBuffer_Win32, PetscDrawFlush_Win32, PetscDrawLine_Win32, PetscDrawLineSetWidth_Win32, PetscDrawLineGetWidth_Win32, PetscDrawPoint_Win32, PetscDrawPointSetSize_Win32, PetscDrawString_Win32, PetscDrawStringVertical_Win32, PetscDrawStringSetSize_Win32, PetscDrawStringGetSize_Win32, 0, PetscDrawClear_Win32, PetscDrawRectangle_Win32, PetscDrawTriangle_Win32, 0, PetscDrawGetMouseButton_Win32, PetscDrawPause_Win32, 0, 0, PetscDrawGetPopup_Win32, PetscDrawSetTitle_Win32, PetscDrawCheckResizedWindow_Win32, PetscDrawResizeWindow_Win32, PetscDrawDestroy_Win32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PetscDrawSetVisible_Win32};
573
PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw * popup)574 static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup)
575 {
576 PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data;
577 PetscBool flg = PETSC_TRUE;
578
579 PetscFunctionBegin;
580 PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL));
581 if (flg) {
582 PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, win->x, win->y + win->h + 36, 220, 220, popup));
583 PetscCall(PetscDrawSetType(*popup, PETSC_DRAW_WIN32));
584 draw->popup = *popup;
585 } else {
586 *popup = NULL;
587 }
588 PetscFunctionReturn(PETSC_SUCCESS);
589 }
PetscDrawCreate_Win32(PetscDraw draw)590 PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
591 {
592 PetscDraw_Win32 *windraw;
593 HANDLE hThread = NULL;
594 WindowNode newnode;
595
596 PetscFunctionBegin;
597 PetscCall(PetscNew(&windraw));
598 draw->data = windraw;
599
600 /* the following is temporary fix for initializing a global datastructure */
601 if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL, FALSE, NULL);
602 draw->ops[0] = DvOps;
603
604 windraw->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
605 /* makes call to MessageLoopThread to creat window and attach a thread */
606 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoopThread_Win32, draw, 0, (LPDWORD)hThread);
607 CloseHandle(hThread);
608 WaitForSingleObject(windraw->hReadyEvent, INFINITE);
609 CloseHandle(windraw->hReadyEvent);
610 WaitForSingleObject(g_hWindowListMutex, INFINITE);
611
612 PetscCall(PetscNew(&newnode));
613 newnode->MouseListHead = NULL;
614 newnode->MouseListTail = NULL;
615 newnode->wnext = WindowListHead;
616 newnode->wprev = NULL;
617 newnode->hWnd = windraw->hWnd;
618 if (WindowListHead) WindowListHead->wprev = newnode;
619 WindowListHead = newnode;
620 windraw->hdc = GetDC(windraw->hWnd);
621
622 windraw->stringheight = 10;
623 windraw->stringwidth = 6;
624 windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
625 windraw->pointdiameter = 1;
626 windraw->node = newnode;
627
628 windraw->x = draw->x;
629 windraw->y = draw->y;
630 windraw->w = newnode->bitwidth = draw->w;
631 windraw->h = newnode->bitheight = draw->h;
632
633 /* Create and initialize primary graphics buffer */
634 newnode->Buffer = CreateCompatibleDC(windraw->hdc);
635 newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc, windraw->w, windraw->h);
636 newnode->store = SelectObject(newnode->Buffer, newnode->BufferBit);
637 ExtFloodFill(newnode->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
638
639 newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL);
640 newnode->DoubleBuffered = PETSC_FALSE;
641
642 ReleaseDC(windraw->hWnd, windraw->hdc);
643 ReleaseMutex(g_hWindowListMutex);
644 PetscFunctionReturn(PETSC_SUCCESS);
645 }
646
647 /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
648 PURPOSE: Processes messages for the main window.
649 WM_COMMAND - process the application menu
650 WM_PAINT - Paint the main window
651 WM_DESTROY - post a quit message and return */
652
PetscWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)653 LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
654 {
655 int wmId;
656
657 switch (message) {
658 HANDLE_MSG(hWnd, WM_PAINT, OnPaint_Win32);
659 HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy_Win32);
660 case WM_COMMAND:
661 wmId = LOWORD(wParam);
662 /* Parse the menu selections:*/
663 switch (wmId) {
664 case IDM_EXIT:
665 DestroyWindow(hWnd);
666 break;
667 default:
668 return DefWindowProc(hWnd, message, wParam, lParam);
669 }
670 break;
671 case WM_LBUTTONUP:
672 MouseRecord_Win32(hWnd, PETSC_BUTTON_LEFT);
673 break;
674 case WM_RBUTTONUP:
675 MouseRecord_Win32(hWnd, PETSC_BUTTON_RIGHT);
676 break;
677 case WM_MBUTTONUP:
678 MouseRecord_Win32(hWnd, PETSC_BUTTON_CENTER);
679 break;
680 default:
681 return DefWindowProc(hWnd, message, wParam, lParam);
682 }
683 return 0;
684 }
685
OnPaint_Win32(HWND hWnd)686 static void OnPaint_Win32(HWND hWnd)
687 {
688 PAINTSTRUCT ps;
689 HDC hdc;
690 WindowNode current = NULL;
691
692 InvalidateRect(hWnd, NULL, TRUE);
693 WaitForSingleObject(g_hWindowListMutex, INFINITE);
694 current = WindowListHead;
695 hdc = BeginPaint(hWnd, &ps);
696
697 while (current) {
698 if (current->hWnd == hWnd) {
699 /* flushes primary buffer to window */
700 BitBlt(hdc, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), current->Buffer, 0, 0, SRCCOPY);
701
702 /* StretchBlt(hdc,0,0,w,h,
703 current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
704 break;
705 }
706 current = current->wnext;
707 }
708 EndPaint(hWnd, &ps);
709 ReleaseMutex(g_hWindowListMutex);
710 return;
711 }
712
MouseRecord_Win32(HWND hWnd,PetscDrawButton button)713 static PetscErrorCode MouseRecord_Win32(HWND hWnd, PetscDrawButton button)
714 {
715 /* Called by all three mouse button actions
716 Records needed mouse data in windows data structure */
717 WindowNode current = NULL;
718 MouseNode newnode;
719 POINT mousepos;
720
721 PetscFunctionBegin;
722 WaitForSingleObject(g_hWindowListMutex, INFINITE);
723 current = WindowListHead;
724 if (current->IsGetMouseOn == TRUE) {
725 SetEvent(current->event);
726 while (current) {
727 if (current->hWnd == hWnd) {
728 PetscCall(PetscNew(&newnode));
729 newnode->Button = button;
730 GetCursorPos(&mousepos);
731 newnode->user.x = mousepos.x;
732 newnode->user.y = mousepos.y;
733 ScreenToClient(hWnd, &mousepos);
734 newnode->phys.x = mousepos.x;
735 newnode->phys.y = mousepos.y;
736 if (!current->MouseListTail) {
737 current->MouseListHead = newnode;
738 current->MouseListTail = newnode;
739 } else {
740 current->MouseListTail->mnext = newnode;
741 current->MouseListTail = newnode;
742 }
743 newnode->mnext = NULL;
744
745 break;
746 }
747 current = current->wnext;
748 }
749 }
750 ReleaseMutex(g_hWindowListMutex);
751 PetscFunctionReturn(PETSC_SUCCESS);
752 }
753
OnDestroy_Win32(HWND hWnd)754 static void OnDestroy_Win32(HWND hWnd)
755 {
756 /* searches linked list of window data and frees corresponding memory */
757 WindowNode current;
758
759 PetscFunctionBegin;
760 WaitForSingleObject(g_hWindowListMutex, INFINITE);
761 current = WindowListHead;
762
763 SetEvent(current->event);
764 while (current) {
765 if (current->hWnd == hWnd) {
766 if (current->wprev) current->wprev->wnext = current->wnext;
767 else WindowListHead = current->wnext;
768 if (current->MouseListHead) deletemouselist_Win32(current);
769 else PetscFree(current);
770 break;
771 }
772 current = current->wnext;
773 }
774 ReleaseMutex(g_hWindowListMutex);
775 PostQuitMessage(0);
776 PetscFunctionReturnVoid();
777 }
778