Actual source code: win32draw.c

petsc-3.7.3 2016-08-01
Report Typos and Errors
  2: #include <petscsys.h>
  3: #include <petsc/private/drawimpl.h>
  4: #include <../src/sys/classes/draw/impls/win32/win32draw.h>

  6: #define IDC_FOUR       109
  7: #define IDI_FOUR       107
  8: #define IDM_EXIT       105
  9: #define IDR_POPUP      103
 10: #define MAX_LOADSTRING 100

 12: #if !defined(SelectPen)
 13: #define SelectPen(hdc, hpen)      ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
 14: #endif
 15: #if !defined(SelectFont)
 16: #define SelectFont(hdc,hfont)    ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
 17: #endif
 18: #if !defined(SelectBrush)
 19: #define SelectBrush(hdc,hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
 20: #endif
 21: #if !defined(GetStockBrush)
 22: #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))
 23: #endif

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

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

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

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

 56: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
 57: {
 58:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 59:   HDC             hdc      = GetDC(windraw->hWnd);

 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,0,0,windraw->w,windraw->h,
 69:          windraw->node->Buffer,0,0, SRCCOPY);

 71:   windraw->node->DoubleBuffered = PETSC_TRUE;
 72:   ReleaseDC(windraw->hWnd,hdc);
 73:   return(0);
 74: }

 78: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
 79: {
 80:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 81:   HDC             hdc      = GetDC(windraw->hWnd);

 84:   /* flush double buffer into primary buffer */
 85:   BitBlt(windraw->node->Buffer,0,0,windraw->w,windraw->h,
 86:          windraw->node->DoubleBuffer,0,0,SRCCOPY);
 87:   /* flush double buffer into window */
 88:   BitBlt(hdc,0,0,windraw->w,windraw->h,
 89:          windraw->node->DoubleBuffer, 0,0,SRCCOPY);
 90:   ReleaseDC(windraw->hWnd,hdc);
 91:   return(0);
 92: }

 96: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
 97: {
 98:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
 99:   MouseNode node;

101:   while (deletelist->MouseListHead) {
102:     node = deletelist->MouseListHead;
103:     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
104:     PetscFree(node);
105:   }
106:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
107:   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
108:   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
109:   PetscFree(deletelist);
110:   return 0;
111: }

115: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
116: {
117:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
118:   WindowNode      current;
119:   MouseNode       node=0;

122:   /* Make sure no other code is using the linked list at this moment */
123:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
124:   /* Look for the node that matches the window you are using */
125:   current = WindowListHead;
126:   while (current) {
127:     if (current->hWnd == windraw->hWnd) {
128:       current->IsGetMouseOn = TRUE;
129:       break;
130:     } else current = current->wnext;
131:   }
132:   /* If no actions have occured, wait for one */
133:   node = current->MouseListHead;
134:   if (!node) {
135:     ReleaseMutex(g_hWindowListMutex);
136:     WaitForSingleObject(current->event, INFINITE);
137:     WaitForSingleObject(g_hWindowListMutex, INFINITE);
138:   }
139:   /* once we have the information, assign the pointers to it */
140:   *button = current->MouseListHead->Button;
141:   *x_user = current->MouseListHead->user.x;
142:   *y_user = current->MouseListHead->user.y;
143:   /* optional arguments */
144:   if (x_phys) *x_phys = current->MouseListHead->phys.x;
145:   if (y_phys) *y_phys = current->MouseListHead->phys.y;
146:   /* remove set of information from sub linked-list, delete the node */
147:   current->MouseListHead = current->MouseListHead->mnext;
148:   if (!current->MouseListHead) {
149:     ResetEvent(current->event);
150:     current->MouseListTail = NULL;
151:   }
152:   if (node) PetscFree(node);

154:   /* Release mutex so that  other code can use
155:      the linked list now that we are done with it */
156:   ReleaseMutex(g_hWindowListMutex);
157:   return(0);
158: }

162: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
163: {
165:   PetscSleep(draw->pause);
166:   return(0);
167: }

171: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
172: {
173:   /* Maps single color value into the RGB colors in our tables */
174:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
175:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
176:   return 0;
177: }

181: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
182: {
183:   /* Averages colors given at points of rectangle and sets color from color table
184:     will be changed once the color gradient problem is worked out */
185:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
186:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
187:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
188:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
189:   return 0;
190: }

194: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
195: {
196:   /* Averages colors given at points of rectangle and sets color from color table
197:     will be changed once the color gradient problem is worked out */
198:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
199:   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
200:                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
201:                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
202:   return 0;
203: }

207: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
208: {
209:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
210:   HBRUSH          hbrush;
211:   RECT            rect;
212:   int             x1,yone,x2,y2;
213:   HDC             hdc;

216:   x1   = XTRANS(draw,windraw,xl);
217:   x2   = XTRANS(draw,windraw,xr);
218:   yone = YTRANS(draw,windraw,yl);
219:   y2   = YTRANS(draw,windraw,yr);
220:   SetRect(&rect,x1,y2,x2,yone);
221:   if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
222:   else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
223:   hbrush = CreateSolidBrush(windraw->currentcolor);

225:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
226:   else                               hdc = windraw->node->Buffer;

228:   FillRect(hdc,&rect,hbrush);
229:   /* Forces a WM_PAINT message and erases background */
230:   InvalidateRect(windraw->hWnd,NULL,TRUE);
231:   UpdateWindow(windraw->hWnd);
232:   return(0);
233: }

237: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
238: {
239:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
240:   HPEN            hpen;
241:   int             x1,yone,x2,y2;
242:   HDC             hdc;

245:   TranslateColor_Win32(draw,color);
246:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
247:   yone = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
248:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
249:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
250:   else                               hdc = windraw->node->Buffer;

252:   SelectPen(hdc,hpen);
253:   MoveToEx(hdc,x1,yone,NULL);
254:   LineTo(hdc,x2,y2);
255:   /* Forces a WM_PAINT message and erases background */
256:   InvalidateRect(windraw->hWnd,NULL,TRUE);
257:   UpdateWindow(windraw->hWnd);
258:   return(0);
259: }

263: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
264: {
265:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
266:   int             averagesize,finalwidth;
267:   RECT            rect;

270:   GetClientRect(windraw->hWnd,&rect);
271:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
272:   finalwidth  = (int)PetscFloorReal(averagesize*width);
273:   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */

275:   windraw->linewidth = finalwidth;
276:   return(0);
277: }

281: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
282: {
283:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

286:   *width = (PetscReal)windraw->linewidth;
287:   return(0);
288: }

292: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
293: {
294:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
295:   HBRUSH          hbrush;
296:   HRGN            hrgn;
297:   int             radius;
298:   int             x1,yone;
299:   HDC             hdc;

302:   TranslateColor_Win32(draw,color);
303:   x1     = XTRANS(draw,windraw,x);
304:   yone   = YTRANS(draw,windraw,y);
305:   hbrush = CreateSolidBrush(windraw->currentcolor);
306:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
307:   else                               hdc = windraw->node->Buffer;

309:   /* desired size is one logical pixel so just turn it on */
310:   if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
311:   else {
312:     /* draw point around position determined */
313:     radius = windraw->pointdiameter/2; /* integer division */
314:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
315:     FillRgn(hdc,hrgn,hbrush);
316:   }
317:   /* Forces a WM_PAINT and erases background */
318:   InvalidateRect(windraw->hWnd,NULL,TRUE);
319:   UpdateWindow(windraw->hWnd);
320:   return(0);
321: }

325: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
326: {
327:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
328:   int             averagesize,diameter;
329:   RECT            rect;

332:   GetClientRect(windraw->hWnd,&rect);
333:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
334:   diameter    = (int)PetscFloorReal(averagesize*width);
335:   if (diameter < 1) diameter = 1;
336:   windraw->pointdiameter = diameter;
337:   return(0);
338: }

342: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
343: {
344:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
345:   RECT            r;
346:   HFONT           hfont;
347:   LOGFONT         logfont;
348:   int             x1,yone;
349:   HDC             hdc;

352:   x1       = XTRANS(draw,windraw,x);
353:   yone     = YTRANS(draw,windraw,y);
354:   r.bottom = yone;
355:   r.left   = x1;
356:   r.right  = x1 + 1;
357:   r.top    = yone + 1;

359:   logfont.lfHeight         = windraw->stringheight;
360:   logfont.lfWidth          = windraw->stringwidth;
361:   logfont.lfEscapement     = 0;
362:   logfont.lfOrientation    = 0;
363:   logfont.lfCharSet        = 0;
364:   logfont.lfClipPrecision  = 0;
365:   logfont.lfItalic         = 0;
366:   logfont.lfOutPrecision   = 0;
367:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
368:   logfont.lfQuality        = DEFAULT_QUALITY;
369:   logfont.lfStrikeOut      = 0;
370:   logfont.lfUnderline      = 0;
371:   logfont.lfWeight         = FW_NORMAL;

373:   hfont = CreateFontIndirect(&logfont);
374:   TranslateColor_Win32(draw,color);
375:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
376:   else                               hdc = windraw->node->Buffer;

378:   SelectFont(hdc,hfont);
379:   SetTextColor(hdc,windraw->currentcolor);
380:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
381:   DeleteObject(hfont);
382:   /* Forces a WM_PAINT message and erases background */
383:   InvalidateRect(windraw->hWnd,NULL,TRUE);
384:   UpdateWindow(windraw->hWnd);
385:   return(0);
386: }

390: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
391: {
392:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
393:   RECT            r;
394:   HFONT           hfont;
395:   LOGFONT         logfont;
396:   int             x1,yone;
397:   HDC             hdc;

400:   x1       = XTRANS(draw,windraw,x);
401:   yone     = YTRANS(draw,windraw,y);
402:   r.left   = x1;
403:   r.bottom = yone + 30;
404:   r.right  = x1 + 1;
405:   r.top    = yone - 30;

407:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
408:   logfont.lfHeight         = windraw->stringheight;
409:   logfont.lfWidth          = windraw->stringwidth;
410:   logfont.lfOrientation    = 0;
411:   logfont.lfCharSet        = DEFAULT_CHARSET;
412:   logfont.lfClipPrecision  = 0;
413:   logfont.lfItalic         = 0;
414:   logfont.lfOutPrecision   = 0;
415:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
416:   logfont.lfQuality        = DEFAULT_QUALITY;
417:   logfont.lfStrikeOut      = 0;
418:   logfont.lfUnderline      = 0;
419:   logfont.lfWeight         = FW_NORMAL;

421:   hfont = CreateFontIndirect(&logfont);
422:   TranslateColor_Win32(draw,color);
423:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
424:   else                               hdc = windraw->node->Buffer;

426:   SelectFont(hdc,hfont);
427:   SetTextColor(hdc,windraw->currentcolor);
428:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
429:   DeleteObject(hfont);
430:   /* Forces a WM_PAINT message and erases background */
431:   InvalidateRect(windraw->hWnd,NULL,TRUE);
432:   UpdateWindow(windraw->hWnd);
433:   return(0);
434: }

438: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
439: {
440:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
441:   int             w,h;

444:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
445:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
446:   if (h < 1) h = 1;
447:   if (w < 1) w = 1;
448:   windraw->stringheight = h;
449:   windraw->stringwidth  = w;
450:   return(0);
451: }
454: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
455: {
456:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
457:   double          scaleX   = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
458:   double          scaleY   = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);

461:   if (height) *height = (double)windraw->stringheight*scaleY;
462:   if (width)  *width  = (double)windraw->stringwidth*scaleX;
463:   return(0);
464: }

468: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
469: {
470:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
471:   RECT            r;

474:   GetWindowRect(windraw->hWnd,&r);
475:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
476:   /* set all variable dealing with window dimensions */
477:   windraw->node->bitheight = windraw->h = draw->h = h;
478:   windraw->node->bitwidth  = windraw->w = draw->w = w;
479:   /* set up graphic buffers with the new size of window */
480:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
481:   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
482:   windraw->haveresized = PETSC_TRUE;
483:   return(0);
484: }

488: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
489: {
490:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

493:   if (windraw->haveresized == 1) PetscFunctionReturn(1);
494:   else return(0);
495: }

499: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
500: {
501:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

504:   SetWindowText(windraw->hWnd,title);
505:   return(0);
506: }

510: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
511: {
512:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

515:   /* clear primary buffer */
516:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
517:   /* if exists clear secondary buffer */
518:   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

520:   /* force WM_PAINT message so cleared buffer will show */
521:   InvalidateRect(windraw->hWnd,NULL,TRUE);
522:   UpdateWindow(windraw->hWnd);
523:   return(0);
524: }

528: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
529:                                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
530: {
531:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
532:   HBRUSH          hbrush;
533:   HPEN            hpen;
534:   int             p1x,p1y,p2x,p2y,p3x,p3y;
535:   HDC             bit;

538:   AverageColorTriangle_Win32(draw,c1,c2,c3);
539:   hbrush = CreateSolidBrush(windraw->currentcolor);
540:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
541:   p1x    = XTRANS(draw,windraw,x1);
542:   p2x    = XTRANS(draw,windraw,x2);
543:   p3x    = XTRANS(draw,windraw,x3);
544:   p1y    = YTRANS(draw,windraw,yone);
545:   p2y    = YTRANS(draw,windraw,y2);
546:   p3y    = YTRANS(draw,windraw,y3);

548:   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
549:   else                               bit = windraw->node->Buffer;

551:   BeginPath(bit);
552:   MoveToEx(bit,p1x,p1y,NULL);
553:   LineTo(bit,p2x,p2y);
554:   LineTo(bit,p3x,p3y);
555:   LineTo(bit,p1x,p1y);
556:   EndPath(bit);
557:   SelectPen(bit,hpen);
558:   SelectBrush(bit,hbrush);
559:   StrokeAndFillPath(bit);
560:   /* Forces a WM_PAINT message and erases background */
561:   InvalidateRect(windraw->hWnd,NULL,TRUE);
562:   UpdateWindow(windraw->hWnd);
563:   return(0);
564: }

568: void PopMessageLoopThread_Win32(PetscDraw popdraw)
569: {
570:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
571:   MSG             msg;
572:   HWND            hWnd = NULL;
573:   char            PopClassName [MAX_LOADSTRING + 1];
574:   RECT            r;
575:   int             width,height;
576:   WNDCLASSEX      myclass;
577:   LPVOID          lpMsgBuf;

580:   /* initialize window class parameters */
581:   myclass.cbSize        = sizeof(WNDCLASSEX);
582:   myclass.style         = CS_OWNDC;
583:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
584:   myclass.cbClsExtra    = 0;
585:   myclass.cbWndExtra    = 0;
586:   myclass.hInstance     = NULL;
587:   myclass.hIcon         = NULL;
588:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
589:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
590:   myclass.lpszMenuName  = NULL;
591:   myclass.lpszClassName = PopClassName;
592:   myclass.hIconSm       = NULL;

594:   RegisterClassEx(&myclass);

596:   SetRect(&r,0,0,450,450);

598:   width  = (r.right - r.left) / 3;
599:   height = (r.bottom - r.top) / 3;

601:   hWnd = CreateWindowEx(0,
602:                         PopClassName,
603:                         NULL,
604:                         WS_POPUPWINDOW | WS_CAPTION,
605:                         0,0,
606:                         width,height,
607:                         NULL,
608:                         NULL,
609:                         hInst,
610:                         NULL);
611:   pop->x = 0;
612:   pop->y = 0;
613:   pop->w = width;
614:   pop->h = height;

616:   if (!hWnd) {
617:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
618:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
619:     LocalFree(lpMsgBuf);
620:     exit(0);
621:   }
622:   pop->hWnd = hWnd;
623:   /* display and update new popup window */
624:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
625:   UpdateWindow(pop->hWnd);
626:   SetEvent(pop->hReadyEvent);

628:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
629:     TranslateMessage(&msg);
630:     DispatchMessage(&msg);
631:   }
632:   PetscFunctionReturnVoid();
633: }

637: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
638: {
639:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

642:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
643:   PetscFree(draw->data);
644:   return(0);
645: }

649: void MessageLoopThread_Win32(PetscDraw draw)
650: {
651:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
652:   MSG             msg;
653:   HWND            hWnd = NULL;
654:   char            classname[MAX_LOADSTRING + 1];
655:   WNDCLASSEX      wclass;
656:   LPVOID          lpMsgBuf;

659:   /* initialize window class parameters */
660:   wclass.cbSize        = sizeof(WNDCLASSEX);
661:   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
662:   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
663:   wclass.cbClsExtra    = 0;
664:   wclass.cbWndExtra    = 0;
665:   wclass.hInstance     = NULL;
666:   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
667:   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
668:   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
669:   wclass.lpszMenuName  = NULL;
670:   wclass.lpszClassName = classname;
671:   wclass.hIconSm       = NULL;

673:   RegisterClassEx(&wclass);


676:   hWnd = CreateWindowEx(0,
677:                         classname,
678:                         NULL,
679:                         WS_OVERLAPPEDWINDOW,
680:                         draw->x,
681:                         draw->y,
682:                         draw->w,
683:                         draw->h,
684:                         NULL,
685:                         NULL,
686:                         hInst,
687:                         NULL);

689:   if (!hWnd) {
690:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
691:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
692:     LocalFree(lpMsgBuf);
693:     exit(0);
694:   }
695:   windraw->hWnd = hWnd;
696:   /* display and update new window */
697:   ShowWindow(hWnd,SW_SHOWNORMAL);
698:   UpdateWindow(hWnd);
699:   SetEvent(windraw->hReadyEvent);

701:   while (GetMessage(&msg,hWnd, 0, 0)) {
702:     TranslateMessage(&msg);
703:     DispatchMessage(&msg);
704:   }
705:   PetscFunctionReturnVoid();
706: }


709: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
710:                                       PetscDrawFlush_Win32,
711:                                       PetscDrawLine_Win32,
712:                                       PetscDrawLineSetWidth_Win32,
713:                                       PetscDrawLineGetWidth_Win32,
714:                                       PetscDrawPoint_Win32,
715:                                       PetscDrawPointSetSize_Win32,
716:                                       PetscDrawString_Win32,
717:                                       PetscDrawStringVertical_Win32,
718:                                       PetscDrawStringSetSize_Win32,
719:                                       PetscDrawStringGetSize_Win32,
720:                                       0,
721:                                       PetscDrawClear_Win32,
722:                                       PetscDrawRectangle_Win32,
723:                                       PetscDrawTriangle_Win32,
724:                                       0,
725:                                       PetscDrawGetMouseButton_Win32,
726:                                       PetscDrawPause_Win32,
727:                                       0,
728:                                       0,
729:                                       PetscDrawGetPopup_Win32,
730:                                       PetscDrawSetTitle_Win32,
731:                                       PetscDrawCheckResizedWindow_Win32,
732:                                       PetscDrawResizeWindow_Win32,
733:                                       PetscDrawDestroy_Win32,
734:                                       0,
735:                                       0,
736:                                       0,
737:                                       0};

741: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
742: {
743:   PetscErrorCode  ierr;
744:   PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
745:   PetscBool       flg  = PETSC_TRUE;

748:   PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);
749:   if (flg) {
750:     PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);
751:     PetscDrawSetType(*popup,PETSC_DRAW_WIN32);
752:     draw->popup = *popup;
753:   } else {
754:     *popup = NULL;
755:   }
756:   return(0);
757: }
760: PETSC_EXTERN PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
761: {
762:   PetscDraw_Win32 *windraw;
763:   HANDLE          hThread = NULL;
764:   PetscErrorCode  ierr;
765:   WindowNode      newnode;

768:   PetscNew(&windraw);
769:   draw->data = windraw;

771:   /* the following is temporary fix for initializing a global datastructure */
772:   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
773:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));

775:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
776:   /* makes call to MessageLoopThread to creat window and attach a thread */
777:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
778:   CloseHandle(hThread);
779:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
780:   CloseHandle(windraw->hReadyEvent);
781:   WaitForSingleObject(g_hWindowListMutex,INFINITE);

783:   PetscNew(&newnode);
784:   newnode->MouseListHead = NULL;
785:   newnode->MouseListTail = NULL;
786:   newnode->wnext         = WindowListHead;
787:   newnode->wprev         = NULL;
788:   newnode->hWnd          = windraw->hWnd;
789:   if (WindowListHead) WindowListHead->wprev = newnode;
790:   WindowListHead         = newnode;
791:   windraw->hdc           = GetDC(windraw->hWnd);

793:   windraw->stringheight  = 10;
794:   windraw->stringwidth   = 6;
795:   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
796:   windraw->pointdiameter = 1;
797:   windraw->node          = newnode;

799:   windraw->x = draw->x;
800:   windraw->y = draw->y;
801:   windraw->w = newnode->bitwidth    = draw->w;
802:   windraw->h = newnode->bitheight   = draw->h;

804:   /* Create and initialize primary graphics buffer */
805:   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
806:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
807:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
808:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

810:   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
811:   newnode->DoubleBuffered = PETSC_FALSE;

813:   ReleaseDC(windraw->hWnd,windraw->hdc);
814:   ReleaseMutex(g_hWindowListMutex);
815:   return(0);
816: }


819: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
820:    PURPOSE:  Processes messages for the main window.
821:    WM_COMMAND  - process the application menu
822:    WM_PAINT    - Paint the main window
823:    WM_DESTROY  - post a quit message and return */

827: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
828: {
829:   int wmId, wmEvent;

832:   switch (message) {
833:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
834:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
835:   case WM_COMMAND:
836:     wmId    = LOWORD(wParam);
837:     wmEvent = HIWORD(wParam);
838:     /* Parse the menu selections:*/
839:     switch (wmId) {
840:     case IDM_EXIT:
841:       DestroyWindow(hWnd);
842:       break;
843:     default:
844:       return DefWindowProc(hWnd, message, wParam, lParam);
845:     }
846:     break;
847:   case WM_LBUTTONUP:
848:     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
849:     break;
850:   case WM_RBUTTONUP:
851:     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
852:     break;
853:   case WM_MBUTTONUP:
854:     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
855:     break;
856:   default:
857:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
858:   }
859:   return(0);
860: }

864: static void OnPaint_Win32(HWND hWnd)
865: {
866:   PAINTSTRUCT ps;
867:   HDC         hdc;
868:   WindowNode  current = NULL;

871:   InvalidateRect(hWnd,NULL,TRUE);
872:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
873:   current = WindowListHead;
874:   hdc     = BeginPaint(hWnd, &ps);

876:   while (current) {
877:     if (current->hWnd == hWnd) {
878:       /* flushes primary buffer to window */
879:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
880:              current->Buffer,0,0,SRCCOPY);

882:       /* StretchBlt(hdc,0,0,w,h,
883:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
884:       break;
885:     }
886:     current = current->wnext;
887:   }
888:   EndPaint(hWnd, &ps);
889:   ReleaseMutex(g_hWindowListMutex);
890:   PetscFunctionReturnVoid();
891: }

895: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
896: {
897:   /* Called by all three mouse button actions
898:     Records needed mouse data in windows data structure */
899:   WindowNode     current = NULL;
900:   MouseNode      newnode;
901:   POINT          mousepos;

905:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
906:   current = WindowListHead;
907:   if (current->IsGetMouseOn == TRUE) {

909:     SetEvent(current->event);
910:     while (current) {
911:       if (current->hWnd == hWnd) {

913:         PetscNew(&newnode);
914:         newnode->Button = button;
915:         GetCursorPos(&mousepos);
916:         newnode->user.x = mousepos.x;
917:         newnode->user.y = mousepos.y;
918:         ScreenToClient(hWnd,&mousepos);
919:         newnode->phys.x = mousepos.x;
920:         newnode->phys.y = mousepos.y;
921:         if (!current->MouseListTail) {
922:           current->MouseListHead = newnode;
923:           current->MouseListTail = newnode;
924:         } else {
925:           current->MouseListTail->mnext = newnode;
926:           current->MouseListTail        = newnode;
927:         }
928:         newnode->mnext = NULL;

930:         break;
931:       }
932:       current = current->wnext;
933:     }
934:   }
935:   ReleaseMutex(g_hWindowListMutex);
936:   return(0);
937: }

941: static void OnDestroy_Win32(HWND hWnd)
942: {
943:   /* searches linked list of window data and frees corresponding memory */
944:   WindowNode current;

947:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
948:   current = WindowListHead;

950:   SetEvent(current->event);
951:   while (current) {
952:     if (current->hWnd == hWnd) {
953:       if (current->wprev) current->wprev->wnext = current->wnext;
954:       else WindowListHead = current->wnext;
955:       if (current->MouseListHead) deletemouselist_Win32(current);
956:       else PetscFree(current);
957:       break;
958:     }
959:     current = current->wnext;
960:   }
961:   ReleaseMutex(g_hWindowListMutex);
962:   PostQuitMessage(0);
963:   PetscFunctionReturnVoid();
964: }