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