Date: 2022-03-31T04:46:00+00:00

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: }