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