Date: 2022-03-04T17:37:02+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);

     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 occurred, 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;

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

    620:   RegisterClassEx(&wclass);

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

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

    647:   while (GetMessage(&msg,hWnd, 0, 0)) {
    648:     TranslateMessage(&msg);
    649:     DispatchMessage(&msg);
    650:   }
    651:   return;
    652: }

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

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

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

    709:   PetscNew(&windraw);
    710:   draw->data = windraw;

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

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

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

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

    740:   windraw->x = draw->x;
    741:   windraw->y = draw->y;
    742:   windraw->w = newnode->bitwidth    = draw->w;
    743:   windraw->h = newnode->bitheight   = draw->h;

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

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

    754:   ReleaseDC(windraw->hWnd,windraw->hdc);
    755:   ReleaseMutex(g_hWindowListMutex);
    756:   return(0);
    757: }

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

    765: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    766: {
    767:   int wmId;

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

    798: static void OnPaint_Win32(HWND hWnd)
    799: {
    800:   PAINTSTRUCT ps;
    801:   HDC         hdc;
    802:   WindowNode  current = NULL;

    804:   InvalidateRect(hWnd,NULL,TRUE);
    805:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    806:   current = WindowListHead;
    807:   hdc     = BeginPaint(hWnd, &ps);

    809:   while (current) {
    810:     if (current->hWnd == hWnd) {
    811:       /* flushes primary buffer to window */
    812:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
    813:              current->Buffer,0,0,SRCCOPY);

    815:       /* StretchBlt(hdc,0,0,w,h,
    816:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
    817:       break;
    818:     }
    819:     current = current->wnext;
    820:   }
    821:   EndPaint(hWnd, &ps);
    822:   ReleaseMutex(g_hWindowListMutex);
    823:   return;
    824: }

    826: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
    827: {
    828:   /* Called by all three mouse button actions
    829:     Records needed mouse data in windows data structure */
    830:   WindowNode     current = NULL;
    831:   MouseNode      newnode;
    832:   POINT          mousepos;

    836:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    837:   current = WindowListHead;
    838:   if (current->IsGetMouseOn == TRUE) {

    840:     SetEvent(current->event);
    841:     while (current) {
    842:       if (current->hWnd == hWnd) {

    844:         PetscNew(&newnode);
    845:         newnode->Button = button;
    846:         GetCursorPos(&mousepos);
    847:         newnode->user.x = mousepos.x;
    848:         newnode->user.y = mousepos.y;
    849:         ScreenToClient(hWnd,&mousepos);
    850:         newnode->phys.x = mousepos.x;
    851:         newnode->phys.y = mousepos.y;
    852:         if (!current->MouseListTail) {
    853:           current->MouseListHead = newnode;
    854:           current->MouseListTail = newnode;
    855:         } else {
    856:           current->MouseListTail->mnext = newnode;
    857:           current->MouseListTail        = newnode;
    858:         }
    859:         newnode->mnext = NULL;

    861:         break;
    862:       }
    863:       current = current->wnext;
    864:     }
    865:   }
    866:   ReleaseMutex(g_hWindowListMutex);
    867:   return(0);
    868: }

    870: static void OnDestroy_Win32(HWND hWnd)
    871: {
    872:   /* searches linked list of window data and frees corresponding memory */
    873:   WindowNode current;

    876:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    877:   current = WindowListHead;

    879:   SetEvent(current->event);
    880:   while (current) {
    881:     if (current->hWnd == hWnd) {
    882:       if (current->wprev) current->wprev->wnext = current->wnext;
    883:       else WindowListHead = current->wnext;
    884:       if (current->MouseListHead) deletemouselist_Win32(current);
    885:       else PetscFree(current);
    886:       break;
    887:     }
    888:     current = current->wnext;
    889:   }
    890:   ReleaseMutex(g_hWindowListMutex);
    891:   PostQuitMessage(0);
    892:   PetscFunctionReturnVoid();
    893: }