Actual source code: win32draw.c
petsc-3.7.3 2016-08-01
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*);
56: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
57: {
58: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
59: HDC hdc = GetDC(windraw->hWnd);
62: windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
63: windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
64: windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
65: /* Fill background of second buffer */
66: ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
67: /* Copy current buffer into seconf buffer and set window data as double buffered */
68: BitBlt(windraw->node->DoubleBuffer,0,0,windraw->w,windraw->h,
69: windraw->node->Buffer,0,0, SRCCOPY);
71: windraw->node->DoubleBuffered = PETSC_TRUE;
72: ReleaseDC(windraw->hWnd,hdc);
73: return(0);
74: }
78: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
79: {
80: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
81: HDC hdc = GetDC(windraw->hWnd);
84: /* flush double buffer into primary buffer */
85: BitBlt(windraw->node->Buffer,0,0,windraw->w,windraw->h,
86: windraw->node->DoubleBuffer,0,0,SRCCOPY);
87: /* flush double buffer into window */
88: BitBlt(hdc,0,0,windraw->w,windraw->h,
89: windraw->node->DoubleBuffer, 0,0,SRCCOPY);
90: ReleaseDC(windraw->hWnd,hdc);
91: return(0);
92: }
96: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
97: {
98: /* Called upon window close. Frees memory of linked list of stored mouse commands */
99: MouseNode node;
101: while (deletelist->MouseListHead) {
102: node = deletelist->MouseListHead;
103: if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
104: PetscFree(node);
105: }
106: deletelist->MouseListHead = deletelist->MouseListTail = NULL;
107: if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
108: if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
109: PetscFree(deletelist);
110: return 0;
111: }
115: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
116: {
117: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
118: WindowNode current;
119: MouseNode node=0;
122: /* Make sure no other code is using the linked list at this moment */
123: WaitForSingleObject(g_hWindowListMutex, INFINITE);
124: /* Look for the node that matches the window you are using */
125: current = WindowListHead;
126: while (current) {
127: if (current->hWnd == windraw->hWnd) {
128: current->IsGetMouseOn = TRUE;
129: break;
130: } else current = current->wnext;
131: }
132: /* If no actions have occured, wait for one */
133: node = current->MouseListHead;
134: if (!node) {
135: ReleaseMutex(g_hWindowListMutex);
136: WaitForSingleObject(current->event, INFINITE);
137: WaitForSingleObject(g_hWindowListMutex, INFINITE);
138: }
139: /* once we have the information, assign the pointers to it */
140: *button = current->MouseListHead->Button;
141: *x_user = current->MouseListHead->user.x;
142: *y_user = current->MouseListHead->user.y;
143: /* optional arguments */
144: if (x_phys) *x_phys = current->MouseListHead->phys.x;
145: if (y_phys) *y_phys = current->MouseListHead->phys.y;
146: /* remove set of information from sub linked-list, delete the node */
147: current->MouseListHead = current->MouseListHead->mnext;
148: if (!current->MouseListHead) {
149: ResetEvent(current->event);
150: current->MouseListTail = NULL;
151: }
152: if (node) PetscFree(node);
154: /* Release mutex so that other code can use
155: the linked list now that we are done with it */
156: ReleaseMutex(g_hWindowListMutex);
157: return(0);
158: }
162: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
163: {
165: PetscSleep(draw->pause);
166: return(0);
167: }
171: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
172: {
173: /* Maps single color value into the RGB colors in our tables */
174: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
175: windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
176: return 0;
177: }
181: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
182: {
183: /* Averages colors given at points of rectangle and sets color from color table
184: will be changed once the color gradient problem is worked out */
185: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
186: windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
187: ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
188: ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
189: return 0;
190: }
194: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
195: {
196: /* Averages colors given at points of rectangle and sets color from color table
197: will be changed once the color gradient problem is worked out */
198: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
199: windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
200: (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
201: (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
202: return 0;
203: }
207: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
208: {
209: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
210: HBRUSH hbrush;
211: RECT rect;
212: int x1,yone,x2,y2;
213: HDC hdc;
216: x1 = XTRANS(draw,windraw,xl);
217: x2 = XTRANS(draw,windraw,xr);
218: yone = YTRANS(draw,windraw,yl);
219: y2 = YTRANS(draw,windraw,yr);
220: SetRect(&rect,x1,y2,x2,yone);
221: if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
222: else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
223: hbrush = CreateSolidBrush(windraw->currentcolor);
225: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
226: else hdc = windraw->node->Buffer;
228: FillRect(hdc,&rect,hbrush);
229: /* Forces a WM_PAINT message and erases background */
230: InvalidateRect(windraw->hWnd,NULL,TRUE);
231: UpdateWindow(windraw->hWnd);
232: return(0);
233: }
237: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
238: {
239: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
240: HPEN hpen;
241: int x1,yone,x2,y2;
242: HDC hdc;
245: TranslateColor_Win32(draw,color);
246: x1 = XTRANS(draw,windraw,xl);x2 = XTRANS(draw,windraw,xr);
247: yone = YTRANS(draw,windraw,yl);y2 = YTRANS(draw,windraw,yr);
248: hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
249: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
250: else hdc = windraw->node->Buffer;
252: SelectPen(hdc,hpen);
253: MoveToEx(hdc,x1,yone,NULL);
254: LineTo(hdc,x2,y2);
255: /* Forces a WM_PAINT message and erases background */
256: InvalidateRect(windraw->hWnd,NULL,TRUE);
257: UpdateWindow(windraw->hWnd);
258: return(0);
259: }
263: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
264: {
265: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
266: int averagesize,finalwidth;
267: RECT rect;
270: GetClientRect(windraw->hWnd,&rect);
271: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
272: finalwidth = (int)PetscFloorReal(averagesize*width);
273: if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
275: windraw->linewidth = finalwidth;
276: return(0);
277: }
281: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
282: {
283: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
286: *width = (PetscReal)windraw->linewidth;
287: return(0);
288: }
292: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
293: {
294: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
295: HBRUSH hbrush;
296: HRGN hrgn;
297: int radius;
298: int x1,yone;
299: HDC hdc;
302: TranslateColor_Win32(draw,color);
303: x1 = XTRANS(draw,windraw,x);
304: yone = YTRANS(draw,windraw,y);
305: hbrush = CreateSolidBrush(windraw->currentcolor);
306: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
307: else hdc = windraw->node->Buffer;
309: /* desired size is one logical pixel so just turn it on */
310: if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
311: else {
312: /* draw point around position determined */
313: radius = windraw->pointdiameter/2; /* integer division */
314: hrgn = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
315: FillRgn(hdc,hrgn,hbrush);
316: }
317: /* Forces a WM_PAINT and erases background */
318: InvalidateRect(windraw->hWnd,NULL,TRUE);
319: UpdateWindow(windraw->hWnd);
320: return(0);
321: }
325: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
326: {
327: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
328: int averagesize,diameter;
329: RECT rect;
332: GetClientRect(windraw->hWnd,&rect);
333: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
334: diameter = (int)PetscFloorReal(averagesize*width);
335: if (diameter < 1) diameter = 1;
336: windraw->pointdiameter = diameter;
337: return(0);
338: }
342: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
343: {
344: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
345: RECT r;
346: HFONT hfont;
347: LOGFONT logfont;
348: int x1,yone;
349: HDC hdc;
352: x1 = XTRANS(draw,windraw,x);
353: yone = YTRANS(draw,windraw,y);
354: r.bottom = yone;
355: r.left = x1;
356: r.right = x1 + 1;
357: r.top = yone + 1;
359: logfont.lfHeight = windraw->stringheight;
360: logfont.lfWidth = windraw->stringwidth;
361: logfont.lfEscapement = 0;
362: logfont.lfOrientation = 0;
363: logfont.lfCharSet = 0;
364: logfont.lfClipPrecision = 0;
365: logfont.lfItalic = 0;
366: logfont.lfOutPrecision = 0;
367: logfont.lfPitchAndFamily = DEFAULT_PITCH;
368: logfont.lfQuality = DEFAULT_QUALITY;
369: logfont.lfStrikeOut = 0;
370: logfont.lfUnderline = 0;
371: logfont.lfWeight = FW_NORMAL;
373: hfont = CreateFontIndirect(&logfont);
374: TranslateColor_Win32(draw,color);
375: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
376: else hdc = windraw->node->Buffer;
378: SelectFont(hdc,hfont);
379: SetTextColor(hdc,windraw->currentcolor);
380: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
381: DeleteObject(hfont);
382: /* Forces a WM_PAINT message and erases background */
383: InvalidateRect(windraw->hWnd,NULL,TRUE);
384: UpdateWindow(windraw->hWnd);
385: return(0);
386: }
390: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
391: {
392: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
393: RECT r;
394: HFONT hfont;
395: LOGFONT logfont;
396: int x1,yone;
397: HDC hdc;
400: x1 = XTRANS(draw,windraw,x);
401: yone = YTRANS(draw,windraw,y);
402: r.left = x1;
403: r.bottom = yone + 30;
404: r.right = x1 + 1;
405: r.top = yone - 30;
407: logfont.lfEscapement = 2700; /* Causes verticle text drawing */
408: logfont.lfHeight = windraw->stringheight;
409: logfont.lfWidth = windraw->stringwidth;
410: logfont.lfOrientation = 0;
411: logfont.lfCharSet = DEFAULT_CHARSET;
412: logfont.lfClipPrecision = 0;
413: logfont.lfItalic = 0;
414: logfont.lfOutPrecision = 0;
415: logfont.lfPitchAndFamily = DEFAULT_PITCH;
416: logfont.lfQuality = DEFAULT_QUALITY;
417: logfont.lfStrikeOut = 0;
418: logfont.lfUnderline = 0;
419: logfont.lfWeight = FW_NORMAL;
421: hfont = CreateFontIndirect(&logfont);
422: TranslateColor_Win32(draw,color);
423: if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
424: else hdc = windraw->node->Buffer;
426: SelectFont(hdc,hfont);
427: SetTextColor(hdc,windraw->currentcolor);
428: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
429: DeleteObject(hfont);
430: /* Forces a WM_PAINT message and erases background */
431: InvalidateRect(windraw->hWnd,NULL,TRUE);
432: UpdateWindow(windraw->hWnd);
433: return(0);
434: }
438: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
439: {
440: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
441: int w,h;
444: w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
445: h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
446: if (h < 1) h = 1;
447: if (w < 1) w = 1;
448: windraw->stringheight = h;
449: windraw->stringwidth = w;
450: return(0);
451: }
454: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
455: {
456: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
457: double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
458: double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
461: if (height) *height = (double)windraw->stringheight*scaleY;
462: if (width) *width = (double)windraw->stringwidth*scaleX;
463: return(0);
464: }
468: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
469: {
470: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
471: RECT r;
474: GetWindowRect(windraw->hWnd,&r);
475: MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
476: /* set all variable dealing with window dimensions */
477: windraw->node->bitheight = windraw->h = draw->h = h;
478: windraw->node->bitwidth = windraw->w = draw->w = w;
479: /* set up graphic buffers with the new size of window */
480: SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
481: if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
482: windraw->haveresized = PETSC_TRUE;
483: return(0);
484: }
488: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
489: {
490: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
493: if (windraw->haveresized == 1) PetscFunctionReturn(1);
494: else return(0);
495: }
499: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
500: {
501: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
504: SetWindowText(windraw->hWnd,title);
505: return(0);
506: }
510: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
511: {
512: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
515: /* clear primary buffer */
516: ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
517: /* if exists clear secondary buffer */
518: if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
520: /* force WM_PAINT message so cleared buffer will show */
521: InvalidateRect(windraw->hWnd,NULL,TRUE);
522: UpdateWindow(windraw->hWnd);
523: return(0);
524: }
528: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
529: PetscReal x3,PetscReal y3,int c1,int c2,int c3)
530: {
531: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
532: HBRUSH hbrush;
533: HPEN hpen;
534: int p1x,p1y,p2x,p2y,p3x,p3y;
535: HDC bit;
538: AverageColorTriangle_Win32(draw,c1,c2,c3);
539: hbrush = CreateSolidBrush(windraw->currentcolor);
540: hpen = CreatePen(PS_SOLID,0,windraw->currentcolor);
541: p1x = XTRANS(draw,windraw,x1);
542: p2x = XTRANS(draw,windraw,x2);
543: p3x = XTRANS(draw,windraw,x3);
544: p1y = YTRANS(draw,windraw,yone);
545: p2y = YTRANS(draw,windraw,y2);
546: p3y = YTRANS(draw,windraw,y3);
548: if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
549: else bit = windraw->node->Buffer;
551: BeginPath(bit);
552: MoveToEx(bit,p1x,p1y,NULL);
553: LineTo(bit,p2x,p2y);
554: LineTo(bit,p3x,p3y);
555: LineTo(bit,p1x,p1y);
556: EndPath(bit);
557: SelectPen(bit,hpen);
558: SelectBrush(bit,hbrush);
559: StrokeAndFillPath(bit);
560: /* Forces a WM_PAINT message and erases background */
561: InvalidateRect(windraw->hWnd,NULL,TRUE);
562: UpdateWindow(windraw->hWnd);
563: return(0);
564: }
568: void PopMessageLoopThread_Win32(PetscDraw popdraw)
569: {
570: PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
571: MSG msg;
572: HWND hWnd = NULL;
573: char PopClassName [MAX_LOADSTRING + 1];
574: RECT r;
575: int width,height;
576: WNDCLASSEX myclass;
577: LPVOID lpMsgBuf;
580: /* initialize window class parameters */
581: myclass.cbSize = sizeof(WNDCLASSEX);
582: myclass.style = CS_OWNDC;
583: myclass.lpfnWndProc = (WNDPROC)PetscWndProc;
584: myclass.cbClsExtra = 0;
585: myclass.cbWndExtra = 0;
586: myclass.hInstance = NULL;
587: myclass.hIcon = NULL;
588: myclass.hCursor = LoadCursor(NULL, IDC_ARROW);
589: myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
590: myclass.lpszMenuName = NULL;
591: myclass.lpszClassName = PopClassName;
592: myclass.hIconSm = NULL;
594: RegisterClassEx(&myclass);
596: SetRect(&r,0,0,450,450);
598: width = (r.right - r.left) / 3;
599: height = (r.bottom - r.top) / 3;
601: hWnd = CreateWindowEx(0,
602: PopClassName,
603: NULL,
604: WS_POPUPWINDOW | WS_CAPTION,
605: 0,0,
606: width,height,
607: NULL,
608: NULL,
609: hInst,
610: NULL);
611: pop->x = 0;
612: pop->y = 0;
613: pop->w = width;
614: pop->h = height;
616: if (!hWnd) {
617: lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
618: MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
619: LocalFree(lpMsgBuf);
620: exit(0);
621: }
622: pop->hWnd = hWnd;
623: /* display and update new popup window */
624: ShowWindow(pop->hWnd, SW_SHOWNORMAL);
625: UpdateWindow(pop->hWnd);
626: SetEvent(pop->hReadyEvent);
628: while (GetMessage(&msg, pop->hWnd, 0, 0)) {
629: TranslateMessage(&msg);
630: DispatchMessage(&msg);
631: }
632: PetscFunctionReturnVoid();
633: }
637: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
638: {
639: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
642: SendMessage(windraw->hWnd,WM_DESTROY,0,0);
643: PetscFree(draw->data);
644: return(0);
645: }
649: void MessageLoopThread_Win32(PetscDraw draw)
650: {
651: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
652: MSG msg;
653: HWND hWnd = NULL;
654: char classname[MAX_LOADSTRING + 1];
655: WNDCLASSEX wclass;
656: LPVOID lpMsgBuf;
659: /* initialize window class parameters */
660: wclass.cbSize = sizeof(WNDCLASSEX);
661: wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
662: wclass.lpfnWndProc = (WNDPROC)PetscWndProc;
663: wclass.cbClsExtra = 0;
664: wclass.cbWndExtra = 0;
665: wclass.hInstance = NULL;
666: wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
667: wclass.hCursor = LoadCursor(NULL,IDC_ARROW);
668: wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
669: wclass.lpszMenuName = NULL;
670: wclass.lpszClassName = classname;
671: wclass.hIconSm = NULL;
673: RegisterClassEx(&wclass);
676: hWnd = CreateWindowEx(0,
677: classname,
678: NULL,
679: WS_OVERLAPPEDWINDOW,
680: draw->x,
681: draw->y,
682: draw->w,
683: draw->h,
684: NULL,
685: NULL,
686: hInst,
687: NULL);
689: if (!hWnd) {
690: lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
691: MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
692: LocalFree(lpMsgBuf);
693: exit(0);
694: }
695: windraw->hWnd = hWnd;
696: /* display and update new window */
697: ShowWindow(hWnd,SW_SHOWNORMAL);
698: UpdateWindow(hWnd);
699: SetEvent(windraw->hReadyEvent);
701: while (GetMessage(&msg,hWnd, 0, 0)) {
702: TranslateMessage(&msg);
703: DispatchMessage(&msg);
704: }
705: PetscFunctionReturnVoid();
706: }
709: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
710: PetscDrawFlush_Win32,
711: PetscDrawLine_Win32,
712: PetscDrawLineSetWidth_Win32,
713: PetscDrawLineGetWidth_Win32,
714: PetscDrawPoint_Win32,
715: PetscDrawPointSetSize_Win32,
716: PetscDrawString_Win32,
717: PetscDrawStringVertical_Win32,
718: PetscDrawStringSetSize_Win32,
719: PetscDrawStringGetSize_Win32,
720: 0,
721: PetscDrawClear_Win32,
722: PetscDrawRectangle_Win32,
723: PetscDrawTriangle_Win32,
724: 0,
725: PetscDrawGetMouseButton_Win32,
726: PetscDrawPause_Win32,
727: 0,
728: 0,
729: PetscDrawGetPopup_Win32,
730: PetscDrawSetTitle_Win32,
731: PetscDrawCheckResizedWindow_Win32,
732: PetscDrawResizeWindow_Win32,
733: PetscDrawDestroy_Win32,
734: 0,
735: 0,
736: 0,
737: 0};
741: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
742: {
743: PetscErrorCode ierr;
744: PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
745: PetscBool flg = PETSC_TRUE;
748: PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);
749: if (flg) {
750: PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);
751: PetscDrawSetType(*popup,PETSC_DRAW_WIN32);
752: draw->popup = *popup;
753: } else {
754: *popup = NULL;
755: }
756: return(0);
757: }
760: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
761: {
762: PetscDraw_Win32 *windraw;
763: HANDLE hThread = NULL;
764: PetscErrorCode ierr;
765: WindowNode newnode;
768: PetscNew(&windraw);
769: draw->data = windraw;
771: /* the following is temporary fix for initializing a global datastructure */
772: if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
773: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
775: windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
776: /* makes call to MessageLoopThread to creat window and attach a thread */
777: CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
778: CloseHandle(hThread);
779: WaitForSingleObject(windraw->hReadyEvent,INFINITE);
780: CloseHandle(windraw->hReadyEvent);
781: WaitForSingleObject(g_hWindowListMutex,INFINITE);
783: PetscNew(&newnode);
784: newnode->MouseListHead = NULL;
785: newnode->MouseListTail = NULL;
786: newnode->wnext = WindowListHead;
787: newnode->wprev = NULL;
788: newnode->hWnd = windraw->hWnd;
789: if (WindowListHead) WindowListHead->wprev = newnode;
790: WindowListHead = newnode;
791: windraw->hdc = GetDC(windraw->hWnd);
793: windraw->stringheight = 10;
794: windraw->stringwidth = 6;
795: windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
796: windraw->pointdiameter = 1;
797: windraw->node = newnode;
799: windraw->x = draw->x;
800: windraw->y = draw->y;
801: windraw->w = newnode->bitwidth = draw->w;
802: windraw->h = newnode->bitheight = draw->h;
804: /* Create and initialize primary graphics buffer */
805: newnode->Buffer = CreateCompatibleDC(windraw->hdc);
806: newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
807: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
808: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
810: newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL);
811: newnode->DoubleBuffered = PETSC_FALSE;
813: ReleaseDC(windraw->hWnd,windraw->hdc);
814: ReleaseMutex(g_hWindowListMutex);
815: return(0);
816: }
819: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
820: PURPOSE: Processes messages for the main window.
821: WM_COMMAND - process the application menu
822: WM_PAINT - Paint the main window
823: WM_DESTROY - post a quit message and return */
827: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
828: {
829: int wmId, wmEvent;
832: switch (message) {
833: HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
834: HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
835: case WM_COMMAND:
836: wmId = LOWORD(wParam);
837: wmEvent = HIWORD(wParam);
838: /* Parse the menu selections:*/
839: switch (wmId) {
840: case IDM_EXIT:
841: DestroyWindow(hWnd);
842: break;
843: default:
844: return DefWindowProc(hWnd, message, wParam, lParam);
845: }
846: break;
847: case WM_LBUTTONUP:
848: MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
849: break;
850: case WM_RBUTTONUP:
851: MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
852: break;
853: case WM_MBUTTONUP:
854: MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
855: break;
856: default:
857: PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
858: }
859: return(0);
860: }
864: static void OnPaint_Win32(HWND hWnd)
865: {
866: PAINTSTRUCT ps;
867: HDC hdc;
868: WindowNode current = NULL;
871: InvalidateRect(hWnd,NULL,TRUE);
872: WaitForSingleObject(g_hWindowListMutex, INFINITE);
873: current = WindowListHead;
874: hdc = BeginPaint(hWnd, &ps);
876: while (current) {
877: if (current->hWnd == hWnd) {
878: /* flushes primary buffer to window */
879: BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
880: current->Buffer,0,0,SRCCOPY);
882: /* StretchBlt(hdc,0,0,w,h,
883: current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
884: break;
885: }
886: current = current->wnext;
887: }
888: EndPaint(hWnd, &ps);
889: ReleaseMutex(g_hWindowListMutex);
890: PetscFunctionReturnVoid();
891: }
895: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
896: {
897: /* Called by all three mouse button actions
898: Records needed mouse data in windows data structure */
899: WindowNode current = NULL;
900: MouseNode newnode;
901: POINT mousepos;
905: WaitForSingleObject(g_hWindowListMutex, INFINITE);
906: current = WindowListHead;
907: if (current->IsGetMouseOn == TRUE) {
909: SetEvent(current->event);
910: while (current) {
911: if (current->hWnd == hWnd) {
913: PetscNew(&newnode);
914: newnode->Button = button;
915: GetCursorPos(&mousepos);
916: newnode->user.x = mousepos.x;
917: newnode->user.y = mousepos.y;
918: ScreenToClient(hWnd,&mousepos);
919: newnode->phys.x = mousepos.x;
920: newnode->phys.y = mousepos.y;
921: if (!current->MouseListTail) {
922: current->MouseListHead = newnode;
923: current->MouseListTail = newnode;
924: } else {
925: current->MouseListTail->mnext = newnode;
926: current->MouseListTail = newnode;
927: }
928: newnode->mnext = NULL;
930: break;
931: }
932: current = current->wnext;
933: }
934: }
935: ReleaseMutex(g_hWindowListMutex);
936: return(0);
937: }
941: static void OnDestroy_Win32(HWND hWnd)
942: {
943: /* searches linked list of window data and frees corresponding memory */
944: WindowNode current;
947: WaitForSingleObject(g_hWindowListMutex, INFINITE);
948: current = WindowListHead;
950: SetEvent(current->event);
951: while (current) {
952: if (current->hWnd == hWnd) {
953: if (current->wprev) current->wprev->wnext = current->wnext;
954: else WindowListHead = current->wnext;
955: if (current->MouseListHead) deletemouselist_Win32(current);
956: else PetscFree(current);
957: break;
958: }
959: current = current->wnext;
960: }
961: ReleaseMutex(g_hWindowListMutex);
962: PostQuitMessage(0);
963: PetscFunctionReturnVoid();
964: }