Actual source code: win32draw.c
petsc-3.13.6 2020-09-29
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) \
26: (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)* \
27: ((draw)->port_xr - (draw)->port_xl))/ \
28: ((draw)->coor_xr - (draw)->coor_xl))))
29: #define YTRANS(draw,win,y) \
30: (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)* \
31: ((draw)->port_yr - (draw)->port_yl))/ \
32: ((draw)->coor_yr - (draw)->coor_yl))))
34: HINSTANCE hInst;
35: HANDLE g_hWindowListMutex = NULL;
36: WindowNode WindowListHead = NULL;
38: /* Hard coded color hue until hue.c works with this */
39: 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};
40: 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};
41: 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};
43: /* Foward declarations of functions included in this code module: */
44: LRESULT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
45: static PetscErrorCode TranslateColor_Win32(PetscDraw,int);
46: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
47: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw,int,int,int);
48: static PetscErrorCode deletemouselist_Win32(WindowNode);
49: static void OnPaint_Win32(HWND);
50: static void OnDestroy_Win32(HWND);
51: static PetscErrorCode MouseRecord_Win32(HWND,PetscDrawButton);
52: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw,PetscDraw*);
54: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
55: {
56: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
57: HDC hdc = GetDC(windraw->hWnd);
60: windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
61: windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
62: windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
63: /* Fill background of second buffer */
64: ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
65: /* Copy current buffer into seconf buffer and set window data as double buffered */
66: BitBlt(windraw->node->DoubleBuffer,0,0,windraw->w,windraw->h,
67: windraw->node->Buffer,0,0, SRCCOPY);
69: windraw->node->DoubleBuffered = PETSC_TRUE;
70: ReleaseDC(windraw->hWnd,hdc);
71: return(0);
72: }
74: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
75: {
76: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
77: HDC hdc = GetDC(windraw->hWnd);
80: /* flush double buffer into primary buffer */
81: BitBlt(windraw->node->Buffer,0,0,windraw->w,windraw->h,
82: windraw->node->DoubleBuffer,0,0,SRCCOPY);
83: /* flush double buffer into window */
84: BitBlt(hdc,0,0,windraw->w,windraw->h,
85: windraw->node->DoubleBuffer, 0,0,SRCCOPY);
86: ReleaseDC(windraw->hWnd,hdc);
87: return(0);
88: }
90: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
91: {
92: /* Called upon window close. Frees memory of linked list of stored mouse commands */
93: MouseNode node;
95: while (deletelist->MouseListHead) {
96: node = deletelist->MouseListHead;
97: if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
98: PetscFree(node);
99: }
100: deletelist->MouseListHead = deletelist->MouseListTail = NULL;
101: if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
102: if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
103: PetscFree(deletelist);
104: return 0;
105: }
107: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
108: {
109: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
110: WindowNode current;
111: MouseNode node=0;
114: /* Make sure no other code is using the linked list at this moment */
115: WaitForSingleObject(g_hWindowListMutex, INFINITE);
116: /* Look for the node that matches the window you are using */
117: current = WindowListHead;
118: while (current) {
119: if (current->hWnd == windraw->hWnd) {
120: current->IsGetMouseOn = TRUE;
121: break;
122: } else current = current->wnext;
123: }
124: /* If no actions have occured, wait for one */
125: node = current->MouseListHead;
126: if (!node) {
127: ReleaseMutex(g_hWindowListMutex);
128: WaitForSingleObject(current->event, INFINITE);
129: WaitForSingleObject(g_hWindowListMutex, INFINITE);
130: }
131: /* once we have the information, assign the pointers to it */
132: *button = current->MouseListHead->Button;
133: *x_user = current->MouseListHead->user.x;
134: *y_user = current->MouseListHead->user.y;
135: /* optional arguments */
136: if (x_phys) *x_phys = current->MouseListHead->phys.x;
137: if (y_phys) *y_phys = current->MouseListHead->phys.y;
138: /* remove set of information from sub linked-list, delete the node */
139: current->MouseListHead = current->MouseListHead->mnext;
140: if (!current->MouseListHead) {
141: ResetEvent(current->event);
142: current->MouseListTail = NULL;
143: }
144: if (node) PetscFree(node);
146: /* Release mutex so that other code can use
147: the linked list now that we are done with it */
148: ReleaseMutex(g_hWindowListMutex);
149: return(0);
150: }
152: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
153: {
155: PetscSleep(draw->pause);
156: return(0);
157: }
159: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
160: {
161: /* Maps single color value into the RGB colors in our tables */
162: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
163: windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
164: return 0;
165: }
167: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
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]+RedMap[c4])/4),
173: ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
174: ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
175: return 0;
176: }
178: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
179: {
180: /* Averages colors given at points of rectangle and sets color from color table
181: will be changed once the color gradient problem is worked out */
182: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
183: windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
184: (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
185: (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
186: return 0;
187: }
189: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
190: {
191: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
192: HBRUSH hbrush;
193: RECT rect;
194: int x1,yone,x2,y2;
195: HDC hdc;
198: x1 = XTRANS(draw,windraw,xl);
199: x2 = XTRANS(draw,windraw,xr);
200: yone = YTRANS(draw,windraw,yl);
201: y2 = YTRANS(draw,windraw,yr);
202: SetRect(&rect,x1,y2,x2,yone);
203: if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
204: else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
205: hbrush = CreateSolidBrush(windraw->currentcolor);
207: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
208: else hdc = windraw->node->Buffer;
210: FillRect(hdc,&rect,hbrush);
211: /* Forces a WM_PAINT message and erases background */
212: InvalidateRect(windraw->hWnd,NULL,TRUE);
213: UpdateWindow(windraw->hWnd);
214: return(0);
215: }
217: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
218: {
219: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
220: HPEN hpen;
221: int x1,yone,x2,y2;
222: HDC hdc;
225: TranslateColor_Win32(draw,color);
226: x1 = XTRANS(draw,windraw,xl);x2 = XTRANS(draw,windraw,xr);
227: yone = YTRANS(draw,windraw,yl);y2 = YTRANS(draw,windraw,yr);
228: hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
229: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
230: else hdc = windraw->node->Buffer;
232: SelectPen(hdc,hpen);
233: MoveToEx(hdc,x1,yone,NULL);
234: LineTo(hdc,x2,y2);
235: /* Forces a WM_PAINT message and erases background */
236: InvalidateRect(windraw->hWnd,NULL,TRUE);
237: UpdateWindow(windraw->hWnd);
238: return(0);
239: }
241: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
242: {
243: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
244: int averagesize,finalwidth;
245: RECT rect;
248: GetClientRect(windraw->hWnd,&rect);
249: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
250: finalwidth = (int)PetscFloorReal(averagesize*width);
251: if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
253: windraw->linewidth = finalwidth;
254: return(0);
255: }
257: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
258: {
259: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
262: *width = (PetscReal)windraw->linewidth;
263: return(0);
264: }
266: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
267: {
268: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
269: HBRUSH hbrush;
270: HRGN hrgn;
271: int radius;
272: int x1,yone;
273: HDC hdc;
276: TranslateColor_Win32(draw,color);
277: x1 = XTRANS(draw,windraw,x);
278: yone = YTRANS(draw,windraw,y);
279: hbrush = CreateSolidBrush(windraw->currentcolor);
280: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
281: else hdc = windraw->node->Buffer;
283: /* desired size is one logical pixel so just turn it on */
284: if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
285: else {
286: /* draw point around position determined */
287: radius = windraw->pointdiameter/2; /* integer division */
288: hrgn = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
289: FillRgn(hdc,hrgn,hbrush);
290: }
291: /* Forces a WM_PAINT and erases background */
292: InvalidateRect(windraw->hWnd,NULL,TRUE);
293: UpdateWindow(windraw->hWnd);
294: return(0);
295: }
297: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
298: {
299: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
300: int averagesize,diameter;
301: RECT rect;
304: GetClientRect(windraw->hWnd,&rect);
305: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
306: diameter = (int)PetscFloorReal(averagesize*width);
307: if (diameter < 1) diameter = 1;
308: windraw->pointdiameter = diameter;
309: return(0);
310: }
312: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
313: {
314: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
315: RECT r;
316: HFONT hfont;
317: LOGFONT logfont;
318: int x1,yone;
319: HDC hdc;
322: x1 = XTRANS(draw,windraw,x);
323: yone = YTRANS(draw,windraw,y);
324: r.bottom = yone;
325: r.left = x1;
326: r.right = x1 + 1;
327: r.top = yone + 1;
329: logfont.lfHeight = windraw->stringheight;
330: logfont.lfWidth = windraw->stringwidth;
331: logfont.lfEscapement = 0;
332: logfont.lfOrientation = 0;
333: logfont.lfCharSet = 0;
334: logfont.lfClipPrecision = 0;
335: logfont.lfItalic = 0;
336: logfont.lfOutPrecision = 0;
337: logfont.lfPitchAndFamily = DEFAULT_PITCH;
338: logfont.lfQuality = DEFAULT_QUALITY;
339: logfont.lfStrikeOut = 0;
340: logfont.lfUnderline = 0;
341: logfont.lfWeight = FW_NORMAL;
343: hfont = CreateFontIndirect(&logfont);
344: TranslateColor_Win32(draw,color);
345: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
346: else hdc = windraw->node->Buffer;
348: SelectFont(hdc,hfont);
349: SetTextColor(hdc,windraw->currentcolor);
350: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
351: DeleteObject(hfont);
352: /* Forces a WM_PAINT message and erases background */
353: InvalidateRect(windraw->hWnd,NULL,TRUE);
354: UpdateWindow(windraw->hWnd);
355: return(0);
356: }
358: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
359: {
360: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
361: RECT r;
362: HFONT hfont;
363: LOGFONT logfont;
364: int x1,yone;
365: HDC hdc;
368: x1 = XTRANS(draw,windraw,x);
369: yone = YTRANS(draw,windraw,y);
370: r.left = x1;
371: r.bottom = yone + 30;
372: r.right = x1 + 1;
373: r.top = yone - 30;
375: logfont.lfEscapement = 2700; /* Causes verticle text drawing */
376: logfont.lfHeight = windraw->stringheight;
377: logfont.lfWidth = windraw->stringwidth;
378: logfont.lfOrientation = 0;
379: logfont.lfCharSet = DEFAULT_CHARSET;
380: logfont.lfClipPrecision = 0;
381: logfont.lfItalic = 0;
382: logfont.lfOutPrecision = 0;
383: logfont.lfPitchAndFamily = DEFAULT_PITCH;
384: logfont.lfQuality = DEFAULT_QUALITY;
385: logfont.lfStrikeOut = 0;
386: logfont.lfUnderline = 0;
387: logfont.lfWeight = FW_NORMAL;
389: hfont = CreateFontIndirect(&logfont);
390: TranslateColor_Win32(draw,color);
391: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
392: else hdc = windraw->node->Buffer;
394: SelectFont(hdc,hfont);
395: SetTextColor(hdc,windraw->currentcolor);
396: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
397: DeleteObject(hfont);
398: /* Forces a WM_PAINT message and erases background */
399: InvalidateRect(windraw->hWnd,NULL,TRUE);
400: UpdateWindow(windraw->hWnd);
401: return(0);
402: }
404: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
405: {
406: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
407: int w,h;
410: w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
411: h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
412: if (h < 1) h = 1;
413: if (w < 1) w = 1;
414: windraw->stringheight = h;
415: windraw->stringwidth = w;
416: return(0);
417: }
418: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
419: {
420: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
421: double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
422: double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
425: if (height) *height = (double)windraw->stringheight*scaleY;
426: if (width) *width = (double)windraw->stringwidth*scaleX;
427: return(0);
428: }
430: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
431: {
432: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
433: RECT r;
436: GetWindowRect(windraw->hWnd,&r);
437: MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
438: /* set all variable dealing with window dimensions */
439: windraw->node->bitheight = windraw->h = draw->h = h;
440: windraw->node->bitwidth = windraw->w = draw->w = w;
441: /* set up graphic buffers with the new size of window */
442: SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
443: if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
444: windraw->haveresized = PETSC_TRUE;
445: return(0);
446: }
448: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
449: {
450: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
453: if (windraw->haveresized == 1) PetscFunctionReturn(1);
454: else return(0);
455: }
457: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
458: {
459: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
462: SetWindowText(windraw->hWnd,title);
463: return(0);
464: }
466: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
467: {
468: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
471: /* clear primary buffer */
472: ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
473: /* if exists clear secondary buffer */
474: if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
476: /* force WM_PAINT message so cleared buffer will show */
477: InvalidateRect(windraw->hWnd,NULL,TRUE);
478: UpdateWindow(windraw->hWnd);
479: return(0);
480: }
482: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
483: PetscReal x3,PetscReal y3,int c1,int c2,int c3)
484: {
485: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
486: HBRUSH hbrush;
487: HPEN hpen;
488: int p1x,p1y,p2x,p2y,p3x,p3y;
489: HDC bit;
492: AverageColorTriangle_Win32(draw,c1,c2,c3);
493: hbrush = CreateSolidBrush(windraw->currentcolor);
494: hpen = CreatePen(PS_SOLID,0,windraw->currentcolor);
495: p1x = XTRANS(draw,windraw,x1);
496: p2x = XTRANS(draw,windraw,x2);
497: p3x = XTRANS(draw,windraw,x3);
498: p1y = YTRANS(draw,windraw,yone);
499: p2y = YTRANS(draw,windraw,y2);
500: p3y = YTRANS(draw,windraw,y3);
502: if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
503: else bit = windraw->node->Buffer;
505: BeginPath(bit);
506: MoveToEx(bit,p1x,p1y,NULL);
507: LineTo(bit,p2x,p2y);
508: LineTo(bit,p3x,p3y);
509: LineTo(bit,p1x,p1y);
510: EndPath(bit);
511: SelectPen(bit,hpen);
512: SelectBrush(bit,hbrush);
513: StrokeAndFillPath(bit);
514: /* Forces a WM_PAINT message and erases background */
515: InvalidateRect(windraw->hWnd,NULL,TRUE);
516: UpdateWindow(windraw->hWnd);
517: return(0);
518: }
520: void PopMessageLoopThread_Win32(PetscDraw popdraw)
521: {
522: PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
523: MSG msg;
524: HWND hWnd = NULL;
525: const char PopClassName[] = "PETSc Window Pop Class";
526: RECT r;
527: int width,height;
528: WNDCLASSEX myclass;
529: LPVOID lpMsgBuf;
532: /* initialize window class parameters */
533: myclass.cbSize = sizeof(WNDCLASSEX);
534: myclass.style = CS_OWNDC;
535: myclass.lpfnWndProc = (WNDPROC)PetscWndProc;
536: myclass.cbClsExtra = 0;
537: myclass.cbWndExtra = 0;
538: myclass.hInstance = NULL;
539: myclass.hIcon = NULL;
540: myclass.hCursor = LoadCursor(NULL, IDC_ARROW);
541: myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
542: myclass.lpszMenuName = NULL;
543: myclass.lpszClassName = PopClassName;
544: myclass.hIconSm = NULL;
546: RegisterClassEx(&myclass);
548: SetRect(&r,0,0,450,450);
550: width = (r.right - r.left) / 3;
551: height = (r.bottom - r.top) / 3;
553: hWnd = CreateWindowEx(0,
554: PopClassName,
555: NULL,
556: WS_POPUPWINDOW | WS_CAPTION,
557: 0,0,
558: width,height,
559: NULL,
560: NULL,
561: hInst,
562: NULL);
563: pop->x = 0;
564: pop->y = 0;
565: pop->w = width;
566: pop->h = height;
568: if (!hWnd) {
569: lpMsgBuf = (LPVOID)"Window Not Successfully Created";
570: MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
571: LocalFree(lpMsgBuf);
572: exit(0);
573: }
574: pop->hWnd = hWnd;
575: /* display and update new popup window */
576: ShowWindow(pop->hWnd, SW_SHOWNORMAL);
577: UpdateWindow(pop->hWnd);
578: SetEvent(pop->hReadyEvent);
580: while (GetMessage(&msg, pop->hWnd, 0, 0)) {
581: TranslateMessage(&msg);
582: DispatchMessage(&msg);
583: }
584: PetscFunctionReturnVoid();
585: }
587: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
588: {
589: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
592: SendMessage(windraw->hWnd,WM_DESTROY,0,0);
593: PetscFree(draw->data);
594: return(0);
595: }
597: void MessageLoopThread_Win32(PetscDraw draw)
598: {
599: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
600: MSG msg;
601: HWND hWnd = NULL;
602: const char classname[] = "PETSc Window Class";
603: WNDCLASSEX wclass;
604: LPVOID lpMsgBuf;
607: /* initialize window class parameters */
608: wclass.cbSize = sizeof(WNDCLASSEX);
609: wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
610: wclass.lpfnWndProc = (WNDPROC)PetscWndProc;
611: wclass.cbClsExtra = 0;
612: wclass.cbWndExtra = 0;
613: wclass.hInstance = NULL;
614: wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
615: wclass.hCursor = LoadCursor(NULL,IDC_ARROW);
616: wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
617: wclass.lpszMenuName = NULL;
618: wclass.lpszClassName = classname;
619: wclass.hIconSm = NULL;
621: RegisterClassEx(&wclass);
624: hWnd = CreateWindowEx(0,
625: classname,
626: NULL,
627: WS_OVERLAPPEDWINDOW,
628: draw->x,
629: draw->y,
630: draw->w,
631: draw->h,
632: NULL,
633: NULL,
634: hInst,
635: NULL);
637: if (!hWnd) {
638: lpMsgBuf = (LPVOID)"Window Not Successfully Created";
639: MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
640: LocalFree(lpMsgBuf);
641: exit(0);
642: }
643: windraw->hWnd = hWnd;
644: /* display and update new window */
645: ShowWindow(hWnd,SW_SHOWNORMAL);
646: UpdateWindow(hWnd);
647: SetEvent(windraw->hReadyEvent);
649: while (GetMessage(&msg,hWnd, 0, 0)) {
650: TranslateMessage(&msg);
651: DispatchMessage(&msg);
652: }
653: PetscFunctionReturnVoid();
654: }
657: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
658: PetscDrawFlush_Win32,
659: PetscDrawLine_Win32,
660: PetscDrawLineSetWidth_Win32,
661: PetscDrawLineGetWidth_Win32,
662: PetscDrawPoint_Win32,
663: PetscDrawPointSetSize_Win32,
664: PetscDrawString_Win32,
665: PetscDrawStringVertical_Win32,
666: PetscDrawStringSetSize_Win32,
667: PetscDrawStringGetSize_Win32,
668: 0,
669: PetscDrawClear_Win32,
670: PetscDrawRectangle_Win32,
671: PetscDrawTriangle_Win32,
672: 0,
673: PetscDrawGetMouseButton_Win32,
674: PetscDrawPause_Win32,
675: 0,
676: 0,
677: PetscDrawGetPopup_Win32,
678: PetscDrawSetTitle_Win32,
679: PetscDrawCheckResizedWindow_Win32,
680: PetscDrawResizeWindow_Win32,
681: PetscDrawDestroy_Win32,
682: 0,
683: 0,
684: 0,
685: 0};
687: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
688: {
689: PetscErrorCode ierr;
690: PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
691: PetscBool flg = PETSC_TRUE;
694: PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);
695: if (flg) {
696: PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);
697: PetscDrawSetType(*popup,PETSC_DRAW_WIN32);
698: draw->popup = *popup;
699: } else {
700: *popup = NULL;
701: }
702: return(0);
703: }
704: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
705: {
706: PetscDraw_Win32 *windraw;
707: HANDLE hThread = NULL;
708: PetscErrorCode ierr;
709: WindowNode newnode;
712: PetscNew(&windraw);
713: draw->data = windraw;
715: /* the following is temporary fix for initializing a global datastructure */
716: if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
717: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
719: windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
720: /* makes call to MessageLoopThread to creat window and attach a thread */
721: CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
722: CloseHandle(hThread);
723: WaitForSingleObject(windraw->hReadyEvent,INFINITE);
724: CloseHandle(windraw->hReadyEvent);
725: WaitForSingleObject(g_hWindowListMutex,INFINITE);
727: PetscNew(&newnode);
728: newnode->MouseListHead = NULL;
729: newnode->MouseListTail = NULL;
730: newnode->wnext = WindowListHead;
731: newnode->wprev = NULL;
732: newnode->hWnd = windraw->hWnd;
733: if (WindowListHead) WindowListHead->wprev = newnode;
734: WindowListHead = newnode;
735: windraw->hdc = GetDC(windraw->hWnd);
737: windraw->stringheight = 10;
738: windraw->stringwidth = 6;
739: windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
740: windraw->pointdiameter = 1;
741: windraw->node = newnode;
743: windraw->x = draw->x;
744: windraw->y = draw->y;
745: windraw->w = newnode->bitwidth = draw->w;
746: windraw->h = newnode->bitheight = draw->h;
748: /* Create and initialize primary graphics buffer */
749: newnode->Buffer = CreateCompatibleDC(windraw->hdc);
750: newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
751: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
752: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
754: newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL);
755: newnode->DoubleBuffered = PETSC_FALSE;
757: ReleaseDC(windraw->hWnd,windraw->hdc);
758: ReleaseMutex(g_hWindowListMutex);
759: return(0);
760: }
763: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
764: PURPOSE: Processes messages for the main window.
765: WM_COMMAND - process the Section 1.5 Writing Application Codes with PETSc menu
766: WM_PAINT - Paint the main window
767: WM_DESTROY - post a quit message and return */
769: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
770: {
771: int wmId;
774: switch (message) {
775: HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
776: HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
777: case WM_COMMAND:
778: wmId = LOWORD(wParam);
779: /* Parse the menu selections:*/
780: switch (wmId) {
781: case IDM_EXIT:
782: DestroyWindow(hWnd);
783: break;
784: default:
785: return DefWindowProc(hWnd, message, wParam, lParam);
786: }
787: break;
788: case WM_LBUTTONUP:
789: MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
790: break;
791: case WM_RBUTTONUP:
792: MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
793: break;
794: case WM_MBUTTONUP:
795: MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
796: break;
797: default:
798: PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
799: }
800: return(0);
801: }
803: static void OnPaint_Win32(HWND hWnd)
804: {
805: PAINTSTRUCT ps;
806: HDC hdc;
807: WindowNode current = NULL;
810: InvalidateRect(hWnd,NULL,TRUE);
811: WaitForSingleObject(g_hWindowListMutex, INFINITE);
812: current = WindowListHead;
813: hdc = BeginPaint(hWnd, &ps);
815: while (current) {
816: if (current->hWnd == hWnd) {
817: /* flushes primary buffer to window */
818: BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
819: current->Buffer,0,0,SRCCOPY);
821: /* StretchBlt(hdc,0,0,w,h,
822: current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
823: break;
824: }
825: current = current->wnext;
826: }
827: EndPaint(hWnd, &ps);
828: ReleaseMutex(g_hWindowListMutex);
829: PetscFunctionReturnVoid();
830: }
832: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
833: {
834: /* Called by all three mouse button actions
835: Records needed mouse data in windows data structure */
836: WindowNode current = NULL;
837: MouseNode newnode;
838: POINT mousepos;
842: WaitForSingleObject(g_hWindowListMutex, INFINITE);
843: current = WindowListHead;
844: if (current->IsGetMouseOn == TRUE) {
846: SetEvent(current->event);
847: while (current) {
848: if (current->hWnd == hWnd) {
850: PetscNew(&newnode);
851: newnode->Button = button;
852: GetCursorPos(&mousepos);
853: newnode->user.x = mousepos.x;
854: newnode->user.y = mousepos.y;
855: ScreenToClient(hWnd,&mousepos);
856: newnode->phys.x = mousepos.x;
857: newnode->phys.y = mousepos.y;
858: if (!current->MouseListTail) {
859: current->MouseListHead = newnode;
860: current->MouseListTail = newnode;
861: } else {
862: current->MouseListTail->mnext = newnode;
863: current->MouseListTail = newnode;
864: }
865: newnode->mnext = NULL;
867: break;
868: }
869: current = current->wnext;
870: }
871: }
872: ReleaseMutex(g_hWindowListMutex);
873: return(0);
874: }
876: static void OnDestroy_Win32(HWND hWnd)
877: {
878: /* searches linked list of window data and frees corresponding memory */
879: WindowNode current;
882: WaitForSingleObject(g_hWindowListMutex, INFINITE);
883: current = WindowListHead;
885: SetEvent(current->event);
886: while (current) {
887: if (current->hWnd == hWnd) {
888: if (current->wprev) current->wprev->wnext = current->wnext;
889: else WindowListHead = current->wnext;
890: if (current->MouseListHead) deletemouselist_Win32(current);
891: else PetscFree(current);
892: break;
893: }
894: current = current->wnext;
895: }
896: ReleaseMutex(g_hWindowListMutex);
897: PostQuitMessage(0);
898: PetscFunctionReturnVoid();
899: }