Actual source code: win32draw.c
2: #include <petscsys.h>
3: #include <../src/sys/draw/drawimpl.h>
4: #include <../src/sys/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);
60:
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,
69: 0,0,
70: windraw->w,windraw->h,
71: windraw->node->Buffer,
72: 0,0,
73: SRCCOPY);
75: windraw->node->DoubleBuffered = PETSC_TRUE;
76: ReleaseDC(windraw->hWnd,hdc);
77: return(0);
78: }
82: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
83: {
84: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
85: HDC hdc = GetDC(windraw->hWnd);
86:
88: /* flush double buffer into primary buffer */
89: BitBlt(windraw->node->Buffer,
90: 0,0,
91: windraw->w,windraw->h,
92: windraw->node->DoubleBuffer,
93: 0,0,
94: SRCCOPY);
95: /* flush double buffer into window */
96: BitBlt(hdc,
97: 0,0,
98: windraw->w,windraw->h,
99: windraw->node->DoubleBuffer,
100: 0,0,
101: SRCCOPY);
102: ReleaseDC(windraw->hWnd,hdc);
103: return(0);
104: }
108: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
109: {
110: /* Called upon window close. Frees memory of linked list of stored mouse commands */
111: MouseNode node;
112:
113: while(deletelist->MouseListHead != NULL) {
114: node = deletelist->MouseListHead;
115: if(deletelist->MouseListHead->mnext != NULL) {
116: deletelist->MouseListHead = deletelist->MouseListHead->mnext;
117: }
118: PetscFree(node);
119: }
120: deletelist->MouseListHead = deletelist->MouseListTail = NULL;
121: if (deletelist->wprev != NULL) {
122: deletelist->wprev->wnext = deletelist->wnext;
123: }
124: if (deletelist->wnext != NULL) {
125: deletelist->wnext->wprev = deletelist->wprev;
126: }
127: PetscFree(deletelist);
128: return 0;
129: }
133: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
134: {
135: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
136: WindowNode current;
137: MouseNode node=0;
138:
140: /* Make sure no other code is using the linked list at this moment */
141: WaitForSingleObject(g_hWindowListMutex, INFINITE);
142: /* Look for the node that matches the window you are using */
143: current = WindowListHead;
144: while (current != NULL) {
145: if(current->hWnd == windraw->hWnd) {
146: current->IsGetMouseOn = TRUE;
147: break;
148: } else {
149: current = current->wnext;
150: }
151: }
152: /* If no actions have occured, wait for one */
153: node = current->MouseListHead;
154: if (!node) {
155: ReleaseMutex(g_hWindowListMutex);
156: WaitForSingleObject(current->event, INFINITE);
157: WaitForSingleObject(g_hWindowListMutex, INFINITE);
158: }
159: /* once we have the information, assign the pointers to it */
160: *button = current->MouseListHead->Button;
161: *x_user = current->MouseListHead->user.x;
162: *y_user = current->MouseListHead->user.y;
163: /* optional arguments */
164: if (x_phys) *x_phys = current->MouseListHead->phys.x;
165: if (y_phys) *y_phys = current->MouseListHead->phys.y;
166: /* remove set of information from sub linked-list, delete the node */
167: current->MouseListHead = current->MouseListHead->mnext;
168: if (!current->MouseListHead) {
169: ResetEvent(current->event);
170: current->MouseListTail = NULL;
171: }
172: if (node) PetscFree(node);
174: /* Release mutex so that other code can use
175: the linked list now that we are done with it */
176: ReleaseMutex(g_hWindowListMutex);
177: return(0);
178: }
182: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
183: {
185: PetscSleep(draw->pause);
186: return(0);
187: }
191: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
192: {
193: /* Maps single color value into the RGB colors in our tables */
194: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
195: windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
196: return 0;
197: }
201: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
202: {
203: /* Averages colors given at points of rectangle and sets color from color table
204: will be changed once the color gradient problem is worked out */
205: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
206: windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
207: ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
208: ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
209: return 0;
210: }
214: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
215: {
216: /* Averages colors given at points of rectangle and sets color from color table
217: will be changed once the color gradient problem is worked out */
218: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
219: windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
220: (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
221: (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
222: return 0;
223: }
227: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
228: {
229: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
230: HBRUSH hbrush;
231: RECT rect;
232: int x1,yone,x2,y2;
233: HDC hdc;
234:
236: x1 = XTRANS(draw,windraw,xl);
237: x2 = XTRANS(draw,windraw,xr);
238: yone = YTRANS(draw,windraw,yl);
239: y2 = YTRANS(draw,windraw,yr);
240: SetRect(&rect,x1,y2,x2,yone);
241: if (c1==c2 && c2==c3 && c3==c4) {
242: TranslateColor_Win32(draw,c1);
243: } else {
244: AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
245: }
246: hbrush = CreateSolidBrush(windraw->currentcolor);
247:
248: if(windraw->node->DoubleBuffered) {
249: hdc = windraw->node->DoubleBuffer;
250: } else {
251: hdc = windraw->node->Buffer;
252: }
253: FillRect(hdc,&rect,hbrush);
254: /* Forces a WM_PAINT message and erases background */
255: InvalidateRect(windraw->hWnd,NULL,TRUE);
256: UpdateWindow(windraw->hWnd);
257: return(0);
258: }
262: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
263: {
264: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
265: HPEN hpen;
266: int x1,yone,x2,y2;
267: HDC hdc;
268:
270: TranslateColor_Win32(draw,color);
271: x1 = XTRANS(draw,windraw,xl);x2 = XTRANS(draw,windraw,xr);
272: yone = YTRANS(draw,windraw,yl);y2 = YTRANS(draw,windraw,yr);
273: hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
274: if(windraw->node->DoubleBuffered) {
275: hdc = windraw->node->DoubleBuffer;
276: } else {
277: hdc = windraw->node->Buffer;
278: }
279: SelectPen(hdc,hpen);
280: MoveToEx(hdc,x1,yone,NULL);
281: LineTo(hdc,x2,y2);
282: /* Forces a WM_PAINT message and erases background */
283: InvalidateRect(windraw->hWnd,NULL,TRUE);
284: UpdateWindow(windraw->hWnd);
285: return(0);
286: }
290: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
291: {
292: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
293: int averagesize,finalwidth;
294: RECT rect;
295:
297: GetClientRect(windraw->hWnd,&rect);
298: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
299: finalwidth = (int)floor(averagesize*width);
300: if (finalwidth < 1) {
301: finalwidth = 1; /* minimum size PetscDrawLine can except */
302: }
303: windraw->linewidth = finalwidth;
304: return(0);
305: }
309: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
310: {
311: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
312:
314: *width = (PetscReal)windraw->linewidth;
315: return(0);
316: }
320: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
321: {
322: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
323: HBRUSH hbrush;
324: HRGN hrgn;
325: int radius;
326: int x1,yone;
327: HDC hdc;
328:
330: TranslateColor_Win32(draw,color);
331: x1 = XTRANS(draw,windraw,x);
332: yone = YTRANS(draw,windraw,y);
333: hbrush = CreateSolidBrush(windraw->currentcolor);
334: if(windraw->node->DoubleBuffered) {
335: hdc = windraw->node->DoubleBuffer;
336: } else {
337: hdc = windraw->node->Buffer;
338: }
339: /* desired size is one logical pixel so just turn it on */
340: if (windraw->pointdiameter == 1) {
341: SetPixelV(hdc,x1,yone,windraw->currentcolor);
342: } else {
343: /* draw point around position determined */
344: radius = windraw->pointdiameter/2; /* integer division */
345: hrgn = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
346: FillRgn(hdc,hrgn,hbrush);
347: }
348: /* Forces a WM_PAINT and erases background */
349: InvalidateRect(windraw->hWnd,NULL,TRUE);
350: UpdateWindow(windraw->hWnd);
351: return(0);
352: }
356: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
357: {
358: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
359: int averagesize,diameter;
360: RECT rect;
361:
363: GetClientRect(windraw->hWnd,&rect);
364: averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
365: diameter = (int)floor(averagesize*width);
366: if (diameter < 1) diameter = 1;
367: windraw->pointdiameter = diameter;
368: return(0);
369: }
373: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
374: {
375: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
376: RECT r;
377: HFONT hfont;
378: LOGFONT logfont;
379: int x1,yone;
380: HDC hdc;
381:
383: x1 = XTRANS(draw,windraw,x);
384: yone = YTRANS(draw,windraw,y);
385: r.bottom = yone;
386: r.left = x1;
387: r.right = x1 + 1;
388: r.top = yone + 1;
389: logfont.lfHeight = windraw->stringheight;
390: logfont.lfWidth = windraw->stringwidth;
391: logfont.lfEscapement = 0;
392: logfont.lfOrientation = 0;
393: logfont.lfCharSet = 0;
394: logfont.lfClipPrecision = 0;
395: logfont.lfItalic = 0;
396: logfont.lfOutPrecision = 0;
397: logfont.lfPitchAndFamily = DEFAULT_PITCH;
398: logfont.lfQuality = DEFAULT_QUALITY;
399: logfont.lfStrikeOut = 0;
400: logfont.lfUnderline = 0;
401: logfont.lfWeight = FW_NORMAL;
402: hfont = CreateFontIndirect(&logfont);
403: TranslateColor_Win32(draw,color);
404: if(windraw->node->DoubleBuffered) {
405: hdc = windraw->node->DoubleBuffer;
406: } else {
407: hdc = windraw->node->Buffer;
408: }
409: SelectFont(hdc,hfont);
410: SetTextColor(hdc,windraw->currentcolor);
411: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
412: DeleteObject(hfont);
413: /* Forces a WM_PAINT message and erases background */
414: InvalidateRect(windraw->hWnd,NULL,TRUE);
415: UpdateWindow(windraw->hWnd);
416: return(0);
417: }
421: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
422: {
423: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
424: RECT r;
425: HFONT hfont;
426: LOGFONT logfont;
427: int x1,yone;
428: HDC hdc;
429:
431: x1 = XTRANS(draw,windraw,x);
432: yone = YTRANS(draw,windraw,y);
433: r.left = x1;
434: r.bottom = yone + 30;
435: r.right = x1 + 1;
436: r.top = yone - 30;
437: logfont.lfEscapement = 2700; /* Causes verticle text drawing */
438: logfont.lfHeight = windraw->stringheight;
439: logfont.lfWidth = windraw->stringwidth;
440: logfont.lfOrientation = 0;
441: logfont.lfCharSet = DEFAULT_CHARSET;
442: logfont.lfClipPrecision = 0;
443: logfont.lfItalic = 0;
444: logfont.lfOutPrecision = 0;
445: logfont.lfPitchAndFamily = DEFAULT_PITCH;
446: logfont.lfQuality = DEFAULT_QUALITY;
447: logfont.lfStrikeOut = 0;
448: logfont.lfUnderline = 0;
449: logfont.lfWeight = FW_NORMAL;
450: hfont = CreateFontIndirect(&logfont);
451: TranslateColor_Win32(draw,color);
452: if(windraw->node->DoubleBuffered) {
453: hdc = windraw->node->DoubleBuffer;
454: } else {
455: hdc = windraw->node->Buffer;
456: }
457: SelectFont(hdc,hfont);
458: SetTextColor(hdc,windraw->currentcolor);
459: DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE );
460: DeleteObject(hfont);
461: /* Forces a WM_PAINT message and erases background */
462: InvalidateRect(windraw->hWnd,NULL,TRUE);
463: UpdateWindow(windraw->hWnd);
464: return(0);
465: }
469: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
470: {
471: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
472: int w,h;
473:
475: w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
476: h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
477: if (h < 1) h = 1;
478: if (w < 1) w = 1;
479: windraw->stringheight = h;
480: windraw->stringwidth = w;
481: return(0);
482: }
485: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
486: {
487: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
488: double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
489: double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
490:
492: *height = (double)windraw->stringheight*scaleY;
493: *width = (double)windraw->stringwidth*scaleX;
494: return(0);
495: }
499: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
500: {
501: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
502: RECT r;
503:
505: GetWindowRect(windraw->hWnd,&r);
506: MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
507: /* set all variable dealing with window dimensions */
508: windraw->node->bitheight = windraw->h = draw->h = h;
509: windraw->node->bitwidth = windraw->w = draw->w = w;
510: /* set up graphic buffers with the new size of window */
511: SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
512: if(windraw->node->DoubleBuffered) {
513: SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
514: }
515: windraw->haveresized = PETSC_TRUE;
516: return(0);
517: }
521: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
522: {
523: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
524:
526: if (windraw->haveresized == 1) {
527: PetscFunctionReturn(1);
528: } else {
529: return(0);
530: }
531:
532: }
536: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
537: {
538: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
539:
541: SetWindowText(windraw->hWnd,title);
542: return(0);
543: }
547: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
548: {
549: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
550:
552: /* clear primary buffer */
553: ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
554: /* if exists clear secondary buffer */
555: if(windraw->node->DoubleBuffered) {
556: ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
557: }
558: /* force WM_PAINT message so cleared buffer will show */
559: InvalidateRect(windraw->hWnd,NULL,TRUE);
560: UpdateWindow(windraw->hWnd);
561: return(0);
562: }
566: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
567: PetscReal x3,PetscReal y3,int c1,int c2,int c3)
568: {
569: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
570: HBRUSH hbrush;
571: HPEN hpen;
572: int p1x,p1y,p2x,p2y,p3x,p3y;
573: HDC bit;
574:
576: AverageColorTriangle_Win32(draw,c1,c2,c3);
577: hbrush = CreateSolidBrush(windraw->currentcolor);
578: hpen = CreatePen(PS_SOLID,0,windraw->currentcolor);
579: p1x = XTRANS(draw,windraw,x1);
580: p2x = XTRANS(draw,windraw,x2);
581: p3x = XTRANS(draw,windraw,x3);
582: p1y = YTRANS(draw,windraw,yone);
583: p2y = YTRANS(draw,windraw,y2);
584: p3y = YTRANS(draw,windraw,y3);
585:
586: if(windraw->node->DoubleBuffered) {
587: bit = windraw->node->DoubleBuffer;
588: } else {
589: bit = windraw->node->Buffer;
590: }
591: BeginPath(bit);
592: MoveToEx(bit,p1x,p1y,NULL);
593: LineTo(bit,p2x,p2y);
594: LineTo(bit,p3x,p3y);
595: LineTo(bit,p1x,p1y);
596: EndPath(bit);
597: SelectPen(bit,hpen);
598: SelectBrush(bit,hbrush);
599: StrokeAndFillPath(bit);
600: /* Forces a WM_PAINT message and erases background */
601: InvalidateRect(windraw->hWnd,NULL,TRUE);
602: UpdateWindow(windraw->hWnd);
603: return(0);
604: }
608: void PopMessageLoopThread_Win32(PetscDraw popdraw)
609: {
610: PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
611: MSG msg;
612: HWND hWnd = NULL;
613: char PopClassName [MAX_LOADSTRING + 1];
614: RECT r;
615: int width,height;
616: WNDCLASSEX myclass;
617: LPVOID lpMsgBuf;
618:
620: /* initialize window class parameters */
621: myclass.cbSize = sizeof(WNDCLASSEX);
622: myclass.style = CS_OWNDC;
623: myclass.lpfnWndProc = (WNDPROC)PetscWndProc;
624: myclass.cbClsExtra = 0;
625: myclass.cbWndExtra = 0;
626: myclass.hInstance = NULL;
627: myclass.hIcon = NULL;
628: myclass.hCursor = LoadCursor(NULL, IDC_ARROW);
629: myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
630: myclass.lpszMenuName = NULL;
631: myclass.lpszClassName = PopClassName;
632: myclass.hIconSm = NULL;
633:
634: RegisterClassEx(&myclass);
635:
636: SetRect(&r,0,0,450,450);
637:
638: width = (r.right - r.left) / 3;
639: height = (r.bottom - r.top) / 3;
640:
641: hWnd = CreateWindowEx(0,
642: PopClassName,
643: NULL,
644: WS_POPUPWINDOW | WS_CAPTION,
645: 0,0,
646: width,height,
647: NULL,
648: NULL,
649: hInst,
650: NULL);
651: pop->x = 0;
652: pop->y = 0;
653: pop->w = width;
654: pop->h = height;
655:
656: if(!hWnd) {
657: lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
658: MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
659: LocalFree( lpMsgBuf );
660: exit(0);
661: }
662: pop->hWnd = hWnd;
663: /* display and update new popup window */
664: ShowWindow(pop->hWnd, SW_SHOWNORMAL);
665: UpdateWindow(pop->hWnd);
666: SetEvent(pop->hReadyEvent);
667:
668: while (GetMessage(&msg, pop->hWnd, 0, 0)) {
669: TranslateMessage(&msg);
670: DispatchMessage(&msg);
671: }
672: PetscFunctionReturnVoid();
673: }
677: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
678: {
679: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
680:
682: SendMessage(windraw->hWnd,WM_DESTROY,0,0);
683: PetscFree(windraw);
684: return(0);
685: }
689: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
690: {
691: /* Multi Processor is not implemeted yet */
693: PetscDrawFlush_Win32(draw);
694: return(0);
695: }
699: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
700: {
701: /* Multi Processor is not implemeted yet */
703: PetscDrawClear_Win32(draw);
704: return(0);
705: }
709: void MessageLoopThread_Win32(PetscDraw draw)
710: {
711: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
712: MSG msg;
713: HWND hWnd = NULL;
714: char classname[MAX_LOADSTRING + 1];
715: WNDCLASSEX wclass;
716: LPVOID lpMsgBuf;
717:
719: /* initialize window class parameters */
720: wclass.cbSize = sizeof(WNDCLASSEX);
721: wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
722: wclass.lpfnWndProc = (WNDPROC)PetscWndProc;
723: wclass.cbClsExtra = 0;
724: wclass.cbWndExtra = 0;
725: wclass.hInstance = NULL;
726: wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
727: wclass.hCursor = LoadCursor(NULL,IDC_ARROW);
728: wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
729: wclass.lpszMenuName = NULL;
730: wclass.lpszClassName = classname;
731: wclass.hIconSm = NULL;
732:
733: RegisterClassEx(&wclass);
734:
735:
736: hWnd = CreateWindowEx(0,
737: classname,
738: NULL,
739: WS_OVERLAPPEDWINDOW,
740: draw->x,
741: draw->y,
742: draw->w,
743: draw->h,
744: NULL,
745: NULL,
746: hInst,
747: NULL);
748:
749: if (!hWnd) {
750: lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
751: MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
752: LocalFree( lpMsgBuf );
753: exit(0);
754: }
755: windraw->hWnd = hWnd;
756: /* display and update new window */
757: ShowWindow(hWnd,SW_SHOWNORMAL);
758: UpdateWindow(hWnd);
759: SetEvent(windraw->hReadyEvent);
760:
761: while (GetMessage(&msg,hWnd, 0, 0)) {
762: TranslateMessage(&msg);
763: DispatchMessage(&msg);
764: }
765: PetscFunctionReturnVoid();
766: }
769: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
770: PetscDrawFlush_Win32,
771: PetscDrawLine_Win32,
772: PetscDrawLineSetWidth_Win32,
773: PetscDrawLineGetWidth_Win32,
774: PetscDrawPoint_Win32,
775: PetscDrawPointSetSize_Win32,
776: PetscDrawString_Win32,
777: PetscDrawStringVertical_Win32,
778: PetscDrawStringSetSize_Win32,
779: PetscDrawStringGetSize_Win32,
780: 0,
781: PetscDrawClear_Win32,
782: PetscDrawSynchronizedFlush_Win32,
783: PetscDrawRectangle_Win32,
784: PetscDrawTriangle_Win32,
785: 0,
786: PetscDrawGetMouseButton_Win32,
787: PetscDrawPause_Win32,
788: PetscDrawSynchronizedClear_Win32,
789: 0,
790: 0,
791: PetscDrawGetPopup_Win32,
792: PetscDrawSetTitle_Win32,
793: PetscDrawCheckResizedWindow_Win32,
794: PetscDrawResizeWindow_Win32,
795: PetscDrawDestroy_Win32,
796: 0,
797: 0,
798: 0,
799: 0};
803: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
804: {
805: PetscDraw_Win32 *pop;
806: HANDLE hThread = NULL;
807: WindowNode newnode;
809:
811: PetscNew(PetscDraw_Win32,&pop);
812: (*popdraw)->data = pop;
813:
814: /* the following is temporary fix for initializing a global datastructure */
815: if(!g_hWindowListMutex) {
816: g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
817: }
818: PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
819:
820: pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
821: CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
822: CloseHandle(hThread);
823: WaitForSingleObject(pop->hReadyEvent, INFINITE);
824: CloseHandle(pop->hReadyEvent);
825: WaitForSingleObject(g_hWindowListMutex, INFINITE);
826:
827: draw->popup = (*popdraw);
828: PetscNew(struct _p_WindowNode,&newnode);
829: newnode->MouseListHead = NULL;
830: newnode->MouseListTail = NULL;
831: newnode->wnext = WindowListHead;
832: newnode->wprev = NULL;
833: newnode->hWnd = pop->hWnd;
834: if(WindowListHead != NULL) {
835: WindowListHead->wprev = newnode;
836: }
837: WindowListHead = newnode;
838: pop->hdc = GetDC(pop->hWnd);
839:
840: pop->stringheight = 10;
841: pop->stringwidth = 6;
842: pop->linewidth = 1; /* default pixel sizes of graphics until user changes them */
843: pop->pointdiameter = 1;
844: pop->node = newnode;
845:
846: newnode->bitwidth = pop->w;
847: newnode->bitheight = pop->h;
848:
849: /* Create and initialize primary graphics buffer */
850: newnode->Buffer = CreateCompatibleDC(pop->hdc);
851: newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
852: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
853: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
854:
855:
856: newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL);
857: newnode->DoubleBuffered = PETSC_FALSE;
858:
859: ReleaseDC(pop->hWnd,pop->hdc);
860: ReleaseMutex(g_hWindowListMutex);
861: return(0);
862: }
867: PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
868: {
869: PetscDraw_Win32 *windraw;
870: HANDLE hThread = NULL;
872: WindowNode newnode;
873:
875: PetscNew(PetscDraw_Win32,&windraw);
876: draw->data = windraw;
877:
878: /* the following is temporary fix for initializing a global datastructure */
879: if(!g_hWindowListMutex) {
880: g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
881: }
882: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
883:
884: windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
885: /* makes call to MessageLoopThread to creat window and attach a thread */
886: CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
887: CloseHandle(hThread);
888: WaitForSingleObject(windraw->hReadyEvent,INFINITE);
889: CloseHandle(windraw->hReadyEvent);
890: WaitForSingleObject(g_hWindowListMutex,INFINITE);
891:
892: PetscNew(struct _p_WindowNode,&newnode);
893: newnode->MouseListHead = NULL;
894: newnode->MouseListTail = NULL;
895: newnode->wnext = WindowListHead;
896: newnode->wprev = NULL;
897: newnode->hWnd = windraw->hWnd;
898: if(WindowListHead != NULL) {
899: WindowListHead->wprev = newnode;
900: }
901: WindowListHead = newnode;
902: windraw->hdc = GetDC(windraw->hWnd);
903:
904: windraw->stringheight = 10;
905: windraw->stringwidth = 6;
906: windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
907: windraw->pointdiameter = 1;
908: windraw->node = newnode;
909:
910: windraw->x = draw->x;
911: windraw->y = draw->y;
912: windraw->w = newnode->bitwidth = draw->w;
913: windraw->h = newnode->bitheight = draw->h;
914:
915: /* Create and initialize primary graphics buffer */
916: newnode->Buffer = CreateCompatibleDC(windraw->hdc);
917: newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
918: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
919: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
920:
921: newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL);
922: newnode->DoubleBuffered = PETSC_FALSE;
923:
924: ReleaseDC(windraw->hWnd,windraw->hdc);
925: ReleaseMutex(g_hWindowListMutex);
926: return(0);
927: }
931: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
932: PURPOSE: Processes messages for the main window.
933: WM_COMMAND - process the application menu
934: WM_PAINT - Paint the main window
935: WM_DESTROY - post a quit message and return */
939: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
940: {
941: int wmId, wmEvent;
942:
944: switch (message) {
945: HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
946: HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
947: case WM_COMMAND:
948: wmId = LOWORD(wParam);
949: wmEvent = HIWORD(wParam);
950: /* Parse the menu selections:*/
951: switch (wmId) {
952: case IDM_EXIT:
953: DestroyWindow(hWnd);
954: break;
955: default:
956: return DefWindowProc(hWnd, message, wParam, lParam);
957: }
958: break;
959: case WM_LBUTTONUP:
960: MouseRecord_Win32(hWnd,BUTTON_LEFT);
961: break;
962: case WM_RBUTTONUP:
963: MouseRecord_Win32(hWnd,BUTTON_RIGHT);
964: break;
965: case WM_MBUTTONUP:
966: MouseRecord_Win32(hWnd,BUTTON_CENTER);
967: break;
968: default:
969: PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
970: }
971: return(0);
972: }
976: static void OnPaint_Win32(HWND hWnd)
977: {
978: PAINTSTRUCT ps;
979: HDC hdc;
980: WindowNode current = NULL;
983: InvalidateRect(hWnd,NULL,TRUE);
984: WaitForSingleObject(g_hWindowListMutex, INFINITE);
985: current = WindowListHead;
986: hdc = BeginPaint(hWnd, &ps);
987:
988: while(current != NULL) {
989: if (current->hWnd == hWnd) {
990: /* flushes primary buffer to window */
991: BitBlt(hdc,
992: 0,0,
993: GetDeviceCaps(hdc,HORZRES),
994: GetDeviceCaps(hdc,VERTRES),
995: current->Buffer,
996: 0,0,
997: SRCCOPY);
998:
999: /* StretchBlt(hdc,
1000: 0,0,
1001: w,h,
1002: current->Buffer,
1003: 0,0,
1004: current->bitwidth,
1005: current->bitheight,
1006: SRCCOPY); */
1007: break;
1008: }
1009: current = current->wnext;
1010: }
1011: EndPaint(hWnd, &ps);
1012: ReleaseMutex(g_hWindowListMutex);
1013: PetscFunctionReturnVoid();
1014: }
1018: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
1019: {
1020: /* Called by all three mouse button actions
1021: Records needed mouse data in windows data structure */
1022: WindowNode current = NULL;
1023: MouseNode newnode;
1024: POINT mousepos;
1026:
1028: WaitForSingleObject(g_hWindowListMutex, INFINITE);
1029: current = WindowListHead;
1030: if(current->IsGetMouseOn == TRUE) {
1031:
1032: SetEvent(current->event);
1033: while (current != NULL) {
1034: if(current->hWnd == hWnd) {
1035:
1036: PetscNew(struct _p_MouseNode,&newnode);
1037: newnode->Button = button;
1038: GetCursorPos(&mousepos);
1039: newnode->user.x = mousepos.x;
1040: newnode->user.y = mousepos.y;
1041: ScreenToClient(hWnd,&mousepos);
1042: newnode->phys.x = mousepos.x;
1043: newnode->phys.y = mousepos.y;
1044: if (!current->MouseListTail) {
1045: current->MouseListHead = newnode;
1046: current->MouseListTail = newnode;
1047: } else {
1048: current->MouseListTail->mnext = newnode;
1049: current->MouseListTail = newnode;
1050: }
1051: newnode->mnext = NULL;
1052:
1053: break;
1054: }
1055: current = current->wnext;
1056: }
1057: }
1058: ReleaseMutex(g_hWindowListMutex);
1059: return(0);
1060: }
1064: static void OnDestroy_Win32(HWND hWnd)
1065: {
1066: /* searches linked list of window data and frees corresponding memory */
1067: WindowNode current;
1068:
1070: WaitForSingleObject(g_hWindowListMutex, INFINITE);
1071: current = WindowListHead;
1072:
1073: SetEvent(current->event);
1074: while (current != NULL) {
1075: if(current->hWnd == hWnd) {
1076: if(current->wprev != NULL) {
1077: current->wprev->wnext = current->wnext;
1078: } else {
1079: WindowListHead = current->wnext;
1080: }
1081: if(current->MouseListHead) {
1082: deletemouselist_Win32(current);
1083: } else {
1084: PetscFree(current);
1085: }
1086: break;
1087: }
1088: current = current->wnext;
1089: }
1090: ReleaseMutex(g_hWindowListMutex);
1091: PostQuitMessage(0);
1092: PetscFunctionReturnVoid();
1093: }