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