Actual source code: win32draw.c


  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);

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

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

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

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

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

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

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

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

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

149: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
150: {
151:   PetscSleep(draw->pause);
152:   return 0;
153: }

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

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

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

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

193:   x1   = XTRANS(draw,windraw,xl);
194:   x2   = XTRANS(draw,windraw,xr);
195:   yone = YTRANS(draw,windraw,yl);
196:   y2   = YTRANS(draw,windraw,yr);
197:   SetRect(&rect,x1,y2,x2,yone);
198:   if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
199:   else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
200:   hbrush = CreateSolidBrush(windraw->currentcolor);

202:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
203:   else                               hdc = windraw->node->Buffer;

205:   FillRect(hdc,&rect,hbrush);
206:   /* Forces a WM_PAINT message and erases background */
207:   InvalidateRect(windraw->hWnd,NULL,TRUE);
208:   UpdateWindow(windraw->hWnd);
209:   return 0;
210: }

212: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
213: {
214:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
215:   HPEN            hpen;
216:   int             x1,yone,x2,y2;
217:   HDC             hdc;

219:   TranslateColor_Win32(draw,color);
220:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
221:   yone = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
222:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
223:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
224:   else                               hdc = windraw->node->Buffer;

226:   SelectPen(hdc,hpen);
227:   MoveToEx(hdc,x1,yone,NULL);
228:   LineTo(hdc,x2,y2);
229:   /* Forces a WM_PAINT message and erases background */
230:   InvalidateRect(windraw->hWnd,NULL,TRUE);
231:   UpdateWindow(windraw->hWnd);
232:   return 0;
233: }

235: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
236: {
237:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
238:   int             averagesize,finalwidth;
239:   RECT            rect;

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

246:   windraw->linewidth = finalwidth;
247:   return 0;
248: }

250: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
251: {
252:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

254:   *width = (PetscReal)windraw->linewidth;
255:   return 0;
256: }

258: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
259: {
260:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
261:   HBRUSH          hbrush;
262:   HRGN            hrgn;
263:   int             radius;
264:   int             x1,yone;
265:   HDC             hdc;

267:   TranslateColor_Win32(draw,color);
268:   x1     = XTRANS(draw,windraw,x);
269:   yone   = YTRANS(draw,windraw,y);
270:   hbrush = CreateSolidBrush(windraw->currentcolor);
271:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
272:   else                               hdc = windraw->node->Buffer;

274:   /* desired size is one logical pixel so just turn it on */
275:   if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
276:   else {
277:     /* draw point around position determined */
278:     radius = windraw->pointdiameter/2; /* integer division */
279:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
280:     FillRgn(hdc,hrgn,hbrush);
281:   }
282:   /* Forces a WM_PAINT and erases background */
283:   InvalidateRect(windraw->hWnd,NULL,TRUE);
284:   UpdateWindow(windraw->hWnd);
285:   return 0;
286: }

288: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
289: {
290:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
291:   int             averagesize,diameter;
292:   RECT            rect;

294:   GetClientRect(windraw->hWnd,&rect);
295:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
296:   diameter    = (int)PetscFloorReal(averagesize*width);
297:   if (diameter < 1) diameter = 1;
298:   windraw->pointdiameter = diameter;
299:   return 0;
300: }

302: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
303: {
304:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
305:   RECT            r;
306:   HFONT           hfont;
307:   LOGFONT         logfont;
308:   int             x1,yone;
309:   HDC             hdc;

311:   x1       = XTRANS(draw,windraw,x);
312:   yone     = YTRANS(draw,windraw,y);
313:   r.bottom = yone;
314:   r.left   = x1;
315:   r.right  = x1 + 1;
316:   r.top    = yone + 1;

318:   logfont.lfHeight         = windraw->stringheight;
319:   logfont.lfWidth          = windraw->stringwidth;
320:   logfont.lfEscapement     = 0;
321:   logfont.lfOrientation    = 0;
322:   logfont.lfCharSet        = 0;
323:   logfont.lfClipPrecision  = 0;
324:   logfont.lfItalic         = 0;
325:   logfont.lfOutPrecision   = 0;
326:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
327:   logfont.lfQuality        = DEFAULT_QUALITY;
328:   logfont.lfStrikeOut      = 0;
329:   logfont.lfUnderline      = 0;
330:   logfont.lfWeight         = FW_NORMAL;

332:   hfont = CreateFontIndirect(&logfont);
333:   TranslateColor_Win32(draw,color);
334:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
335:   else                               hdc = windraw->node->Buffer;

337:   SelectFont(hdc,hfont);
338:   SetTextColor(hdc,windraw->currentcolor);
339:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
340:   DeleteObject(hfont);
341:   /* Forces a WM_PAINT message and erases background */
342:   InvalidateRect(windraw->hWnd,NULL,TRUE);
343:   UpdateWindow(windraw->hWnd);
344:   return 0;
345: }

347: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
348: {
349:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
350:   RECT            r;
351:   HFONT           hfont;
352:   LOGFONT         logfont;
353:   int             x1,yone;
354:   HDC             hdc;

356:   x1       = XTRANS(draw,windraw,x);
357:   yone     = YTRANS(draw,windraw,y);
358:   r.left   = x1;
359:   r.bottom = yone + 30;
360:   r.right  = x1 + 1;
361:   r.top    = yone - 30;

363:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
364:   logfont.lfHeight         = windraw->stringheight;
365:   logfont.lfWidth          = windraw->stringwidth;
366:   logfont.lfOrientation    = 0;
367:   logfont.lfCharSet        = DEFAULT_CHARSET;
368:   logfont.lfClipPrecision  = 0;
369:   logfont.lfItalic         = 0;
370:   logfont.lfOutPrecision   = 0;
371:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
372:   logfont.lfQuality        = DEFAULT_QUALITY;
373:   logfont.lfStrikeOut      = 0;
374:   logfont.lfUnderline      = 0;
375:   logfont.lfWeight         = FW_NORMAL;

377:   hfont = CreateFontIndirect(&logfont);
378:   TranslateColor_Win32(draw,color);
379:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
380:   else                               hdc = windraw->node->Buffer;

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

392: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
393: {
394:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
395:   int             w,h;

397:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
398:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
399:   if (h < 1) h = 1;
400:   if (w < 1) w = 1;
401:   windraw->stringheight = h;
402:   windraw->stringwidth  = w;
403:   return 0;
404: }
405: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
406: {
407:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
408:   double          scaleX   = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
409:   double          scaleY   = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);

411:   if (height) *height = (double)windraw->stringheight*scaleY;
412:   if (width)  *width  = (double)windraw->stringwidth*scaleX;
413:   return 0;
414: }

416: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
417: {
418:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
419:   RECT            r;

421:   GetWindowRect(windraw->hWnd,&r);
422:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
423:   /* set all variable dealing with window dimensions */
424:   windraw->node->bitheight = windraw->h = draw->h = h;
425:   windraw->node->bitwidth  = windraw->w = draw->w = w;
426:   /* set up graphic buffers with the new size of window */
427:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
428:   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
429:   windraw->haveresized = PETSC_TRUE;
430:   return 0;
431: }

433: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
434: {
435:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

437:   if (windraw->haveresized == 1) return 1;
438:   else return 0;
439: }

441: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
442: {
443:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

445:   SetWindowText(windraw->hWnd,title);
446:   return 0;
447: }

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

453:   /* clear primary buffer */
454:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
455:   /* if exists clear secondary buffer */
456:   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

458:   /* force WM_PAINT message so cleared buffer will show */
459:   InvalidateRect(windraw->hWnd,NULL,TRUE);
460:   UpdateWindow(windraw->hWnd);
461:   return 0;
462: }

464: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
465:                                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
466: {
467:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
468:   HBRUSH          hbrush;
469:   HPEN            hpen;
470:   int             p1x,p1y,p2x,p2y,p3x,p3y;
471:   HDC             bit;

473:   AverageColorTriangle_Win32(draw,c1,c2,c3);
474:   hbrush = CreateSolidBrush(windraw->currentcolor);
475:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
476:   p1x    = XTRANS(draw,windraw,x1);
477:   p2x    = XTRANS(draw,windraw,x2);
478:   p3x    = XTRANS(draw,windraw,x3);
479:   p1y    = YTRANS(draw,windraw,yone);
480:   p2y    = YTRANS(draw,windraw,y2);
481:   p3y    = YTRANS(draw,windraw,y3);

483:   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
484:   else                               bit = windraw->node->Buffer;

486:   BeginPath(bit);
487:   MoveToEx(bit,p1x,p1y,NULL);
488:   LineTo(bit,p2x,p2y);
489:   LineTo(bit,p3x,p3y);
490:   LineTo(bit,p1x,p1y);
491:   EndPath(bit);
492:   SelectPen(bit,hpen);
493:   SelectBrush(bit,hbrush);
494:   StrokeAndFillPath(bit);
495:   /* Forces a WM_PAINT message and erases background */
496:   InvalidateRect(windraw->hWnd,NULL,TRUE);
497:   UpdateWindow(windraw->hWnd);
498:   return 0;
499: }

501: void PopMessageLoopThread_Win32(PetscDraw popdraw)
502: {
503:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
504:   MSG             msg;
505:   HWND            hWnd = NULL;
506:   const char      PopClassName[] = "PETSc Window Pop Class";
507:   RECT            r;
508:   int             width,height;
509:   WNDCLASSEX      myclass;
510:   LPVOID          lpMsgBuf;

512:   /* initialize window class parameters */
513:   myclass.cbSize        = sizeof(WNDCLASSEX);
514:   myclass.style         = CS_OWNDC;
515:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
516:   myclass.cbClsExtra    = 0;
517:   myclass.cbWndExtra    = 0;
518:   myclass.hInstance     = NULL;
519:   myclass.hIcon         = NULL;
520:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
521:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
522:   myclass.lpszMenuName  = NULL;
523:   myclass.lpszClassName = PopClassName;
524:   myclass.hIconSm       = NULL;

526:   RegisterClassEx(&myclass);

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

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

533:   hWnd = CreateWindowEx(0,
534:                         PopClassName,
535:                         NULL,
536:                         WS_POPUPWINDOW | WS_CAPTION,
537:                         0,0,
538:                         width,height,
539:                         NULL,
540:                         NULL,
541:                         hInst,
542:                         NULL);
543:   pop->x = 0;
544:   pop->y = 0;
545:   pop->w = width;
546:   pop->h = height;

548:   if (!hWnd) {
549:     lpMsgBuf = (LPVOID)"Window Not Successfully Created";
550:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
551:     LocalFree(lpMsgBuf);
552:     exit(0);
553:   }
554:   pop->hWnd = hWnd;
555:   /* display and update new popup window */
556:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
557:   UpdateWindow(pop->hWnd);
558:   SetEvent(pop->hReadyEvent);

560:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
561:     TranslateMessage(&msg);
562:     DispatchMessage(&msg);
563:   }
564:   return;
565: }

567: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
568: {
569:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

571:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
572:   PetscFree(draw->data);
573:   return 0;
574: }

576: void MessageLoopThread_Win32(PetscDraw draw)
577: {
578:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
579:   MSG             msg;
580:   HWND            hWnd = NULL;
581:   const char      classname[] = "PETSc Window Class";
582:   WNDCLASSEX      wclass;
583:   LPVOID          lpMsgBuf;

585:   /* initialize window class parameters */
586:   wclass.cbSize        = sizeof(WNDCLASSEX);
587:   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
588:   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
589:   wclass.cbClsExtra    = 0;
590:   wclass.cbWndExtra    = 0;
591:   wclass.hInstance     = NULL;
592:   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
593:   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
594:   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
595:   wclass.lpszMenuName  = NULL;
596:   wclass.lpszClassName = classname;
597:   wclass.hIconSm       = NULL;

599:   RegisterClassEx(&wclass);

601:   hWnd = CreateWindowEx(0,
602:                         classname,
603:                         NULL,
604:                         WS_OVERLAPPEDWINDOW,
605:                         draw->x,
606:                         draw->y,
607:                         draw->w,
608:                         draw->h,
609:                         NULL,
610:                         NULL,
611:                         hInst,
612:                         NULL);

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

626:   while (GetMessage(&msg,hWnd, 0, 0)) {
627:     TranslateMessage(&msg);
628:     DispatchMessage(&msg);
629:   }
630:   return;
631: }

633: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
634:                                       PetscDrawFlush_Win32,
635:                                       PetscDrawLine_Win32,
636:                                       PetscDrawLineSetWidth_Win32,
637:                                       PetscDrawLineGetWidth_Win32,
638:                                       PetscDrawPoint_Win32,
639:                                       PetscDrawPointSetSize_Win32,
640:                                       PetscDrawString_Win32,
641:                                       PetscDrawStringVertical_Win32,
642:                                       PetscDrawStringSetSize_Win32,
643:                                       PetscDrawStringGetSize_Win32,
644:                                       0,
645:                                       PetscDrawClear_Win32,
646:                                       PetscDrawRectangle_Win32,
647:                                       PetscDrawTriangle_Win32,
648:                                       0,
649:                                       PetscDrawGetMouseButton_Win32,
650:                                       PetscDrawPause_Win32,
651:                                       0,
652:                                       0,
653:                                       PetscDrawGetPopup_Win32,
654:                                       PetscDrawSetTitle_Win32,
655:                                       PetscDrawCheckResizedWindow_Win32,
656:                                       PetscDrawResizeWindow_Win32,
657:                                       PetscDrawDestroy_Win32,
658:                                       0,
659:                                       0,
660:                                       0,
661:                                       0};

663: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
664: {
665:   PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
666:   PetscBool       flg  = PETSC_TRUE;

668:   PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);
669:   if (flg) {
670:     PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);
671:     PetscDrawSetType(*popup,PETSC_DRAW_WIN32);
672:     draw->popup = *popup;
673:   } else {
674:     *popup = NULL;
675:   }
676:   return 0;
677: }
678: PETSC_EXTERN PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
679: {
680:   PetscDraw_Win32 *windraw;
681:   HANDLE          hThread = NULL;
682:   WindowNode      newnode;

684:   PetscNew(&windraw);
685:   draw->data = windraw;

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

691:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
692:   /* makes call to MessageLoopThread to creat window and attach a thread */
693:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
694:   CloseHandle(hThread);
695:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
696:   CloseHandle(windraw->hReadyEvent);
697:   WaitForSingleObject(g_hWindowListMutex,INFINITE);

699:   PetscNew(&newnode);
700:   newnode->MouseListHead = NULL;
701:   newnode->MouseListTail = NULL;
702:   newnode->wnext         = WindowListHead;
703:   newnode->wprev         = NULL;
704:   newnode->hWnd          = windraw->hWnd;
705:   if (WindowListHead) WindowListHead->wprev = newnode;
706:   WindowListHead         = newnode;
707:   windraw->hdc           = GetDC(windraw->hWnd);

709:   windraw->stringheight  = 10;
710:   windraw->stringwidth   = 6;
711:   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
712:   windraw->pointdiameter = 1;
713:   windraw->node          = newnode;

715:   windraw->x = draw->x;
716:   windraw->y = draw->y;
717:   windraw->w = newnode->bitwidth    = draw->w;
718:   windraw->h = newnode->bitheight   = draw->h;

720:   /* Create and initialize primary graphics buffer */
721:   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
722:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
723:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
724:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

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

729:   ReleaseDC(windraw->hWnd,windraw->hdc);
730:   ReleaseMutex(g_hWindowListMutex);
731:   return 0;
732: }

734: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
735:    PURPOSE:  Processes messages for the main window.
736:    WM_COMMAND  - process the application menu
737:    WM_PAINT    - Paint the main window
738:    WM_DESTROY  - post a quit message and return */

740: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
741: {
742:   int wmId;

744:   switch (message) {
745:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
746:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
747:   case WM_COMMAND:
748:     wmId    = LOWORD(wParam);
749:     /* Parse the menu selections:*/
750:     switch (wmId) {
751:     case IDM_EXIT:
752:       DestroyWindow(hWnd);
753:       break;
754:     default:
755:       return DefWindowProc(hWnd, message, wParam, lParam);
756:     }
757:     break;
758:   case WM_LBUTTONUP:
759:     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
760:     break;
761:   case WM_RBUTTONUP:
762:     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
763:     break;
764:   case WM_MBUTTONUP:
765:     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
766:     break;
767:   default:
768:     return DefWindowProc(hWnd, message, wParam, lParam);
769:   }
770:   return 0;
771: }

773: static void OnPaint_Win32(HWND hWnd)
774: {
775:   PAINTSTRUCT ps;
776:   HDC         hdc;
777:   WindowNode  current = NULL;

779:   InvalidateRect(hWnd,NULL,TRUE);
780:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
781:   current = WindowListHead;
782:   hdc     = BeginPaint(hWnd, &ps);

784:   while (current) {
785:     if (current->hWnd == hWnd) {
786:       /* flushes primary buffer to window */
787:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
788:              current->Buffer,0,0,SRCCOPY);

790:       /* StretchBlt(hdc,0,0,w,h,
791:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
792:       break;
793:     }
794:     current = current->wnext;
795:   }
796:   EndPaint(hWnd, &ps);
797:   ReleaseMutex(g_hWindowListMutex);
798:   return;
799: }

801: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
802: {
803:   /* Called by all three mouse button actions
804:     Records needed mouse data in windows data structure */
805:   WindowNode     current = NULL;
806:   MouseNode      newnode;
807:   POINT          mousepos;

809:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
810:   current = WindowListHead;
811:   if (current->IsGetMouseOn == TRUE) {

813:     SetEvent(current->event);
814:     while (current) {
815:       if (current->hWnd == hWnd) {

817:         PetscNew(&newnode);
818:         newnode->Button = button;
819:         GetCursorPos(&mousepos);
820:         newnode->user.x = mousepos.x;
821:         newnode->user.y = mousepos.y;
822:         ScreenToClient(hWnd,&mousepos);
823:         newnode->phys.x = mousepos.x;
824:         newnode->phys.y = mousepos.y;
825:         if (!current->MouseListTail) {
826:           current->MouseListHead = newnode;
827:           current->MouseListTail = newnode;
828:         } else {
829:           current->MouseListTail->mnext = newnode;
830:           current->MouseListTail        = newnode;
831:         }
832:         newnode->mnext = NULL;

834:         break;
835:       }
836:       current = current->wnext;
837:     }
838:   }
839:   ReleaseMutex(g_hWindowListMutex);
840:   return 0;
841: }

843: static void OnDestroy_Win32(HWND hWnd)
844: {
845:   /* searches linked list of window data and frees corresponding memory */
846:   WindowNode current;

848:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
849:   current = WindowListHead;

851:   SetEvent(current->event);
852:   while (current) {
853:     if (current->hWnd == hWnd) {
854:       if (current->wprev) current->wprev->wnext = current->wnext;
855:       else WindowListHead = current->wnext;
856:       if (current->MouseListHead) deletemouselist_Win32(current);
857:       else PetscFree(current);
858:       break;
859:     }
860:     current = current->wnext;
861:   }
862:   ReleaseMutex(g_hWindowListMutex);
863:   PostQuitMessage(0);
864:   return;
865: }