Actual source code: win32draw.c
petsc-3.6.1 2015-08-06
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 != NULL) {
102: node = deletelist->MouseListHead;
103: if (deletelist->MouseListHead->mnext != NULL) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
104: PetscFree(node);
105: }
106: deletelist->MouseListHead = deletelist->MouseListTail = NULL;
107: if (deletelist->wprev != NULL) deletelist->wprev->wnext = deletelist->wnext;
108: if (deletelist->wnext != NULL) 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 != NULL) {
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: *height = (double)windraw->stringheight*scaleY;
462: *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: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
650: {
651: /* Multi Processor is not implemeted yet */
653: PetscDrawFlush_Win32(draw);
654: return(0);
655: }
659: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
660: {
661: /* Multi Processor is not implemeted yet */
663: PetscDrawClear_Win32(draw);
664: return(0);
665: }
669: void MessageLoopThread_Win32(PetscDraw draw)
670: {
671: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
672: MSG msg;
673: HWND hWnd = NULL;
674: char classname[MAX_LOADSTRING + 1];
675: WNDCLASSEX wclass;
676: LPVOID lpMsgBuf;
679: /* initialize window class parameters */
680: wclass.cbSize = sizeof(WNDCLASSEX);
681: wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
682: wclass.lpfnWndProc = (WNDPROC)PetscWndProc;
683: wclass.cbClsExtra = 0;
684: wclass.cbWndExtra = 0;
685: wclass.hInstance = NULL;
686: wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
687: wclass.hCursor = LoadCursor(NULL,IDC_ARROW);
688: wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
689: wclass.lpszMenuName = NULL;
690: wclass.lpszClassName = classname;
691: wclass.hIconSm = NULL;
693: RegisterClassEx(&wclass);
696: hWnd = CreateWindowEx(0,
697: classname,
698: NULL,
699: WS_OVERLAPPEDWINDOW,
700: draw->x,
701: draw->y,
702: draw->w,
703: draw->h,
704: NULL,
705: NULL,
706: hInst,
707: NULL);
709: if (!hWnd) {
710: lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
711: MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
712: LocalFree(lpMsgBuf);
713: exit(0);
714: }
715: windraw->hWnd = hWnd;
716: /* display and update new window */
717: ShowWindow(hWnd,SW_SHOWNORMAL);
718: UpdateWindow(hWnd);
719: SetEvent(windraw->hReadyEvent);
721: while (GetMessage(&msg,hWnd, 0, 0)) {
722: TranslateMessage(&msg);
723: DispatchMessage(&msg);
724: }
725: PetscFunctionReturnVoid();
726: }
729: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
730: PetscDrawFlush_Win32,
731: PetscDrawLine_Win32,
732: PetscDrawLineSetWidth_Win32,
733: PetscDrawLineGetWidth_Win32,
734: PetscDrawPoint_Win32,
735: PetscDrawPointSetSize_Win32,
736: PetscDrawString_Win32,
737: PetscDrawStringVertical_Win32,
738: PetscDrawStringSetSize_Win32,
739: PetscDrawStringGetSize_Win32,
740: 0,
741: PetscDrawClear_Win32,
742: PetscDrawSynchronizedFlush_Win32,
743: PetscDrawRectangle_Win32,
744: PetscDrawTriangle_Win32,
745: 0,
746: PetscDrawGetMouseButton_Win32,
747: PetscDrawPause_Win32,
748: PetscDrawSynchronizedClear_Win32,
749: 0,
750: 0,
751: PetscDrawGetPopup_Win32,
752: PetscDrawSetTitle_Win32,
753: PetscDrawCheckResizedWindow_Win32,
754: PetscDrawResizeWindow_Win32,
755: PetscDrawDestroy_Win32,
756: 0,
757: 0,
758: 0,
759: 0};
763: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
764: {
765: PetscDraw_Win32 *pop;
766: HANDLE hThread = NULL;
767: WindowNode newnode;
768: PetscErrorCode ierr;
771: PetscNew(&pop);
773: (*popdraw)->data = pop;
775: /* the following is temporary fix for initializing a global datastructure */
776: if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
777: PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
779: pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
780: CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(LPDWORD)hThread);
781: CloseHandle(hThread);
782: WaitForSingleObject(pop->hReadyEvent, INFINITE);
783: CloseHandle(pop->hReadyEvent);
784: WaitForSingleObject(g_hWindowListMutex, INFINITE);
786: draw->popup = (*popdraw);
787: PetscNew(&newnode);
788: newnode->MouseListHead = NULL;
789: newnode->MouseListTail = NULL;
790: newnode->wnext = WindowListHead;
791: newnode->wprev = NULL;
792: newnode->hWnd = pop->hWnd;
793: if (WindowListHead != NULL) WindowListHead->wprev = newnode;
794: WindowListHead = newnode;
795: pop->hdc = GetDC(pop->hWnd);
797: pop->stringheight = 10;
798: pop->stringwidth = 6;
799: pop->linewidth = 1; /* default pixel sizes of graphics until user changes them */
800: pop->pointdiameter = 1;
801: pop->node = newnode;
803: newnode->bitwidth = pop->w;
804: newnode->bitheight = pop->h;
806: /* Create and initialize primary graphics buffer */
807: newnode->Buffer = CreateCompatibleDC(pop->hdc);
808: newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
809: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
810: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
813: newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL);
814: newnode->DoubleBuffered = PETSC_FALSE;
816: ReleaseDC(pop->hWnd,pop->hdc);
817: ReleaseMutex(g_hWindowListMutex);
818: return(0);
819: }
823: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
824: {
825: PetscDraw_Win32 *windraw;
826: HANDLE hThread = NULL;
827: PetscErrorCode ierr;
828: WindowNode newnode;
831: PetscNew(&windraw);
832: draw->data = windraw;
834: /* the following is temporary fix for initializing a global datastructure */
835: if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
836: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
838: windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
839: /* makes call to MessageLoopThread to creat window and attach a thread */
840: CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
841: CloseHandle(hThread);
842: WaitForSingleObject(windraw->hReadyEvent,INFINITE);
843: CloseHandle(windraw->hReadyEvent);
844: WaitForSingleObject(g_hWindowListMutex,INFINITE);
846: PetscNew(&newnode);
847: newnode->MouseListHead = NULL;
848: newnode->MouseListTail = NULL;
849: newnode->wnext = WindowListHead;
850: newnode->wprev = NULL;
851: newnode->hWnd = windraw->hWnd;
852: if (WindowListHead != NULL) WindowListHead->wprev = newnode;
853: WindowListHead = newnode;
854: windraw->hdc = GetDC(windraw->hWnd);
856: windraw->stringheight = 10;
857: windraw->stringwidth = 6;
858: windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
859: windraw->pointdiameter = 1;
860: windraw->node = newnode;
862: windraw->x = draw->x;
863: windraw->y = draw->y;
864: windraw->w = newnode->bitwidth = draw->w;
865: windraw->h = newnode->bitheight = draw->h;
867: /* Create and initialize primary graphics buffer */
868: newnode->Buffer = CreateCompatibleDC(windraw->hdc);
869: newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
870: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
871: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
873: newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL);
874: newnode->DoubleBuffered = PETSC_FALSE;
876: ReleaseDC(windraw->hWnd,windraw->hdc);
877: ReleaseMutex(g_hWindowListMutex);
878: return(0);
879: }
882: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
883: PURPOSE: Processes messages for the main window.
884: WM_COMMAND - process the application menu
885: WM_PAINT - Paint the main window
886: WM_DESTROY - post a quit message and return */
890: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
891: {
892: int wmId, wmEvent;
895: switch (message) {
896: HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
897: HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
898: case WM_COMMAND:
899: wmId = LOWORD(wParam);
900: wmEvent = HIWORD(wParam);
901: /* Parse the menu selections:*/
902: switch (wmId) {
903: case IDM_EXIT:
904: DestroyWindow(hWnd);
905: break;
906: default:
907: return DefWindowProc(hWnd, message, wParam, lParam);
908: }
909: break;
910: case WM_LBUTTONUP:
911: MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
912: break;
913: case WM_RBUTTONUP:
914: MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
915: break;
916: case WM_MBUTTONUP:
917: MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
918: break;
919: default:
920: PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
921: }
922: return(0);
923: }
927: static void OnPaint_Win32(HWND hWnd)
928: {
929: PAINTSTRUCT ps;
930: HDC hdc;
931: WindowNode current = NULL;
934: InvalidateRect(hWnd,NULL,TRUE);
935: WaitForSingleObject(g_hWindowListMutex, INFINITE);
936: current = WindowListHead;
937: hdc = BeginPaint(hWnd, &ps);
939: while (current != NULL) {
940: if (current->hWnd == hWnd) {
941: /* flushes primary buffer to window */
942: BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
943: current->Buffer,0,0,SRCCOPY);
945: /* StretchBlt(hdc,0,0,w,h,
946: current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
947: break;
948: }
949: current = current->wnext;
950: }
951: EndPaint(hWnd, &ps);
952: ReleaseMutex(g_hWindowListMutex);
953: PetscFunctionReturnVoid();
954: }
958: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
959: {
960: /* Called by all three mouse button actions
961: Records needed mouse data in windows data structure */
962: WindowNode current = NULL;
963: MouseNode newnode;
964: POINT mousepos;
968: WaitForSingleObject(g_hWindowListMutex, INFINITE);
969: current = WindowListHead;
970: if (current->IsGetMouseOn == TRUE) {
972: SetEvent(current->event);
973: while (current != NULL) {
974: if (current->hWnd == hWnd) {
976: PetscNew(&newnode);
977: newnode->Button = button;
978: GetCursorPos(&mousepos);
979: newnode->user.x = mousepos.x;
980: newnode->user.y = mousepos.y;
981: ScreenToClient(hWnd,&mousepos);
982: newnode->phys.x = mousepos.x;
983: newnode->phys.y = mousepos.y;
984: if (!current->MouseListTail) {
985: current->MouseListHead = newnode;
986: current->MouseListTail = newnode;
987: } else {
988: current->MouseListTail->mnext = newnode;
989: current->MouseListTail = newnode;
990: }
991: newnode->mnext = NULL;
993: break;
994: }
995: current = current->wnext;
996: }
997: }
998: ReleaseMutex(g_hWindowListMutex);
999: return(0);
1000: }
1004: static void OnDestroy_Win32(HWND hWnd)
1005: {
1006: /* searches linked list of window data and frees corresponding memory */
1007: WindowNode current;
1010: WaitForSingleObject(g_hWindowListMutex, INFINITE);
1011: current = WindowListHead;
1013: SetEvent(current->event);
1014: while (current != NULL) {
1015: if (current->hWnd == hWnd) {
1016: if (current->wprev != NULL) current->wprev->wnext = current->wnext;
1017: else WindowListHead = current->wnext;
1018: if (current->MouseListHead) deletemouselist_Win32(current);
1019: else PetscFree(current);
1020: break;
1021: }
1022: current = current->wnext;
1023: }
1024: ReleaseMutex(g_hWindowListMutex);
1025: PostQuitMessage(0);
1026: PetscFunctionReturnVoid();
1027: }