Actual source code: win32draw.c
1: #include <petscsys.h>
2: #include <petsc/private/drawimpl.h>
3: #include <../src/sys/classes/draw/impls/win32/win32draw.h>
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
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
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))))
27: HINSTANCE hInst;
28: HANDLE g_hWindowListMutex = NULL;
29: WindowNode WindowListHead = NULL;
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};
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 *);
47: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
48: {
49: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
50: HDC hdc = GetDC(windraw->hWnd);
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);
61: windraw->node->DoubleBuffered = PETSC_TRUE;
62: ReleaseDC(windraw->hWnd, hdc);
63: PetscFunctionReturn(PETSC_SUCCESS);
64: }
66: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
67: {
68: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
69: HDC hdc = GetDC(windraw->hWnd);
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: }
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;
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: }
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;
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);
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: }
142: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
143: {
144: PetscFunctionBegin;
145: PetscSleep(draw->pause);
146: PetscFunctionReturn(PETSC_SUCCESS);
147: }
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: }
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: }
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: }
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;
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);
193: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
194: else hdc = windraw->node->Buffer;
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: }
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;
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;
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: }
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;
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 */
241: windraw->linewidth = finalwidth;
242: PetscFunctionReturn(PETSC_SUCCESS);
243: }
245: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width)
246: {
247: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
249: PetscFunctionBegin;
250: *width = (PetscReal)windraw->linewidth;
251: PetscFunctionReturn(PETSC_SUCCESS);
252: }
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;
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;
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: }
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;
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: }
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;
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;
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;
331: hfont = CreateFontIndirect(&logfont);
332: TranslateColor_Win32(draw, color);
333: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
334: else hdc = windraw->node->Buffer;
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: }
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;
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;
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;
377: hfont = CreateFontIndirect(&logfont);
378: TranslateColor_Win32(draw, color);
379: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
380: else hdc = windraw->node->Buffer;
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: }
392: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height)
393: {
394: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
395: int w, h;
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: }
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);
412: PetscFunctionBegin;
413: if (height) *height = (double)windraw->stringheight * scaleY;
414: if (width) *width = (double)windraw->stringwidth * scaleX;
415: PetscFunctionReturn(PETSC_SUCCESS);
416: }
418: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h)
419: {
420: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
421: RECT r;
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: }
436: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
437: {
438: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
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: }
445: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
446: {
447: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
449: PetscFunctionBegin;
450: SetWindowText(windraw->hWnd, title);
451: PetscFunctionReturn(PETSC_SUCCESS);
452: }
454: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
455: {
456: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
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);
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: }
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;
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);
489: if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
490: else bit = windraw->node->Buffer;
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: }
507: static PetscErrorCode PetscDrawSetVisible_Win32(PetscDraw draw, PetscBool visible)
508: {
509: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
511: PetscFunctionBegin;
512: ShowWindow(windraw->hWnd, visible ? SW_SHOWNA : SW_HIDE);
513: PetscFunctionReturn(PETSC_SUCCESS);
514: }
516: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
517: {
518: PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
520: PetscFunctionBegin;
521: SendMessage(windraw->hWnd, WM_DESTROY, 0, 0);
522: PetscFree(draw->data);
523: PetscFunctionReturn(PETSC_SUCCESS);
524: }
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;
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;
549: RegisterClassEx(&wclass);
551: hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL);
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);
565: while (GetMessage(&msg, hWnd, 0, 0)) {
566: TranslateMessage(&msg);
567: DispatchMessage(&msg);
568: }
569: return;
570: }
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};
574: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup)
575: {
576: PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data;
577: PetscBool flg = PETSC_TRUE;
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: }
590: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
591: {
592: PetscDraw_Win32 *windraw;
593: HANDLE hThread = NULL;
594: WindowNode newnode;
596: PetscFunctionBegin;
597: PetscCall(PetscNew(&windraw));
598: draw->data = windraw;
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;
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);
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);
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;
628: windraw->x = draw->x;
629: windraw->y = draw->y;
630: windraw->w = newnode->bitwidth = draw->w;
631: windraw->h = newnode->bitheight = draw->h;
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);
639: newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL);
640: newnode->DoubleBuffered = PETSC_FALSE;
642: ReleaseDC(windraw->hWnd, windraw->hdc);
643: ReleaseMutex(g_hWindowListMutex);
644: PetscFunctionReturn(PETSC_SUCCESS);
645: }
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 */
653: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
654: {
655: int wmId;
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: }
686: static void OnPaint_Win32(HWND hWnd)
687: {
688: PAINTSTRUCT ps;
689: HDC hdc;
690: WindowNode current = NULL;
692: InvalidateRect(hWnd, NULL, TRUE);
693: WaitForSingleObject(g_hWindowListMutex, INFINITE);
694: current = WindowListHead;
695: hdc = BeginPaint(hWnd, &ps);
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);
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: }
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;
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;
745: break;
746: }
747: current = current->wnext;
748: }
749: }
750: ReleaseMutex(g_hWindowListMutex);
751: PetscFunctionReturn(PETSC_SUCCESS);
752: }
754: static void OnDestroy_Win32(HWND hWnd)
755: {
756: /* searches linked list of window data and frees corresponding memory */
757: WindowNode current;
759: PetscFunctionBegin;
760: WaitForSingleObject(g_hWindowListMutex, INFINITE);
761: current = WindowListHead;
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: }