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