Date: 2013-07-02T14:38:23+00:00

Actual source code: win32draw.c
petsc-3.4.2 2013-07-02

      2: #include <petscsys.h>
      3: #include <petsc-private/drawimpl.h>
      4: #include <../src/sys/classes/draw/impls/win32/win32draw.h>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    594:   RegisterClassEx(&myclass);

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

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

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

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

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

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

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

    649: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
    650: {
    651:   /* Multi Processor is not implemeted yet */
    653:   PetscDrawFlush_Win32(draw);
    654:   return(0);
    655: }

    659: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
    660: {
    661:   /* Multi Processor is not implemeted yet */
    663:   PetscDrawClear_Win32(draw);
    664:   return(0);
    665: }

    669: void MessageLoopThread_Win32(PetscDraw draw)
    670: {
    671:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    672:   MSG             msg;
    673:   HWND            hWnd = NULL;
    674:   char            classname[MAX_LOADSTRING + 1];
    675:   WNDCLASSEX      wclass;
    676:   LPVOID          lpMsgBuf;

    679:   /* initialize window class parameters */
    680:   wclass.cbSize        = sizeof(WNDCLASSEX);
    681:   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
    682:   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
    683:   wclass.cbClsExtra    = 0;
    684:   wclass.cbWndExtra    = 0;
    685:   wclass.hInstance     = NULL;
    686:   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
    687:   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
    688:   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
    689:   wclass.lpszMenuName  = NULL;
    690:   wclass.lpszClassName = classname;
    691:   wclass.hIconSm       = NULL;

    693:   RegisterClassEx(&wclass);

    696:   hWnd = CreateWindowEx(0,
    697:                         classname,
    698:                         NULL,
    699:                         WS_OVERLAPPEDWINDOW,
    700:                         draw->x,
    701:                         draw->y,
    702:                         draw->w,
    703:                         draw->h,
    704:                         NULL,
    705:                         NULL,
    706:                         hInst,
    707:                         NULL);

    709:   if (!hWnd) {
    710:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
    711:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
    712:     LocalFree(lpMsgBuf);
    713:     exit(0);
    714:   }
    715:   windraw->hWnd = hWnd;
    716:   /* display and update new window */
    717:   ShowWindow(hWnd,SW_SHOWNORMAL);
    718:   UpdateWindow(hWnd);
    719:   SetEvent(windraw->hReadyEvent);

    721:   while (GetMessage(&msg,hWnd, 0, 0)) {
    722:     TranslateMessage(&msg);
    723:     DispatchMessage(&msg);
    724:   }
    725:   PetscFunctionReturnVoid();
    726: }

    729: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
    730:                                       PetscDrawFlush_Win32,
    731:                                       PetscDrawLine_Win32,
    732:                                       PetscDrawLineSetWidth_Win32,
    733:                                       PetscDrawLineGetWidth_Win32,
    734:                                       PetscDrawPoint_Win32,
    735:                                       PetscDrawPointSetSize_Win32,
    736:                                       PetscDrawString_Win32,
    737:                                       PetscDrawStringVertical_Win32,
    738:                                       PetscDrawStringSetSize_Win32,
    739:                                       PetscDrawStringGetSize_Win32,
    740:                                       0,
    741:                                       PetscDrawClear_Win32,
    742:                                       PetscDrawSynchronizedFlush_Win32,
    743:                                       PetscDrawRectangle_Win32,
    744:                                       PetscDrawTriangle_Win32,
    745:                                       0,
    746:                                       PetscDrawGetMouseButton_Win32,
    747:                                       PetscDrawPause_Win32,
    748:                                       PetscDrawSynchronizedClear_Win32,
    749:                                       0,
    750:                                       0,
    751:                                       PetscDrawGetPopup_Win32,
    752:                                       PetscDrawSetTitle_Win32,
    753:                                       PetscDrawCheckResizedWindow_Win32,
    754:                                       PetscDrawResizeWindow_Win32,
    755:                                       PetscDrawDestroy_Win32,
    756:                                       0,
    757:                                       0,
    758:                                       0,
    759:                                       0};

    763: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
    764: {
    765:   PetscDraw_Win32 *pop;
    766:   HANDLE          hThread = NULL;
    767:   WindowNode      newnode;
    768:   PetscErrorCode  ierr;

    771:   PetscNew(PetscDraw_Win32,&pop);

    773:   (*popdraw)->data = pop;

    775:   /* the following is temporary fix for initializing a global datastructure */
    776:   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
    777:   PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));

    779:   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    780:   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
    781:   CloseHandle(hThread);
    782:   WaitForSingleObject(pop->hReadyEvent, INFINITE);
    783:   CloseHandle(pop->hReadyEvent);
    784:   WaitForSingleObject(g_hWindowListMutex, INFINITE);

    786:   draw->popup            = (*popdraw);
    787:   PetscNew(struct _p_WindowNode,&newnode);
    788:   newnode->MouseListHead = NULL;
    789:   newnode->MouseListTail = NULL;
    790:   newnode->wnext         = WindowListHead;
    791:   newnode->wprev         = NULL;
    792:   newnode->hWnd          = pop->hWnd;
    793:   if (WindowListHead != NULL) WindowListHead->wprev = newnode;
    794:   WindowListHead         = newnode;
    795:   pop->hdc               = GetDC(pop->hWnd);

    797:   pop->stringheight  = 10;
    798:   pop->stringwidth   = 6;
    799:   pop->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
    800:   pop->pointdiameter = 1;
    801:   pop->node          = newnode;

    803:   newnode->bitwidth  = pop->w;
    804:   newnode->bitheight = pop->h;

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

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

    816:   ReleaseDC(pop->hWnd,pop->hdc);
    817:   ReleaseMutex(g_hWindowListMutex);
    818:   return(0);
    819: }

    821: EXTERN_C_BEGIN
    824: PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
    825: {
    826:   PetscDraw_Win32 *windraw;
    827:   HANDLE          hThread = NULL;
    828:   PetscErrorCode  ierr;
    829:   WindowNode      newnode;

    832:   PetscNew(PetscDraw_Win32,&windraw);
    833:   draw->data = windraw;

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

    839:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
    840:   /* makes call to MessageLoopThread to creat window and attach a thread */
    841:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
    842:   CloseHandle(hThread);
    843:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
    844:   CloseHandle(windraw->hReadyEvent);
    845:   WaitForSingleObject(g_hWindowListMutex,INFINITE);

    847:   PetscNew(struct _p_WindowNode,&newnode);
    848:   newnode->MouseListHead = NULL;
    849:   newnode->MouseListTail = NULL;
    850:   newnode->wnext         = WindowListHead;
    851:   newnode->wprev         = NULL;
    852:   newnode->hWnd          = windraw->hWnd;
    853:   if (WindowListHead != NULL) WindowListHead->wprev = newnode;
    854:   WindowListHead         = newnode;
    855:   windraw->hdc           = GetDC(windraw->hWnd);

    857:   windraw->stringheight  = 10;
    858:   windraw->stringwidth   = 6;
    859:   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
    860:   windraw->pointdiameter = 1;
    861:   windraw->node          = newnode;

    863:   windraw->x = draw->x;
    864:   windraw->y = draw->y;
    865:   windraw->w = newnode->bitwidth    = draw->w;
    866:   windraw->h = newnode->bitheight   = draw->h;

    868:   /* Create and initialize primary graphics buffer */
    869:   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
    870:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
    871:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
    872:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

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

    877:   ReleaseDC(windraw->hWnd,windraw->hdc);
    878:   ReleaseMutex(g_hWindowListMutex);
    879:   return(0);
    880: }
    881: EXTERN_C_END

    884: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
    885:    PURPOSE:  Processes messages for the main window.
    886:    WM_COMMAND  - process the application menu
    887:    WM_PAINT    - Paint the main window
    888:    WM_DESTROY  - post a quit message and return */

    892: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    893: {
    894:   int wmId, wmEvent;

    897:   switch (message) {
    898:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
    899:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
    900:   case WM_COMMAND:
    901:     wmId    = LOWORD(wParam);
    902:     wmEvent = HIWORD(wParam);
    903:     /* Parse the menu selections:*/
    904:     switch (wmId) {
    905:     case IDM_EXIT:
    906:       DestroyWindow(hWnd);
    907:       break;
    908:     default:
    909:       return DefWindowProc(hWnd, message, wParam, lParam);
    910:     }
    911:     break;
    912:   case WM_LBUTTONUP:
    913:     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
    914:     break;
    915:   case WM_RBUTTONUP:
    916:     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
    917:     break;
    918:   case WM_MBUTTONUP:
    919:     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
    920:     break;
    921:   default:
    922:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
    923:   }
    924:   return(0);
    925: }

    929: static void OnPaint_Win32(HWND hWnd)
    930: {
    931:   PAINTSTRUCT ps;
    932:   HDC         hdc;
    933:   WindowNode  current = NULL;

    936:   InvalidateRect(hWnd,NULL,TRUE);
    937:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    938:   current = WindowListHead;
    939:   hdc     = BeginPaint(hWnd, &ps);

    941:   while (current != NULL) {
    942:     if (current->hWnd == hWnd) {
    943:       /* flushes primary buffer to window */
    944:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
    945:              current->Buffer,0,0,SRCCOPY);

    947:       /* StretchBlt(hdc,0,0,w,h,
    948:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
    949:       break;
    950:     }
    951:     current = current->wnext;
    952:   }
    953:   EndPaint(hWnd, &ps);
    954:   ReleaseMutex(g_hWindowListMutex);
    955:   PetscFunctionReturnVoid();
    956: }

    960: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
    961: {
    962:   /* Called by all three mouse button actions
    963:     Records needed mouse data in windows data structure */
    964:   WindowNode     current = NULL;
    965:   MouseNode      newnode;
    966:   POINT          mousepos;

    970:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    971:   current = WindowListHead;
    972:   if (current->IsGetMouseOn == TRUE) {

    974:     SetEvent(current->event);
    975:     while (current != NULL) {
    976:       if (current->hWnd == hWnd) {

    978:         PetscNew(struct _p_MouseNode,&newnode);
    979:         newnode->Button = button;
    980:         GetCursorPos(&mousepos);
    981:         newnode->user.x = mousepos.x;
    982:         newnode->user.y = mousepos.y;
    983:         ScreenToClient(hWnd,&mousepos);
    984:         newnode->phys.x = mousepos.x;
    985:         newnode->phys.y = mousepos.y;
    986:         if (!current->MouseListTail) {
    987:           current->MouseListHead = newnode;
    988:           current->MouseListTail = newnode;
    989:         } else {
    990:           current->MouseListTail->mnext = newnode;
    991:           current->MouseListTail        = newnode;
    992:         }
    993:         newnode->mnext = NULL;

    995:         break;
    996:       }
    997:       current = current->wnext;
    998:     }
    999:   }
    1000:   ReleaseMutex(g_hWindowListMutex);
    1001:   return(0);
    1002: }

    1006: static void OnDestroy_Win32(HWND hWnd)
    1007: {
    1008:   /* searches linked list of window data and frees corresponding memory */
    1009:   WindowNode current;

    1012:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    1013:   current = WindowListHead;

    1015:   SetEvent(current->event);
    1016:   while (current != NULL) {
    1017:     if (current->hWnd == hWnd) {
    1018:       if (current->wprev != NULL) current->wprev->wnext = current->wnext;
    1019:       else WindowListHead = current->wnext;
    1020:       if (current->MouseListHead) deletemouselist_Win32(current);
    1021:       else PetscFree(current);
    1022:       break;
    1023:     }
    1024:     current = current->wnext;
    1025:   }
    1026:   ReleaseMutex(g_hWindowListMutex);
    1027:   PostQuitMessage(0);
    1028:   PetscFunctionReturnVoid();
    1029: }