Actual source code: win32draw.c

petsc-3.12.1 2019-10-22
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*);

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

 60:   windraw->node->DoubleBuffer    = CreateCompatibleDC(hdc);
 61:   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
 62:   windraw->node->dbstore         = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
 63:   /* Fill background of second buffer */
 64:   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
 65:   /* Copy current buffer into seconf buffer and set window data as double buffered */
 66:   BitBlt(windraw->node->DoubleBuffer,0,0,windraw->w,windraw->h,
 67:          windraw->node->Buffer,0,0, SRCCOPY);

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

 74: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
 75: {
 76:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 77:   HDC             hdc      = GetDC(windraw->hWnd);

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

 90: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
 91: {
 92:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
 93:   MouseNode node;

 95:   while (deletelist->MouseListHead) {
 96:     node = deletelist->MouseListHead;
 97:     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
 98:     PetscFree(node);
 99:   }
100:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
101:   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
102:   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
103:   PetscFree(deletelist);
104:   return 0;
105: }

107: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
108: {
109:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
110:   WindowNode      current;
111:   MouseNode       node=0;

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

146:   /* Release mutex so that  other code can use
147:      the linked list now that we are done with it */
148:   ReleaseMutex(g_hWindowListMutex);
149:   return(0);
150: }

152: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
153: {
155:   PetscSleep(draw->pause);
156:   return(0);
157: }

159: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
160: {
161:   /* Maps single color value into the RGB colors in our tables */
162:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
163:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
164:   return 0;
165: }

167: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
168: {
169:   /* Averages colors given at points of rectangle and sets color from color table
170:     will be changed once the color gradient problem is worked out */
171:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
172:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
173:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
174:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
175:   return 0;
176: }

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

189: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
190: {
191:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
192:   HBRUSH          hbrush;
193:   RECT            rect;
194:   int             x1,yone,x2,y2;
195:   HDC             hdc;

198:   x1   = XTRANS(draw,windraw,xl);
199:   x2   = XTRANS(draw,windraw,xr);
200:   yone = YTRANS(draw,windraw,yl);
201:   y2   = YTRANS(draw,windraw,yr);
202:   SetRect(&rect,x1,y2,x2,yone);
203:   if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
204:   else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
205:   hbrush = CreateSolidBrush(windraw->currentcolor);

207:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
208:   else                               hdc = windraw->node->Buffer;

210:   FillRect(hdc,&rect,hbrush);
211:   /* Forces a WM_PAINT message and erases background */
212:   InvalidateRect(windraw->hWnd,NULL,TRUE);
213:   UpdateWindow(windraw->hWnd);
214:   return(0);
215: }

217: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
218: {
219:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
220:   HPEN            hpen;
221:   int             x1,yone,x2,y2;
222:   HDC             hdc;

225:   TranslateColor_Win32(draw,color);
226:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
227:   yone = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
228:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
229:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
230:   else                               hdc = windraw->node->Buffer;

232:   SelectPen(hdc,hpen);
233:   MoveToEx(hdc,x1,yone,NULL);
234:   LineTo(hdc,x2,y2);
235:   /* Forces a WM_PAINT message and erases background */
236:   InvalidateRect(windraw->hWnd,NULL,TRUE);
237:   UpdateWindow(windraw->hWnd);
238:   return(0);
239: }

241: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
242: {
243:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
244:   int             averagesize,finalwidth;
245:   RECT            rect;

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

253:   windraw->linewidth = finalwidth;
254:   return(0);
255: }

257: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
258: {
259:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

262:   *width = (PetscReal)windraw->linewidth;
263:   return(0);
264: }

266: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
267: {
268:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
269:   HBRUSH          hbrush;
270:   HRGN            hrgn;
271:   int             radius;
272:   int             x1,yone;
273:   HDC             hdc;

276:   TranslateColor_Win32(draw,color);
277:   x1     = XTRANS(draw,windraw,x);
278:   yone   = YTRANS(draw,windraw,y);
279:   hbrush = CreateSolidBrush(windraw->currentcolor);
280:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
281:   else                               hdc = windraw->node->Buffer;

283:   /* desired size is one logical pixel so just turn it on */
284:   if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
285:   else {
286:     /* draw point around position determined */
287:     radius = windraw->pointdiameter/2; /* integer division */
288:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
289:     FillRgn(hdc,hrgn,hbrush);
290:   }
291:   /* Forces a WM_PAINT and erases background */
292:   InvalidateRect(windraw->hWnd,NULL,TRUE);
293:   UpdateWindow(windraw->hWnd);
294:   return(0);
295: }

297: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
298: {
299:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
300:   int             averagesize,diameter;
301:   RECT            rect;

304:   GetClientRect(windraw->hWnd,&rect);
305:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
306:   diameter    = (int)PetscFloorReal(averagesize*width);
307:   if (diameter < 1) diameter = 1;
308:   windraw->pointdiameter = diameter;
309:   return(0);
310: }

312: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
313: {
314:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
315:   RECT            r;
316:   HFONT           hfont;
317:   LOGFONT         logfont;
318:   int             x1,yone;
319:   HDC             hdc;

322:   x1       = XTRANS(draw,windraw,x);
323:   yone     = YTRANS(draw,windraw,y);
324:   r.bottom = yone;
325:   r.left   = x1;
326:   r.right  = x1 + 1;
327:   r.top    = yone + 1;

329:   logfont.lfHeight         = windraw->stringheight;
330:   logfont.lfWidth          = windraw->stringwidth;
331:   logfont.lfEscapement     = 0;
332:   logfont.lfOrientation    = 0;
333:   logfont.lfCharSet        = 0;
334:   logfont.lfClipPrecision  = 0;
335:   logfont.lfItalic         = 0;
336:   logfont.lfOutPrecision   = 0;
337:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
338:   logfont.lfQuality        = DEFAULT_QUALITY;
339:   logfont.lfStrikeOut      = 0;
340:   logfont.lfUnderline      = 0;
341:   logfont.lfWeight         = FW_NORMAL;

343:   hfont = CreateFontIndirect(&logfont);
344:   TranslateColor_Win32(draw,color);
345:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
346:   else                               hdc = windraw->node->Buffer;

348:   SelectFont(hdc,hfont);
349:   SetTextColor(hdc,windraw->currentcolor);
350:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
351:   DeleteObject(hfont);
352:   /* Forces a WM_PAINT message and erases background */
353:   InvalidateRect(windraw->hWnd,NULL,TRUE);
354:   UpdateWindow(windraw->hWnd);
355:   return(0);
356: }

358: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
359: {
360:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
361:   RECT            r;
362:   HFONT           hfont;
363:   LOGFONT         logfont;
364:   int             x1,yone;
365:   HDC             hdc;

368:   x1       = XTRANS(draw,windraw,x);
369:   yone     = YTRANS(draw,windraw,y);
370:   r.left   = x1;
371:   r.bottom = yone + 30;
372:   r.right  = x1 + 1;
373:   r.top    = yone - 30;

375:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
376:   logfont.lfHeight         = windraw->stringheight;
377:   logfont.lfWidth          = windraw->stringwidth;
378:   logfont.lfOrientation    = 0;
379:   logfont.lfCharSet        = DEFAULT_CHARSET;
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;

389:   hfont = CreateFontIndirect(&logfont);
390:   TranslateColor_Win32(draw,color);
391:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
392:   else                               hdc = windraw->node->Buffer;

394:   SelectFont(hdc,hfont);
395:   SetTextColor(hdc,windraw->currentcolor);
396:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
397:   DeleteObject(hfont);
398:   /* Forces a WM_PAINT message and erases background */
399:   InvalidateRect(windraw->hWnd,NULL,TRUE);
400:   UpdateWindow(windraw->hWnd);
401:   return(0);
402: }

404: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
405: {
406:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
407:   int             w,h;

410:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
411:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
412:   if (h < 1) h = 1;
413:   if (w < 1) w = 1;
414:   windraw->stringheight = h;
415:   windraw->stringwidth  = w;
416:   return(0);
417: }
418: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
419: {
420:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
421:   double          scaleX   = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
422:   double          scaleY   = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);

425:   if (height) *height = (double)windraw->stringheight*scaleY;
426:   if (width)  *width  = (double)windraw->stringwidth*scaleX;
427:   return(0);
428: }

430: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
431: {
432:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
433:   RECT            r;

436:   GetWindowRect(windraw->hWnd,&r);
437:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
438:   /* set all variable dealing with window dimensions */
439:   windraw->node->bitheight = windraw->h = draw->h = h;
440:   windraw->node->bitwidth  = windraw->w = draw->w = w;
441:   /* set up graphic buffers with the new size of window */
442:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
443:   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
444:   windraw->haveresized = PETSC_TRUE;
445:   return(0);
446: }

448: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
449: {
450:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

453:   if (windraw->haveresized == 1) PetscFunctionReturn(1);
454:   else return(0);
455: }

457: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
458: {
459:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

462:   SetWindowText(windraw->hWnd,title);
463:   return(0);
464: }

466: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
467: {
468:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

471:   /* clear primary buffer */
472:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
473:   /* if exists clear secondary buffer */
474:   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

476:   /* force WM_PAINT message so cleared buffer will show */
477:   InvalidateRect(windraw->hWnd,NULL,TRUE);
478:   UpdateWindow(windraw->hWnd);
479:   return(0);
480: }

482: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
483:                                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
484: {
485:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
486:   HBRUSH          hbrush;
487:   HPEN            hpen;
488:   int             p1x,p1y,p2x,p2y,p3x,p3y;
489:   HDC             bit;

492:   AverageColorTriangle_Win32(draw,c1,c2,c3);
493:   hbrush = CreateSolidBrush(windraw->currentcolor);
494:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
495:   p1x    = XTRANS(draw,windraw,x1);
496:   p2x    = XTRANS(draw,windraw,x2);
497:   p3x    = XTRANS(draw,windraw,x3);
498:   p1y    = YTRANS(draw,windraw,yone);
499:   p2y    = YTRANS(draw,windraw,y2);
500:   p3y    = YTRANS(draw,windraw,y3);

502:   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
503:   else                               bit = windraw->node->Buffer;

505:   BeginPath(bit);
506:   MoveToEx(bit,p1x,p1y,NULL);
507:   LineTo(bit,p2x,p2y);
508:   LineTo(bit,p3x,p3y);
509:   LineTo(bit,p1x,p1y);
510:   EndPath(bit);
511:   SelectPen(bit,hpen);
512:   SelectBrush(bit,hbrush);
513:   StrokeAndFillPath(bit);
514:   /* Forces a WM_PAINT message and erases background */
515:   InvalidateRect(windraw->hWnd,NULL,TRUE);
516:   UpdateWindow(windraw->hWnd);
517:   return(0);
518: }

520: void PopMessageLoopThread_Win32(PetscDraw popdraw)
521: {
522:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
523:   MSG             msg;
524:   HWND            hWnd = NULL;
525:   const char      PopClassName[] = "PETSc Window Pop Class";
526:   RECT            r;
527:   int             width,height;
528:   WNDCLASSEX      myclass;
529:   LPVOID          lpMsgBuf;

532:   /* initialize window class parameters */
533:   myclass.cbSize        = sizeof(WNDCLASSEX);
534:   myclass.style         = CS_OWNDC;
535:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
536:   myclass.cbClsExtra    = 0;
537:   myclass.cbWndExtra    = 0;
538:   myclass.hInstance     = NULL;
539:   myclass.hIcon         = NULL;
540:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
541:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
542:   myclass.lpszMenuName  = NULL;
543:   myclass.lpszClassName = PopClassName;
544:   myclass.hIconSm       = NULL;

546:   RegisterClassEx(&myclass);

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

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

553:   hWnd = CreateWindowEx(0,
554:                         PopClassName,
555:                         NULL,
556:                         WS_POPUPWINDOW | WS_CAPTION,
557:                         0,0,
558:                         width,height,
559:                         NULL,
560:                         NULL,
561:                         hInst,
562:                         NULL);
563:   pop->x = 0;
564:   pop->y = 0;
565:   pop->w = width;
566:   pop->h = height;

568:   if (!hWnd) {
569:     lpMsgBuf = (LPVOID)"Window Not Successfully Created";
570:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
571:     LocalFree(lpMsgBuf);
572:     exit(0);
573:   }
574:   pop->hWnd = hWnd;
575:   /* display and update new popup window */
576:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
577:   UpdateWindow(pop->hWnd);
578:   SetEvent(pop->hReadyEvent);

580:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
581:     TranslateMessage(&msg);
582:     DispatchMessage(&msg);
583:   }
584:   PetscFunctionReturnVoid();
585: }

587: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
588: {
589:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

592:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
593:   PetscFree(draw->data);
594:   return(0);
595: }

597: void MessageLoopThread_Win32(PetscDraw draw)
598: {
599:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
600:   MSG             msg;
601:   HWND            hWnd = NULL;
602:   const char      classname[] = "PETSc Window Class";
603:   WNDCLASSEX      wclass;
604:   LPVOID          lpMsgBuf;

607:   /* initialize window class parameters */
608:   wclass.cbSize        = sizeof(WNDCLASSEX);
609:   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
610:   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
611:   wclass.cbClsExtra    = 0;
612:   wclass.cbWndExtra    = 0;
613:   wclass.hInstance     = NULL;
614:   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
615:   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
616:   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
617:   wclass.lpszMenuName  = NULL;
618:   wclass.lpszClassName = classname;
619:   wclass.hIconSm       = NULL;

621:   RegisterClassEx(&wclass);


624:   hWnd = CreateWindowEx(0,
625:                         classname,
626:                         NULL,
627:                         WS_OVERLAPPEDWINDOW,
628:                         draw->x,
629:                         draw->y,
630:                         draw->w,
631:                         draw->h,
632:                         NULL,
633:                         NULL,
634:                         hInst,
635:                         NULL);

637:   if (!hWnd) {
638:     lpMsgBuf = (LPVOID)"Window Not Successfully Created";
639:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
640:     LocalFree(lpMsgBuf);
641:     exit(0);
642:   }
643:   windraw->hWnd = hWnd;
644:   /* display and update new window */
645:   ShowWindow(hWnd,SW_SHOWNORMAL);
646:   UpdateWindow(hWnd);
647:   SetEvent(windraw->hReadyEvent);

649:   while (GetMessage(&msg,hWnd, 0, 0)) {
650:     TranslateMessage(&msg);
651:     DispatchMessage(&msg);
652:   }
653:   PetscFunctionReturnVoid();
654: }


657: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
658:                                       PetscDrawFlush_Win32,
659:                                       PetscDrawLine_Win32,
660:                                       PetscDrawLineSetWidth_Win32,
661:                                       PetscDrawLineGetWidth_Win32,
662:                                       PetscDrawPoint_Win32,
663:                                       PetscDrawPointSetSize_Win32,
664:                                       PetscDrawString_Win32,
665:                                       PetscDrawStringVertical_Win32,
666:                                       PetscDrawStringSetSize_Win32,
667:                                       PetscDrawStringGetSize_Win32,
668:                                       0,
669:                                       PetscDrawClear_Win32,
670:                                       PetscDrawRectangle_Win32,
671:                                       PetscDrawTriangle_Win32,
672:                                       0,
673:                                       PetscDrawGetMouseButton_Win32,
674:                                       PetscDrawPause_Win32,
675:                                       0,
676:                                       0,
677:                                       PetscDrawGetPopup_Win32,
678:                                       PetscDrawSetTitle_Win32,
679:                                       PetscDrawCheckResizedWindow_Win32,
680:                                       PetscDrawResizeWindow_Win32,
681:                                       PetscDrawDestroy_Win32,
682:                                       0,
683:                                       0,
684:                                       0,
685:                                       0};

687: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
688: {
689:   PetscErrorCode  ierr;
690:   PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
691:   PetscBool       flg  = PETSC_TRUE;

694:   PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);
695:   if (flg) {
696:     PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);
697:     PetscDrawSetType(*popup,PETSC_DRAW_WIN32);
698:     draw->popup = *popup;
699:   } else {
700:     *popup = NULL;
701:   }
702:   return(0);
703: }
704: PETSC_EXTERN PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
705: {
706:   PetscDraw_Win32 *windraw;
707:   HANDLE          hThread = NULL;
708:   PetscErrorCode  ierr;
709:   WindowNode      newnode;

712:   PetscNew(&windraw);
713:   draw->data = windraw;

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

719:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
720:   /* makes call to MessageLoopThread to creat window and attach a thread */
721:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
722:   CloseHandle(hThread);
723:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
724:   CloseHandle(windraw->hReadyEvent);
725:   WaitForSingleObject(g_hWindowListMutex,INFINITE);

727:   PetscNew(&newnode);
728:   newnode->MouseListHead = NULL;
729:   newnode->MouseListTail = NULL;
730:   newnode->wnext         = WindowListHead;
731:   newnode->wprev         = NULL;
732:   newnode->hWnd          = windraw->hWnd;
733:   if (WindowListHead) WindowListHead->wprev = newnode;
734:   WindowListHead         = newnode;
735:   windraw->hdc           = GetDC(windraw->hWnd);

737:   windraw->stringheight  = 10;
738:   windraw->stringwidth   = 6;
739:   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
740:   windraw->pointdiameter = 1;
741:   windraw->node          = newnode;

743:   windraw->x = draw->x;
744:   windraw->y = draw->y;
745:   windraw->w = newnode->bitwidth    = draw->w;
746:   windraw->h = newnode->bitheight   = draw->h;

748:   /* Create and initialize primary graphics buffer */
749:   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
750:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
751:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
752:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

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

757:   ReleaseDC(windraw->hWnd,windraw->hdc);
758:   ReleaseMutex(g_hWindowListMutex);
759:   return(0);
760: }


763: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
764:    PURPOSE:  Processes messages for the main window.
765:    WM_COMMAND  - process the application menu
766:    WM_PAINT    - Paint the main window
767:    WM_DESTROY  - post a quit message and return */

769: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
770: {
771:   int wmId;

774:   switch (message) {
775:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
776:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
777:   case WM_COMMAND:
778:     wmId    = LOWORD(wParam);
779:     /* Parse the menu selections:*/
780:     switch (wmId) {
781:     case IDM_EXIT:
782:       DestroyWindow(hWnd);
783:       break;
784:     default:
785:       return DefWindowProc(hWnd, message, wParam, lParam);
786:     }
787:     break;
788:   case WM_LBUTTONUP:
789:     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
790:     break;
791:   case WM_RBUTTONUP:
792:     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
793:     break;
794:   case WM_MBUTTONUP:
795:     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
796:     break;
797:   default:
798:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
799:   }
800:   return(0);
801: }

803: static void OnPaint_Win32(HWND hWnd)
804: {
805:   PAINTSTRUCT ps;
806:   HDC         hdc;
807:   WindowNode  current = NULL;

810:   InvalidateRect(hWnd,NULL,TRUE);
811:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
812:   current = WindowListHead;
813:   hdc     = BeginPaint(hWnd, &ps);

815:   while (current) {
816:     if (current->hWnd == hWnd) {
817:       /* flushes primary buffer to window */
818:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
819:              current->Buffer,0,0,SRCCOPY);

821:       /* StretchBlt(hdc,0,0,w,h,
822:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
823:       break;
824:     }
825:     current = current->wnext;
826:   }
827:   EndPaint(hWnd, &ps);
828:   ReleaseMutex(g_hWindowListMutex);
829:   PetscFunctionReturnVoid();
830: }

832: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
833: {
834:   /* Called by all three mouse button actions
835:     Records needed mouse data in windows data structure */
836:   WindowNode     current = NULL;
837:   MouseNode      newnode;
838:   POINT          mousepos;

842:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
843:   current = WindowListHead;
844:   if (current->IsGetMouseOn == TRUE) {

846:     SetEvent(current->event);
847:     while (current) {
848:       if (current->hWnd == hWnd) {

850:         PetscNew(&newnode);
851:         newnode->Button = button;
852:         GetCursorPos(&mousepos);
853:         newnode->user.x = mousepos.x;
854:         newnode->user.y = mousepos.y;
855:         ScreenToClient(hWnd,&mousepos);
856:         newnode->phys.x = mousepos.x;
857:         newnode->phys.y = mousepos.y;
858:         if (!current->MouseListTail) {
859:           current->MouseListHead = newnode;
860:           current->MouseListTail = newnode;
861:         } else {
862:           current->MouseListTail->mnext = newnode;
863:           current->MouseListTail        = newnode;
864:         }
865:         newnode->mnext = NULL;

867:         break;
868:       }
869:       current = current->wnext;
870:     }
871:   }
872:   ReleaseMutex(g_hWindowListMutex);
873:   return(0);
874: }

876: static void OnDestroy_Win32(HWND hWnd)
877: {
878:   /* searches linked list of window data and frees corresponding memory */
879:   WindowNode current;

882:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
883:   current = WindowListHead;

885:   SetEvent(current->event);
886:   while (current) {
887:     if (current->hWnd == hWnd) {
888:       if (current->wprev) current->wprev->wnext = current->wnext;
889:       else WindowListHead = current->wnext;
890:       if (current->MouseListHead) deletemouselist_Win32(current);
891:       else PetscFree(current);
892:       break;
893:     }
894:     current = current->wnext;
895:   }
896:   ReleaseMutex(g_hWindowListMutex);
897:   PostQuitMessage(0);
898:   PetscFunctionReturnVoid();
899: }