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