Actual source code: win32draw.c

  1: #define PETSC_DLL
  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: #if !defined(SelectPen)
 13: #define SelectPen(hdc, hpen)      ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
 14: #endif
 15: #if !defined(SelectFont)
 16: #define SelectFont(hdc,hfont)    ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
 17: #endif
 18: #if !defined(SelectBrush)
 19: #define SelectBrush(hdc,hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
 20: #endif
 21: #if !defined(GetStockBrush)
 22: #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))
 23: #endif

 25: #define XTRANS(draw,win,x) \
 26:    (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*\
 27:                                    ((draw)->port_xr - (draw)->port_xl))/\
 28:                                    ((draw)->coor_xr - (draw)->coor_xl))))
 29: #define YTRANS(draw,win,y) \
 30:    (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*\
 31:                                    ((draw)->port_yr - (draw)->port_yl))/\
 32:                                    ((draw)->coor_yr - (draw)->coor_yl))))

 34: HINSTANCE     hInst;
 35: HANDLE        g_hWindowListMutex = NULL;
 36: WindowNode    WindowListHead     = NULL;

 38: /* Hard coded color hue until hue.c works with this */
 39: unsigned char RedMap[]   = {255,0,255,0,0,0,255,127,34,255,238,165,255,255,190,255,255,238,0,255,105,154,135,0,0,244,152,176,220,216,50,255};
 40: unsigned char GreenMap[] = {255,0,0,255,255,0,0,255,139,165,130,42,182,127,190,255,215,162,197,246,105,205,206,100,0,164,245,224,17,191,205,240};
 41: unsigned char BlueMap[]  = {255,0,0,0,255,255,225,212,34,0,238,42,193,80,190,0,0,173,205,143,105,50,235,0,128,96,255,230,120,216,50,245};

 43: /* Foward declarations of functions included in this code module: */
 44: LRESULT PETSC_DLLEXPORT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
 45: static PetscErrorCode TranslateColor_Win32(PetscDraw,int);
 46: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
 47: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw,int,int,int);
 48: static PetscErrorCode deletemouselist_Win32(WindowNode);
 49: static void OnPaint_Win32(HWND);
 50: static void OnDestroy_Win32(HWND);
 51: static PetscErrorCode MouseRecord_Win32(HWND,PetscDrawButton);
 52: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw,PetscDraw *);

 56: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
 57: {
 58:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 59:   HDC             hdc      = GetDC(windraw->hWnd);
 60: 
 62:   windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
 63:   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
 64:   windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
 65:   /* Fill background of second buffer */
 66:   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
 67:   /* Copy current buffer into seconf buffer and set window data as double buffered */
 68:   BitBlt(windraw->node->DoubleBuffer,
 69:          0,0,
 70:          windraw->w,windraw->h,
 71:          windraw->node->Buffer,
 72:          0,0,
 73:          SRCCOPY);

 75:   windraw->node->DoubleBuffered = PETSC_TRUE;
 76:   ReleaseDC(windraw->hWnd,hdc);
 77:   return(0);
 78: }

 82: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
 83: {
 84:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 85:   HDC             hdc = GetDC(windraw->hWnd);
 86: 
 88:   /* flush double buffer into primary buffer */
 89:   BitBlt(windraw->node->Buffer,
 90:          0,0,
 91:          windraw->w,windraw->h,
 92:          windraw->node->DoubleBuffer,
 93:          0,0,
 94:          SRCCOPY);
 95:   /* flush double buffer into window */
 96:   BitBlt(hdc,
 97:          0,0,
 98:          windraw->w,windraw->h,
 99:          windraw->node->DoubleBuffer,
100:          0,0,
101:          SRCCOPY);
102:   ReleaseDC(windraw->hWnd,hdc);
103:   return(0);
104: }

108: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
109: {
110:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
111:   MouseNode node;
112: 
113:   while(deletelist->MouseListHead != NULL) {
114:     node = deletelist->MouseListHead;
115:     if(deletelist->MouseListHead->mnext != NULL) {
116:       deletelist->MouseListHead = deletelist->MouseListHead->mnext;
117:     }
118:     PetscFree(node);
119:   }
120:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
121:   if (deletelist->wprev != NULL) {
122:     deletelist->wprev->wnext = deletelist->wnext;
123:   }
124:   if (deletelist->wnext != NULL) {
125:     deletelist->wnext->wprev = deletelist->wprev;
126:   }
127:   PetscFree(deletelist);
128:   return 0;
129: }

133: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
134: {
135:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
136:   WindowNode      current;
137:   MouseNode       node=0;
138: 
140:   /* Make sure no other code is using the linked list at this moment */
141:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
142:   /* Look for the node that matches the window you are using */
143:   current = WindowListHead;
144:   while (current != NULL) {
145:     if(current->hWnd == windraw->hWnd) {
146:       current->IsGetMouseOn = TRUE;
147:       break;
148:     } else {
149:       current = current->wnext;
150:     }
151:   }
152:   /* If no actions have occured, wait for one */
153:   node = current->MouseListHead;
154:   if (!node) {
155:     ReleaseMutex(g_hWindowListMutex);
156:     WaitForSingleObject(current->event, INFINITE);
157:     WaitForSingleObject(g_hWindowListMutex, INFINITE);
158:   }
159:   /* once we have the information, assign the pointers to it */
160:   *button = current->MouseListHead->Button;
161:   *x_user = current->MouseListHead->user.x;
162:   *y_user = current->MouseListHead->user.y;
163:   /* optional arguments */
164:   if (x_phys) *x_phys = current->MouseListHead->phys.x;
165:   if (y_phys) *y_phys = current->MouseListHead->phys.y;
166:   /* remove set of information from sub linked-list, delete the node */
167:   current->MouseListHead = current->MouseListHead->mnext;
168:   if (!current->MouseListHead) {
169:     ResetEvent(current->event);
170:     current->MouseListTail = NULL;
171:   }
172:   if (node) PetscFree(node);

174:   /* Release mutex so that  other code can use
175:      the linked list now that we are done with it */
176:   ReleaseMutex(g_hWindowListMutex);
177:   return(0);
178: }

182: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
183: {
185:   PetscSleep(draw->pause);
186:   return(0);
187: }

191: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
192: {
193:   /* Maps single color value into the RGB colors in our tables */
194:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
195:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
196:   return 0;
197: }

201: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
202: {
203:   /* Averages colors given at points of rectangle and sets color from color table
204:     will be changed once the color gradient problem is worked out */
205:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
206:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
207:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
208:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
209:   return 0;
210: }

214: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
215: {
216:   /* Averages colors given at points of rectangle and sets color from color table
217:     will be changed once the color gradient problem is worked out */
218:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
219:   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
220:                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
221:                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
222:   return 0;
223: }

227: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
228: {
229:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
230:   HBRUSH          hbrush;
231:   RECT            rect;
232:   int             x1,yone,x2,y2;
233:   HDC             hdc;
234: 
236:   x1 = XTRANS(draw,windraw,xl);
237:   x2 = XTRANS(draw,windraw,xr);
238:   yone = YTRANS(draw,windraw,yl);
239:   y2 = YTRANS(draw,windraw,yr);
240:   SetRect(&rect,x1,y2,x2,yone);
241:   if (c1==c2 && c2==c3 && c3==c4) {
242:     TranslateColor_Win32(draw,c1);
243:   } else {
244:     AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
245:   }
246:   hbrush = CreateSolidBrush(windraw->currentcolor);
247: 
248:   if(windraw->node->DoubleBuffered) {
249:     hdc = windraw->node->DoubleBuffer;
250:   } else {
251:     hdc = windraw->node->Buffer;
252:   }
253:   FillRect(hdc,&rect,hbrush);
254:   /* Forces a WM_PAINT message and erases background */
255:   InvalidateRect(windraw->hWnd,NULL,TRUE);
256:   UpdateWindow(windraw->hWnd);
257:   return(0);
258: }

262: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
263: {
264:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
265:   HPEN            hpen;
266:   int             x1,yone,x2,y2;
267:   HDC             hdc;
268: 
270:   TranslateColor_Win32(draw,color);
271:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
272:   yone   = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
273:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
274:   if(windraw->node->DoubleBuffered) {
275:     hdc = windraw->node->DoubleBuffer;
276:   } else {
277:     hdc = windraw->node->Buffer;
278:   }
279:   SelectPen(hdc,hpen);
280:   MoveToEx(hdc,x1,yone,NULL);
281:   LineTo(hdc,x2,y2);
282:   /* Forces a WM_PAINT message and erases background */
283:   InvalidateRect(windraw->hWnd,NULL,TRUE);
284:   UpdateWindow(windraw->hWnd);
285:   return(0);
286: }

290: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
291: {
292:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
293:   int             averagesize,finalwidth;
294:   RECT            rect;
295: 
297:   GetClientRect(windraw->hWnd,&rect);
298:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
299:   finalwidth  = (int)floor(averagesize*width);
300:   if (finalwidth < 1) {
301:     finalwidth = 1; /* minimum size PetscDrawLine can except */
302:   }
303:   windraw->linewidth = finalwidth;
304:   return(0);
305: }

309: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
310: {
311:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
312: 
314:   *width = (PetscReal)windraw->linewidth;
315:   return(0);
316: }

320: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
321: {
322:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
323:   HBRUSH          hbrush;
324:   HRGN            hrgn;
325:   int             radius;
326:   int             x1,yone;
327:   HDC             hdc;
328: 
330:   TranslateColor_Win32(draw,color);
331:   x1     = XTRANS(draw,windraw,x);
332:   yone     = YTRANS(draw,windraw,y);
333:   hbrush = CreateSolidBrush(windraw->currentcolor);
334:   if(windraw->node->DoubleBuffered) {
335:     hdc = windraw->node->DoubleBuffer;
336:   } else {
337:     hdc = windraw->node->Buffer;
338:   }
339:   /* desired size is one logical pixel so just turn it on */
340:   if (windraw->pointdiameter == 1) {
341:     SetPixelV(hdc,x1,yone,windraw->currentcolor);
342:   } else {
343:     /* draw point around position determined */
344:     radius = windraw->pointdiameter/2; /* integer division */
345:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
346:     FillRgn(hdc,hrgn,hbrush);
347:   }
348:   /* Forces a WM_PAINT and erases background */
349:   InvalidateRect(windraw->hWnd,NULL,TRUE);
350:   UpdateWindow(windraw->hWnd);
351:   return(0);
352: }

356: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
357: {
358:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
359:   int             averagesize,diameter;
360:   RECT            rect;
361: 
363:   GetClientRect(windraw->hWnd,&rect);
364:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
365:   diameter    = (int)floor(averagesize*width);
366:   if (diameter < 1) diameter = 1;
367:   windraw->pointdiameter     = diameter;
368:   return(0);
369: }

373: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
374: {
375:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
376:   RECT            r;
377:   HFONT           hfont;
378:   LOGFONT         logfont;
379:   int             x1,yone;
380:   HDC             hdc;
381: 
383:   x1              = XTRANS(draw,windraw,x);
384:   yone              = YTRANS(draw,windraw,y);
385:   r.bottom        = yone;
386:   r.left          = x1;
387:   r.right         = x1 + 1;
388:   r.top           = yone + 1;
389:   logfont.lfHeight         = windraw->stringheight;
390:   logfont.lfWidth          = windraw->stringwidth;
391:   logfont.lfEscapement     = 0;
392:   logfont.lfOrientation    = 0;
393:   logfont.lfCharSet        = 0;
394:   logfont.lfClipPrecision  = 0;
395:   logfont.lfItalic         = 0;
396:   logfont.lfOutPrecision   = 0;
397:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
398:   logfont.lfQuality        = DEFAULT_QUALITY;
399:   logfont.lfStrikeOut      = 0;
400:   logfont.lfUnderline      = 0;
401:   logfont.lfWeight         = FW_NORMAL;
402:   hfont = CreateFontIndirect(&logfont);
403:   TranslateColor_Win32(draw,color);
404:   if(windraw->node->DoubleBuffered) {
405:     hdc = windraw->node->DoubleBuffer;
406:   } else {
407:     hdc = windraw->node->Buffer;
408:   }
409:   SelectFont(hdc,hfont);
410:   SetTextColor(hdc,windraw->currentcolor);
411:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
412:   DeleteObject(hfont);
413:   /* Forces a WM_PAINT message and erases background */
414:   InvalidateRect(windraw->hWnd,NULL,TRUE);
415:   UpdateWindow(windraw->hWnd);
416:   return(0);
417: }

421: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
422: {
423:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
424:   RECT            r;
425:   HFONT           hfont;
426:   LOGFONT         logfont;
427:   int             x1,yone;
428:   HDC             hdc;
429: 
431:   x1           = XTRANS(draw,windraw,x);
432:   yone           = YTRANS(draw,windraw,y);
433:   r.left       = x1;
434:   r.bottom     = yone + 30;
435:   r.right      = x1 + 1;
436:   r.top        = yone - 30;
437:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
438:   logfont.lfHeight         = windraw->stringheight;
439:   logfont.lfWidth          = windraw->stringwidth;
440:   logfont.lfOrientation    = 0;
441:   logfont.lfCharSet        = DEFAULT_CHARSET;
442:   logfont.lfClipPrecision  = 0;
443:   logfont.lfItalic         = 0;
444:   logfont.lfOutPrecision   = 0;
445:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
446:   logfont.lfQuality        = DEFAULT_QUALITY;
447:   logfont.lfStrikeOut      = 0;
448:   logfont.lfUnderline      = 0;
449:   logfont.lfWeight         = FW_NORMAL;
450:   hfont = CreateFontIndirect(&logfont);
451:   TranslateColor_Win32(draw,color);
452:   if(windraw->node->DoubleBuffered) {
453:     hdc = windraw->node->DoubleBuffer;
454:   } else {
455:     hdc = windraw->node->Buffer;
456:   }
457:   SelectFont(hdc,hfont);
458:   SetTextColor(hdc,windraw->currentcolor);
459:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE );
460:   DeleteObject(hfont);
461:   /* Forces a WM_PAINT message and erases background */
462:   InvalidateRect(windraw->hWnd,NULL,TRUE);
463:   UpdateWindow(windraw->hWnd);
464:   return(0);
465: }

469: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
470: {
471:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
472:   int             w,h;
473: 
475:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
476:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
477:   if (h < 1) h = 1;
478:   if (w < 1) w = 1;
479:   windraw->stringheight = h;
480:   windraw->stringwidth  = w;
481:   return(0);
482: }
485: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
486: {
487:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
488:   double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
489:   double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
490: 
492:   *height = (double)windraw->stringheight*scaleY;
493:   *width  = (double)windraw->stringwidth*scaleX;
494:   return(0);
495: }

499: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
500: {
501:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
502:   RECT            r;
503: 
505:   GetWindowRect(windraw->hWnd,&r);
506:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
507:   /* set all variable dealing with window dimensions */
508:   windraw->node->bitheight = windraw->h = draw->h = h;
509:   windraw->node->bitwidth  = windraw->w = draw->w = w;
510:   /* set up graphic buffers with the new size of window */
511:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
512:   if(windraw->node->DoubleBuffered) {
513:     SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
514:   }
515:   windraw->haveresized = PETSC_TRUE;
516:   return(0);
517: }

521: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
522: {
523:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
524: 
526:   if (windraw->haveresized == 1) {
527:     PetscFunctionReturn(1);
528:   } else {
529:     return(0);
530:   }
531: 
532: }

536: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
537: {
538:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
539: 
541:   SetWindowText(windraw->hWnd,title);
542:   return(0);
543: }

547: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
548: {
549:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
550: 
552:   /* clear primary buffer */
553:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
554:   /* if exists clear secondary buffer */
555:   if(windraw->node->DoubleBuffered) {
556:     ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
557:   }
558:   /* force WM_PAINT message so cleared buffer will show */
559:   InvalidateRect(windraw->hWnd,NULL,TRUE);
560:   UpdateWindow(windraw->hWnd);
561:   return(0);
562: }

566: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
567:                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
568: {
569:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
570:   HBRUSH          hbrush;
571:   HPEN            hpen;
572:   int             p1x,p1y,p2x,p2y,p3x,p3y;
573:   HDC             bit;
574: 
576:   AverageColorTriangle_Win32(draw,c1,c2,c3);
577:   hbrush = CreateSolidBrush(windraw->currentcolor);
578:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
579:   p1x = XTRANS(draw,windraw,x1);
580:   p2x = XTRANS(draw,windraw,x2);
581:   p3x = XTRANS(draw,windraw,x3);
582:   p1y = YTRANS(draw,windraw,yone);
583:   p2y = YTRANS(draw,windraw,y2);
584:   p3y = YTRANS(draw,windraw,y3);
585: 
586:   if(windraw->node->DoubleBuffered) {
587:     bit = windraw->node->DoubleBuffer;
588:   } else {
589:     bit = windraw->node->Buffer;
590:   }
591:   BeginPath(bit);
592:   MoveToEx(bit,p1x,p1y,NULL);
593:   LineTo(bit,p2x,p2y);
594:   LineTo(bit,p3x,p3y);
595:   LineTo(bit,p1x,p1y);
596:   EndPath(bit);
597:   SelectPen(bit,hpen);
598:   SelectBrush(bit,hbrush);
599:   StrokeAndFillPath(bit);
600:   /* Forces a WM_PAINT message and erases background */
601:   InvalidateRect(windraw->hWnd,NULL,TRUE);
602:   UpdateWindow(windraw->hWnd);
603:   return(0);
604: }

608: void PopMessageLoopThread_Win32(PetscDraw popdraw)
609: {
610:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
611:   MSG             msg;
612:   HWND            hWnd = NULL;
613:   char            PopClassName [MAX_LOADSTRING + 1];
614:   RECT            r;
615:   int             width,height;
616:   WNDCLASSEX      myclass;
617:   LPVOID          lpMsgBuf;
618: 
620:   /* initialize window class parameters */
621:   myclass.cbSize        = sizeof(WNDCLASSEX);
622:   myclass.style         = CS_OWNDC;
623:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
624:   myclass.cbClsExtra    = 0;
625:   myclass.cbWndExtra    = 0;
626:   myclass.hInstance     = NULL;
627:   myclass.hIcon         = NULL;
628:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
629:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
630:   myclass.lpszMenuName  = NULL;
631:   myclass.lpszClassName = PopClassName;
632:   myclass.hIconSm       = NULL;
633: 
634:   RegisterClassEx(&myclass);
635: 
636:   SetRect(&r,0,0,450,450);
637: 
638:   width    = (r.right - r.left) / 3;
639:   height   = (r.bottom - r.top) / 3;
640: 
641:   hWnd = CreateWindowEx(0,
642:                         PopClassName,
643:                         NULL,
644:                         WS_POPUPWINDOW | WS_CAPTION,
645:                         0,0,
646:                         width,height,
647:                         NULL,
648:                         NULL,
649:                         hInst,
650:                         NULL);
651:   pop->x = 0;
652:   pop->y = 0;
653:   pop->w = width;
654:   pop->h = height;
655: 
656:   if(!hWnd) {
657:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
658:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
659:     LocalFree( lpMsgBuf );
660:     exit(0);
661:   }
662:   pop->hWnd = hWnd;
663:   /* display and update new popup window */
664:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
665:   UpdateWindow(pop->hWnd);
666:   SetEvent(pop->hReadyEvent);
667: 
668:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
669:     TranslateMessage(&msg);
670:     DispatchMessage(&msg);
671:   }
672:   PetscFunctionReturnVoid();
673: }

677: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
678: {
679:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
680: 
682:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
683:   PetscFree(windraw);
684:   return(0);
685: }

689: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
690: {
691:   /* Multi Processor is not implemeted yet */
693:   PetscDrawFlush_Win32(draw);
694:   return(0);
695: }

699: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
700: {
701:   /* Multi Processor is not implemeted yet */
703:   PetscDrawClear_Win32(draw);
704:   return(0);
705: }

709: void MessageLoopThread_Win32(PetscDraw draw)
710: {
711:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
712:   MSG             msg;
713:   HWND            hWnd = NULL;
714:   char            classname[MAX_LOADSTRING + 1];
715:   WNDCLASSEX      wclass;
716:   LPVOID          lpMsgBuf;
717: 
719:   /* initialize window class parameters */
720:   wclass.cbSize         = sizeof(WNDCLASSEX);
721:   wclass.style          = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
722:   wclass.lpfnWndProc    = (WNDPROC)PetscWndProc;
723:   wclass.cbClsExtra     = 0;
724:   wclass.cbWndExtra     = 0;
725:   wclass.hInstance      = NULL;
726:   wclass.hIcon          = LoadIcon(NULL,IDI_APPLICATION);
727:   wclass.hCursor        = LoadCursor(NULL,IDC_ARROW);
728:   wclass.hbrBackground  = GetStockBrush(WHITE_BRUSH);
729:   wclass.lpszMenuName   = NULL;
730:   wclass.lpszClassName  = classname;
731:   wclass.hIconSm        = NULL;
732: 
733:   RegisterClassEx(&wclass);
734: 
735: 
736:   hWnd = CreateWindowEx(0,
737:                         classname,
738:                         NULL,
739:                         WS_OVERLAPPEDWINDOW,
740:                         draw->x,
741:                         draw->y,
742:                         draw->w,
743:                         draw->h,
744:                         NULL,
745:                         NULL,
746:                         hInst,
747:                         NULL);
748: 
749:   if (!hWnd) {
750:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
751:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
752:     LocalFree( lpMsgBuf );
753:     exit(0);
754:   }
755:   windraw->hWnd = hWnd;
756:   /* display and update new window */
757:   ShowWindow(hWnd,SW_SHOWNORMAL);
758:   UpdateWindow(hWnd);
759:   SetEvent(windraw->hReadyEvent);
760: 
761:   while (GetMessage(&msg,hWnd, 0, 0)) {
762:     TranslateMessage(&msg);
763:     DispatchMessage(&msg);
764:   }
765:   PetscFunctionReturnVoid();
766: }


769: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
770:                                  PetscDrawFlush_Win32,
771:                                  PetscDrawLine_Win32,
772:                                  PetscDrawLineSetWidth_Win32,
773:                                  PetscDrawLineGetWidth_Win32,
774:                                  PetscDrawPoint_Win32,
775:                                  PetscDrawPointSetSize_Win32,
776:                                  PetscDrawString_Win32,
777:                                  PetscDrawStringVertical_Win32,
778:                                  PetscDrawStringSetSize_Win32,
779:                                  PetscDrawStringGetSize_Win32,
780:                                  0,
781:                                  PetscDrawClear_Win32,
782:                                  PetscDrawSynchronizedFlush_Win32,
783:                                  PetscDrawRectangle_Win32,
784:                                  PetscDrawTriangle_Win32,
785:                                  0,
786:                                  PetscDrawGetMouseButton_Win32,
787:                                  PetscDrawPause_Win32,
788:                                  PetscDrawSynchronizedClear_Win32,
789:                                  0,
790:                                  0,
791:                                  PetscDrawGetPopup_Win32,
792:                                  PetscDrawSetTitle_Win32,
793:                                  PetscDrawCheckResizedWindow_Win32,
794:                                  PetscDrawResizeWindow_Win32,
795:                                  PetscDrawDestroy_Win32,
796:                                  0,
797:                                  0,
798:                                  0,
799:                                  0};

803: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
804: {
805:   PetscDraw_Win32 *pop;
806:   HANDLE          hThread = NULL;
807:   WindowNode      newnode;
809: 
811:   PetscNew(PetscDraw_Win32,&pop);
812:   (*popdraw)->data = pop;
813: 
814:   /* the following is temporary fix for initializing a global datastructure */
815:   if(!g_hWindowListMutex) {
816:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
817:   }
818:   PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
819: 
820:   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
821:   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
822:   CloseHandle(hThread);
823:   WaitForSingleObject(pop->hReadyEvent, INFINITE);
824:   CloseHandle(pop->hReadyEvent);
825:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
826: 
827:   draw->popup             = (*popdraw);
828:   PetscNew(struct _p_WindowNode,&newnode);
829:   newnode->MouseListHead  = NULL;
830:   newnode->MouseListTail  = NULL;
831:   newnode->wnext          = WindowListHead;
832:   newnode->wprev          = NULL;
833:   newnode->hWnd           = pop->hWnd;
834:   if(WindowListHead != NULL) {
835:     WindowListHead->wprev = newnode;
836:   }
837:   WindowListHead          = newnode;
838:   pop->hdc                = GetDC(pop->hWnd);
839: 
840:   pop->stringheight   = 10;
841:   pop->stringwidth    = 6;
842:   pop->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
843:   pop->pointdiameter  = 1;
844:   pop->node           = newnode;
845: 
846:   newnode->bitwidth  = pop->w;
847:   newnode->bitheight = pop->h;
848: 
849:   /* Create and initialize primary graphics buffer */
850:   newnode->Buffer = CreateCompatibleDC(pop->hdc);
851:   newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
852:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
853:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
854: 
855: 
856:   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
857:   newnode->DoubleBuffered = PETSC_FALSE;
858: 
859:   ReleaseDC(pop->hWnd,pop->hdc);
860:   ReleaseMutex(g_hWindowListMutex);
861:   return(0);
862: }

867: PetscErrorCode PETSC_DLLEXPORT PetscDrawCreate_Win32(PetscDraw draw)
868: {
869:   PetscDraw_Win32 *windraw;
870:   HANDLE          hThread = NULL;
872:   WindowNode      newnode;
873: 
875:   PetscNew(PetscDraw_Win32,&windraw);
876:   draw->data  = windraw;
877: 
878:   /* the following is temporary fix for initializing a global datastructure */
879:   if(!g_hWindowListMutex) {
880:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
881:   }
882:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
883: 
884:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
885:   /* makes call to MessageLoopThread to creat window and attach a thread */
886:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
887:   CloseHandle(hThread);
888:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
889:   CloseHandle(windraw->hReadyEvent);
890:   WaitForSingleObject(g_hWindowListMutex,INFINITE);
891: 
892:   PetscNew(struct _p_WindowNode,&newnode);
893:   newnode->MouseListHead  = NULL;
894:   newnode->MouseListTail  = NULL;
895:   newnode->wnext          = WindowListHead;
896:   newnode->wprev          = NULL;
897:   newnode->hWnd           = windraw->hWnd;
898:   if(WindowListHead != NULL) {
899:     WindowListHead->wprev = newnode;
900:   }
901:   WindowListHead          = newnode;
902:   windraw->hdc            = GetDC(windraw->hWnd);
903: 
904:   windraw->stringheight   = 10;
905:   windraw->stringwidth    = 6;
906:   windraw->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
907:   windraw->pointdiameter  = 1;
908:   windraw->node           = newnode;
909: 
910:   windraw->x = draw->x;
911:   windraw->y = draw->y;
912:   windraw->w = newnode->bitwidth    = draw->w;
913:   windraw->h = newnode->bitheight   = draw->h;
914: 
915:   /* Create and initialize primary graphics buffer */
916:   newnode->Buffer = CreateCompatibleDC(windraw->hdc);
917:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
918:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
919:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
920: 
921:   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
922:   newnode->DoubleBuffered = PETSC_FALSE;
923: 
924:   ReleaseDC(windraw->hWnd,windraw->hdc);
925:   ReleaseMutex(g_hWindowListMutex);
926:   return(0);
927: }


931: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
932:    PURPOSE:  Processes messages for the main window.
933:    WM_COMMAND  - process the application menu
934:    WM_PAINT    - Paint the main window
935:    WM_DESTROY  - post a quit message and return */

939: LRESULT PETSC_DLLEXPORT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
940: {
941:   int         wmId, wmEvent;
942: 
944:   switch (message) {
945:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
946:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
947:   case WM_COMMAND:
948:     wmId    = LOWORD(wParam);
949:     wmEvent = HIWORD(wParam);
950:     /* Parse the menu selections:*/
951:     switch (wmId) {
952:     case IDM_EXIT:
953:       DestroyWindow(hWnd);
954:       break;
955:     default:
956:       return DefWindowProc(hWnd, message, wParam, lParam);
957:     }
958:     break;
959:   case WM_LBUTTONUP:
960:     MouseRecord_Win32(hWnd,BUTTON_LEFT);
961:     break;
962:   case WM_RBUTTONUP:
963:     MouseRecord_Win32(hWnd,BUTTON_RIGHT);
964:     break;
965:   case WM_MBUTTONUP:
966:     MouseRecord_Win32(hWnd,BUTTON_CENTER);
967:     break;
968:   default:
969:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
970:   }
971:   return(0);
972: }

976: static void OnPaint_Win32(HWND hWnd)
977: {
978:   PAINTSTRUCT ps;
979:   HDC         hdc;
980:   WindowNode  current = NULL;

983:   InvalidateRect(hWnd,NULL,TRUE);
984:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
985:   current = WindowListHead;
986:   hdc     = BeginPaint(hWnd, &ps);
987: 
988:   while(current != NULL) {
989:     if (current->hWnd == hWnd) {
990:       /* flushes primary buffer to window */
991:       BitBlt(hdc,
992:              0,0,
993:              GetDeviceCaps(hdc,HORZRES),
994:              GetDeviceCaps(hdc,VERTRES),
995:              current->Buffer,
996:              0,0,
997:              SRCCOPY);
998: 
999:       /* StretchBlt(hdc,
1000:         0,0,
1001:         w,h,
1002:         current->Buffer,
1003:         0,0,
1004:         current->bitwidth,
1005:         current->bitheight,
1006:         SRCCOPY); */
1007:       break;
1008:     }
1009:     current = current->wnext;
1010:   }
1011:   EndPaint(hWnd, &ps);
1012:   ReleaseMutex(g_hWindowListMutex);
1013:   PetscFunctionReturnVoid();
1014: }

1018: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
1019: {
1020:   /* Called by all three mouse button actions
1021:     Records needed mouse data in windows data structure */
1022:   WindowNode current = NULL;
1023:   MouseNode  newnode;
1024:   POINT      mousepos;
1026: 
1028:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1029:   current = WindowListHead;
1030:   if(current->IsGetMouseOn == TRUE) {
1031: 
1032:     SetEvent(current->event);
1033:     while (current != NULL) {
1034:       if(current->hWnd == hWnd) {
1035: 
1036:         PetscNew(struct _p_MouseNode,&newnode);
1037:         newnode->Button = button;
1038:         GetCursorPos(&mousepos);
1039:         newnode->user.x = mousepos.x;
1040:         newnode->user.y = mousepos.y;
1041:         ScreenToClient(hWnd,&mousepos);
1042:         newnode->phys.x = mousepos.x;
1043:         newnode->phys.y = mousepos.y;
1044:         if (!current->MouseListTail) {
1045:           current->MouseListHead = newnode;
1046:           current->MouseListTail = newnode;
1047:         } else {
1048:           current->MouseListTail->mnext = newnode;
1049:           current->MouseListTail = newnode;
1050:         }
1051:         newnode->mnext = NULL;
1052: 
1053:         break;
1054:       }
1055:       current = current->wnext;
1056:     }
1057:   }
1058:   ReleaseMutex(g_hWindowListMutex);
1059:   return(0);
1060: }

1064: static void OnDestroy_Win32(HWND hWnd)
1065: {
1066:   /* searches linked list of window data and frees corresponding memory */
1067:   WindowNode current;
1068: 
1070:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1071:   current = WindowListHead;
1072: 
1073:   SetEvent(current->event);
1074:   while (current != NULL) {
1075:     if(current->hWnd == hWnd) {
1076:       if(current->wprev != NULL) {
1077:         current->wprev->wnext = current->wnext;
1078:       } else {
1079:         WindowListHead = current->wnext;
1080:       }
1081:       if(current->MouseListHead) {
1082:         deletemouselist_Win32(current);
1083:       } else {
1084:         PetscFree(current);
1085:       }
1086:       break;
1087:     }
1088:     current = current->wnext;
1089:   }
1090:   ReleaseMutex(g_hWindowListMutex);
1091:   PostQuitMessage(0);
1092:   PetscFunctionReturnVoid();
1093: }