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