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 *);
47: #undef __FUNCT__
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: }
72: #undef __FUNCT__
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: }
98: #undef __FUNCT__
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: }
123: #undef __FUNCT__
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: }
172: #undef __FUNCT__
174: static int PetscDrawPause_Win32(PetscDraw draw)
175: {
177: PetscSleep(draw->pause);
178: return(0);
179: }
181: #undef __FUNCT__
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: }
190: #undef __FUNCT__
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: }
202: #undef __FUNCT__
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: }
214: #undef __FUNCT__
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: }
248: #undef __FUNCT__
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: }
276: #undef __FUNCT__
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: }
295: #undef __FUNCT__
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: }
305: #undef __FUNCT__
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: }
341: #undef __FUNCT__
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: }
357: #undef __FUNCT__
359: static int PetscDrawString_Win32(PetscDraw draw,double x,double y,int color,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: }
404: #undef __FUNCT__
406: static int PetscDrawStringVertical_Win32(PetscDraw draw,double x,double y,int color,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: }
451: #undef __FUNCT__
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: }
467: #undef __FUNCT__
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: }
479: #undef __FUNCT__
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: }
501: #undef __FUNCT__
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: }
516: #undef __FUNCT__
518: static int PetscDrawSetTitle_Win32(PetscDraw draw, char *title)
519: {
520: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
521:
523: draw->title = title;
524: SetWindowText(windraw->hWnd,title);
525: return(0);
526: }
528: #undef __FUNCT__
530: static int PetscDrawClear_Win32(PetscDraw draw)
531: {
532: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
533:
535: /* clear primary buffer */
536: ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
537: /* if exists clear secondary buffer */
538: if(windraw->node->DoubleBuffered) {
539: ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
540: }
541: /* force WM_PAINT message so cleared buffer will show */
542: InvalidateRect(windraw->hWnd,NULL,TRUE);
543: UpdateWindow(windraw->hWnd);
544: return(0);
545: }
547: #undef __FUNCT__
549: static int PetscDrawTriangle_Win32(PetscDraw draw,double x1,double y1,double x2,double y2,double x3,double y3,
550: int c1,int c2,int c3)
551: {
552: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
553: HBRUSH hbrush;
554: HPEN hpen;
555: int p1x,p1y,p2x,p2y,p3x,p3y;
556: HDC bit;
557:
559: AverageColorTriangle_Win32(draw,c1,c2,c3);
560: hbrush = CreateSolidBrush(windraw->currentcolor);
561: hpen = CreatePen(PS_SOLID,0,windraw->currentcolor);
562: p1x = XTRANS(draw,windraw,x1);
563: p2x = XTRANS(draw,windraw,x2);
564: p3x = XTRANS(draw,windraw,x3);
565: p1y = YTRANS(draw,windraw,y1);
566: p2y = YTRANS(draw,windraw,y2);
567: p3y = YTRANS(draw,windraw,y3);
568:
569: if(windraw->node->DoubleBuffered) {
570: bit = windraw->node->DoubleBuffer;
571: } else {
572: bit = windraw->node->Buffer;
573: }
574: BeginPath(bit);
575: MoveToEx(bit,p1x,p1y,NULL);
576: LineTo(bit,p2x,p2y);
577: LineTo(bit,p3x,p3y);
578: LineTo(bit,p1x,p1y);
579: EndPath(bit);
580: SelectPen(bit,hpen);
581: SelectBrush(bit,hbrush);
582: StrokeAndFillPath(bit);
583: /* Forces a WM_PAINT message and erases background */
584: InvalidateRect(windraw->hWnd,NULL,TRUE);
585: UpdateWindow(windraw->hWnd);
586: return(0);
587: }
588: #undef __FUNCT__
590: void PopMessageLoopThread_Win32(PetscDraw popdraw)
591: {
592: PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
593: MSG msg;
594: HWND hWnd = NULL;
595: char PopClassName [MAX_LOADSTRING + 1];
596: RECT r;
597: int width,height;
598: WNDCLASSEX myclass;
599: LPVOID lpMsgBuf;
600:
601: /* initialize window class parameters */
602: myclass.cbSize = sizeof(WNDCLASSEX);
603: myclass.style = CS_OWNDC;
604: myclass.lpfnWndProc = (WNDPROC)WndProc;
605: myclass.cbClsExtra = 0;
606: myclass.cbWndExtra = 0;
607: myclass.hInstance = NULL;
608: myclass.hIcon = NULL;
609: myclass.hCursor = LoadCursor(NULL, IDC_ARROW);
610: myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
611: myclass.lpszMenuName = NULL;
612: myclass.lpszClassName = PopClassName;
613: myclass.hIconSm = NULL;
614:
615: RegisterClassEx(&myclass);
616:
617: SetRect(&r,0,0,450,450);
618:
619: width = (r.right - r.left) / 3;
620: height = (r.bottom - r.top) / 3;
621:
622: hWnd = CreateWindowEx(0,
623: PopClassName,
624: NULL,
625: WS_POPUPWINDOW | WS_CAPTION,
626: 0,0,
627: width,height,
628: NULL,
629: NULL,
630: hInst,
631: NULL);
632: pop->x = 0;
633: pop->y = 0;
634: pop->w = width;
635: pop->h = height;
636:
637: if(hWnd == NULL) {
638: lpMsgBuf = "Window Not Succesfully Created";
639: MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
640: LocalFree( lpMsgBuf );
641: exit(0);
642: }
643: pop->hWnd = hWnd;
644: /* display and update new popup window */
645: ShowWindow(pop->hWnd, SW_SHOWNORMAL);
646: UpdateWindow(pop->hWnd);
647: SetEvent(pop->hReadyEvent);
648:
649: while (GetMessage(&msg, pop->hWnd, 0, 0)) {
650: TranslateMessage(&msg);
651: DispatchMessage(&msg);
652: }
653: }
655: #undef __FUNCT__
657: static int PetscDrawDestroy_Win32(PetscDraw draw)
658: {
659: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
660:
662: SendMessage(windraw->hWnd,WM_DESTROY,0,0);
663: PetscFree(windraw);
664: return(0);
665: }
666: #undef __FUNCT__
668: static int PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
669: {
670: /* Multi Processor is not implemeted yet */
672: PetscDrawFlush_Win32(draw);
673: return(0);
674: }
675: #undef __FUNCT__
677: static int PetscDrawSynchronizedClear_Win32(PetscDraw draw)
678: {
679: /* Multi Processor is not implemeted yet */
681: PetscDrawClear_Win32(draw);
682: return(0);
683: }
684: #undef __FUNCT__
686: void MessageLoopThread_Win32(PetscDraw draw)
687: {
688: PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
689: MSG msg;
690: HWND hWnd = NULL;
691: char classname[MAX_LOADSTRING + 1];
692: WNDCLASSEX wclass;
693: LPVOID lpMsgBuf;
694:
695: /* initialize window class parameters */
696: wclass.cbSize = sizeof(WNDCLASSEX);
697: wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
698: wclass.lpfnWndProc = (WNDPROC)WndProc;
699: wclass.cbClsExtra = 0;
700: wclass.cbWndExtra = 0;
701: wclass.hInstance = NULL;
702: wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
703: wclass.hCursor = LoadCursor(NULL,IDC_ARROW);
704: wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
705: wclass.lpszMenuName = NULL;
706: wclass.lpszClassName = classname;
707: wclass.hIconSm = NULL;
708:
709: RegisterClassEx(&wclass);
710:
711:
712: hWnd = CreateWindowEx(0,
713: classname,
714: NULL,
715: WS_OVERLAPPEDWINDOW,
716: draw->x,
717: draw->y,
718: draw->w,
719: draw->h,
720: NULL,
721: NULL,
722: hInst,
723: NULL);
724:
725: if(hWnd == NULL) {
726: lpMsgBuf = "Window Not Succesfully Created";
727: MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
728: LocalFree( lpMsgBuf );
729: exit(0);
730: }
731: windraw->hWnd = hWnd;
732: /* display and update new window */
733: ShowWindow(hWnd,SW_SHOWNORMAL);
734: UpdateWindow(hWnd);
735: SetEvent(windraw->hReadyEvent);
736:
737: while (GetMessage(&msg,hWnd, 0, 0)) {
738: TranslateMessage(&msg);
739: DispatchMessage(&msg);
740: }
741: }
744: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
745: PetscDrawFlush_Win32,
746: PetscDrawLine_Win32,
747: PetscDrawLineSetWidth_Win32,
748: PetscDrawLineGetWidth_Win32,
749: PetscDrawPoint_Win32,
750: PetscDrawPointSetSize_Win32,
751: PetscDrawString_Win32,
752: PetscDrawStringVertical_Win32,
753: PetscDrawStringSetSize_Win32,
754: PetscDrawStringGetSize_Win32,
755: 0,
756: PetscDrawClear_Win32,
757: PetscDrawSynchronizedFlush_Win32,
758: PetscDrawRectangle_Win32,
759: PetscDrawTriangle_Win32,
760: 0,
761: PetscDrawGetMouseButton_Win32,
762: PetscDrawPause_Win32,
763: PetscDrawSynchronizedClear_Win32,
764: 0,
765: 0,
766: PetscDrawGetPopup_Win32,
767: PetscDrawSetTitle_Win32,
768: PetscDrawCheckResizedWindow_Win32,
769: PetscDrawResizeWindow_Win32,
770: PetscDrawDestroy_Win32,
771: 0,
772: 0,
773: 0,
774: 0};
777: static int PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
778: {
779: PetscDraw_Win32 *pop;
780: HANDLE hThread = NULL;
781: WindowNode newnode;
782: int ierr;
783:
785: PetscNew(PetscDraw_Win32,&pop);
786: (*popdraw)->data = pop;
787:
788: /* the following is temporary fix for initializing a global datastructure */
789: if(!g_hWindowListMutex) {
790: g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
791: }
792: PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
793:
794: pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
795: CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
796: CloseHandle(hThread);
797: WaitForSingleObject(pop->hReadyEvent, INFINITE);
798: CloseHandle(pop->hReadyEvent);
799: WaitForSingleObject(g_hWindowListMutex, INFINITE);
800:
801: draw->popup = (*popdraw);
802: ierr = PetscNew(struct _p_WindowNode,&newnode);
803: newnode->MouseListHead = NULL;
804: newnode->MouseListTail = NULL;
805: newnode->wnext = WindowListHead;
806: newnode->wprev = NULL;
807: newnode->hWnd = pop->hWnd;
808: if(WindowListHead != NULL) {
809: WindowListHead->wprev = newnode;
810: }
811: WindowListHead = newnode;
812: pop->hdc = GetDC(pop->hWnd);
813:
814: pop->stringheight = 10;
815: pop->stringwidth = 6;
816: pop->linewidth = 1; /* default pixel sizes of graphics until user changes them */
817: pop->pointdiameter = 1;
818: pop->node = newnode;
819:
820: newnode->bitwidth = pop->w;
821: newnode->bitheight = pop->h;
822:
823: /* Create and initialize primary graphics buffer */
824: newnode->Buffer = CreateCompatibleDC(pop->hdc);
825: newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
826: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
827: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
828:
829:
830: newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL);
831: newnode->DoubleBuffered = PETSC_FALSE;
832:
833: ReleaseDC(pop->hWnd,pop->hdc);
834: ReleaseMutex(g_hWindowListMutex);
835: return(0);
836: }
839: EXTERN_C_BEGIN
840: int PetscDrawCreate_Win32(PetscDraw draw)
841: {
842: PetscDraw_Win32 *windraw;
843: HANDLE hThread = NULL;
844: int ierr;
845: WindowNode newnode;
846:
847: ierr = PetscNew(PetscDraw_Win32,&windraw);
848: draw->data = windraw;
849:
850: /* the following is temporary fix for initializing a global datastructure */
851: if(!g_hWindowListMutex) {
852: g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
853: }
854: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
855:
856: windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
857: /* makes call to MessageLoopThread to creat window and attach a thread */
858: CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
859: CloseHandle(hThread);
860: WaitForSingleObject(windraw->hReadyEvent,INFINITE);
861: CloseHandle(windraw->hReadyEvent);
862: WaitForSingleObject(g_hWindowListMutex,INFINITE);
863:
864: ierr = PetscNew(struct _p_WindowNode,&newnode);
865: newnode->MouseListHead = NULL;
866: newnode->MouseListTail = NULL;
867: newnode->wnext = WindowListHead;
868: newnode->wprev = NULL;
869: newnode->hWnd = windraw->hWnd;
870: if(WindowListHead != NULL) {
871: WindowListHead->wprev = newnode;
872: }
873: WindowListHead = newnode;
874: windraw->hdc = GetDC(windraw->hWnd);
875:
876: windraw->stringheight = 10;
877: windraw->stringwidth = 6;
878: windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */
879: windraw->pointdiameter = 1;
880: windraw->node = newnode;
881:
882: windraw->x = draw->x;
883: windraw->y = draw->y;
884: windraw->w = newnode->bitwidth = draw->w;
885: windraw->h = newnode->bitheight = draw->h;
886:
887: /* Create and initialize primary graphics buffer */
888: newnode->Buffer = CreateCompatibleDC(windraw->hdc);
889: newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
890: newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
891: ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
892:
893: newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL);
894: newnode->DoubleBuffered = PETSC_FALSE;
895:
896: ReleaseDC(windraw->hWnd,windraw->hdc);
897: ReleaseMutex(g_hWindowListMutex);
898: return 0;
899: }
900: EXTERN_C_END
903: /* FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
904: PURPOSE: Processes messages for the main window.
905: WM_COMMAND - process the application menu
906: WM_PAINT - Paint the main window
907: WM_DESTROY - post a quit message and return */
908: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
909: {
910: int wmId, wmEvent;
911: PAINTSTRUCT ps;
912:
913: switch (message) {
914: HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
915: HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
916: case WM_COMMAND:
917: wmId = LOWORD(wParam);
918: wmEvent = HIWORD(wParam);
919: /* Parse the menu selections:*/
920: switch (wmId) {
921: case IDM_EXIT:
922: DestroyWindow(hWnd);
923: break;
924: default:
925: return DefWindowProc(hWnd, message, wParam, lParam);
926: }
927: break;
928: case WM_LBUTTONUP:
929: MouseRecord_Win32(hWnd,BUTTON_LEFT);
930: break;
931: case WM_RBUTTONUP:
932: MouseRecord_Win32(hWnd,BUTTON_RIGHT);
933: break;
934: case WM_MBUTTONUP:
935: MouseRecord_Win32(hWnd,BUTTON_CENTER);
936: break;
937: default:
938: return DefWindowProc(hWnd, message, wParam, lParam);
939: }
940: return 0;
941: }
943: static void OnPaint_Win32(HWND hWnd)
944: {
945: PAINTSTRUCT ps;
946: HDC hdc;
947: WindowNode current = NULL;
948: InvalidateRect(hWnd,NULL,TRUE);
949: WaitForSingleObject(g_hWindowListMutex, INFINITE);
950: current = WindowListHead;
951: hdc = BeginPaint(hWnd, &ps);
952:
953: while(current != NULL) {
954: if (current->hWnd == hWnd) {
955: /* flushes primary buffer to window */
956: BitBlt(hdc,
957: 0,0,
958: GetDeviceCaps(hdc,HORZRES),
959: GetDeviceCaps(hdc,VERTRES),
960: current->Buffer,
961: 0,0,
962: SRCCOPY);
963:
964: /* StretchBlt(hdc,
965: 0,0,
966: w,h,
967: current->Buffer,
968: 0,0,
969: current->bitwidth,
970: current->bitheight,
971: SRCCOPY); */
972: break;
973: }
974: current = current->wnext;
975: }
976: EndPaint(hWnd, &ps);
977: ReleaseMutex(g_hWindowListMutex);
978: }
980: static int MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
981: {
982:
983: /* Called by all three mouse button actions
984: Records needed mouse data in windows data structure */
985: WindowNode current = NULL;
986: MouseNode newnode;
987: POINT mousepos;
988: int ierr;
989:
990: WaitForSingleObject(g_hWindowListMutex, INFINITE);
991: current = WindowListHead;
992: if(current->IsGetMouseOn == TRUE) {
993:
994: SetEvent(current->event);
995: while (current != NULL) {
996: if(current->hWnd == hWnd) {
997:
998: ierr = PetscNew(struct _p_MouseNode,&newnode);
999: newnode->Button = button;
1000: GetCursorPos(&mousepos);
1001: newnode->user.x = mousepos.x;
1002: newnode->user.y = mousepos.y;
1003: ScreenToClient(hWnd,&mousepos);
1004: newnode->phys.x = mousepos.x;
1005: newnode->phys.y = mousepos.y;
1006: if(current->MouseListTail == NULL) {
1007: current->MouseListHead = newnode;
1008: current->MouseListTail = newnode;
1009: } else {
1010: current->MouseListTail->mnext = newnode;
1011: current->MouseListTail = newnode;
1012: }
1013: newnode->mnext = NULL;
1014:
1015: break;
1016: }
1017: current = current->wnext;
1018: }
1019: }
1020: ReleaseMutex(g_hWindowListMutex);
1021: return 0;
1022: }
1024: static void OnDestroy_Win32(HWND hWnd)
1025: {
1026: /* searches linked list of window data and frees corresponding memory */
1027: WindowNode current;
1028:
1029: WaitForSingleObject(g_hWindowListMutex, INFINITE);
1030: current = WindowListHead;
1031:
1032: SetEvent(current->event);
1033: while (current != NULL) {
1034: if(current->hWnd == hWnd) {
1035: if(current->wprev != NULL) {
1036: current->wprev->wnext = current->wnext;
1037: } else {
1038: WindowListHead = current->wnext;
1039: }
1040: if(current->MouseListHead) {
1041: deletemouselist_Win32(current);
1042: } else {
1043: PetscFree(current);
1044: }
1045: break;
1046: }
1047: current = current->wnext;
1048: }
1049: ReleaseMutex(g_hWindowListMutex);
1050: PostQuitMessage(0);
1051: }