1 2 #include <petscsys.h> 3 #include <petsc/private/drawimpl.h> 4 #include <../src/sys/classes/draw/impls/win32/win32draw.h> 5 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 11 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 24 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)))) 33 34 HINSTANCE hInst; 35 HANDLE g_hWindowListMutex = NULL; 36 WindowNode WindowListHead = NULL; 37 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}; 42 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*); 53 54 static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw) 55 { 56 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 57 HDC hdc = GetDC(windraw->hWnd); 58 59 PetscFunctionBegin; 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); 68 69 windraw->node->DoubleBuffered = PETSC_TRUE; 70 ReleaseDC(windraw->hWnd,hdc); 71 PetscFunctionReturn(0); 72 } 73 74 static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw) 75 { 76 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 77 HDC hdc = GetDC(windraw->hWnd); 78 79 PetscFunctionBegin; 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 PetscFunctionReturn(0); 88 } 89 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; 94 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 } 106 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; 112 113 PetscFunctionBegin; 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); 145 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 PetscFunctionReturn(0); 150 } 151 152 static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw) 153 { 154 PetscFunctionBegin; 155 PetscSleep(draw->pause); 156 PetscFunctionReturn(0); 157 } 158 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 } 166 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 } 177 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 } 188 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; 196 197 PetscFunctionBegin; 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); 206 207 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 208 else hdc = windraw->node->Buffer; 209 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 PetscFunctionReturn(0); 215 } 216 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; 223 224 PetscFunctionBegin; 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; 231 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 PetscFunctionReturn(0); 239 } 240 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; 246 247 PetscFunctionBegin; 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 */ 252 253 windraw->linewidth = finalwidth; 254 PetscFunctionReturn(0); 255 } 256 257 static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width) 258 { 259 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 260 261 PetscFunctionBegin; 262 *width = (PetscReal)windraw->linewidth; 263 PetscFunctionReturn(0); 264 } 265 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; 274 275 PetscFunctionBegin; 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; 282 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 PetscFunctionReturn(0); 295 } 296 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; 302 303 PetscFunctionBegin; 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 PetscFunctionReturn(0); 310 } 311 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; 320 321 PetscFunctionBegin; 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; 328 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; 342 343 hfont = CreateFontIndirect(&logfont); 344 TranslateColor_Win32(draw,color); 345 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 346 else hdc = windraw->node->Buffer; 347 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 PetscFunctionReturn(0); 356 } 357 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; 366 367 PetscFunctionBegin; 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; 374 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; 388 389 hfont = CreateFontIndirect(&logfont); 390 TranslateColor_Win32(draw,color); 391 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 392 else hdc = windraw->node->Buffer; 393 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 PetscFunctionReturn(0); 402 } 403 404 static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height) 405 { 406 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 407 int w,h; 408 409 PetscFunctionBegin; 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 PetscFunctionReturn(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); 423 424 PetscFunctionBegin; 425 if (height) *height = (double)windraw->stringheight*scaleY; 426 if (width) *width = (double)windraw->stringwidth*scaleX; 427 PetscFunctionReturn(0); 428 } 429 430 static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h) 431 { 432 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 433 RECT r; 434 435 PetscFunctionBegin; 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 PetscFunctionReturn(0); 446 } 447 448 static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw) 449 { 450 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 451 452 PetscFunctionBegin; 453 if (windraw->haveresized == 1) PetscFunctionReturn(1); 454 else PetscFunctionReturn(0); 455 } 456 457 static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[]) 458 { 459 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 460 461 PetscFunctionBegin; 462 SetWindowText(windraw->hWnd,title); 463 PetscFunctionReturn(0); 464 } 465 466 static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw) 467 { 468 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 469 470 PetscFunctionBegin; 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); 475 476 /* force WM_PAINT message so cleared buffer will show */ 477 InvalidateRect(windraw->hWnd,NULL,TRUE); 478 UpdateWindow(windraw->hWnd); 479 PetscFunctionReturn(0); 480 } 481 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; 490 491 PetscFunctionBegin; 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); 501 502 if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer; 503 else bit = windraw->node->Buffer; 504 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 PetscFunctionReturn(0); 518 } 519 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; 530 531 PetscFunctionBegin; 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; 545 546 RegisterClassEx(&myclass); 547 548 SetRect(&r,0,0,450,450); 549 550 width = (r.right - r.left) / 3; 551 height = (r.bottom - r.top) / 3; 552 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; 567 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); 579 580 while (GetMessage(&msg, pop->hWnd, 0, 0)) { 581 TranslateMessage(&msg); 582 DispatchMessage(&msg); 583 } 584 PetscFunctionReturnVoid(); 585 } 586 587 static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw) 588 { 589 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 590 591 PetscFunctionBegin; 592 SendMessage(windraw->hWnd,WM_DESTROY,0,0); 593 PetscFree(draw->data); 594 PetscFunctionReturn(0); 595 } 596 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; 605 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; 619 620 RegisterClassEx(&wclass); 621 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); 634 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); 646 647 while (GetMessage(&msg,hWnd, 0, 0)) { 648 TranslateMessage(&msg); 649 DispatchMessage(&msg); 650 } 651 return; 652 } 653 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}; 683 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; 689 690 PetscFunctionBegin; 691 ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);CHKERRQ(ierr); 692 if (flg) { 693 ierr = PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);CHKERRQ(ierr); 694 ierr = PetscDrawSetType(*popup,PETSC_DRAW_WIN32);CHKERRQ(ierr); 695 draw->popup = *popup; 696 } else { 697 *popup = NULL; 698 } 699 PetscFunctionReturn(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; 707 708 PetscFunctionBegin; 709 ierr = PetscNew(&windraw);CHKERRQ(ierr); 710 draw->data = windraw; 711 712 /* the following is temporary fix for initializing a global datastructure */ 713 if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL); 714 ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr); 715 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); 723 724 ierr = PetscNew(&newnode);CHKERRQ(ierr); 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); 733 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; 739 740 windraw->x = draw->x; 741 windraw->y = draw->y; 742 windraw->w = newnode->bitwidth = draw->w; 743 windraw->h = newnode->bitheight = draw->h; 744 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); 750 751 newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL); 752 newnode->DoubleBuffered = PETSC_FALSE; 753 754 ReleaseDC(windraw->hWnd,windraw->hdc); 755 ReleaseMutex(g_hWindowListMutex); 756 PetscFunctionReturn(0); 757 } 758 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 */ 764 765 LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 766 { 767 int wmId; 768 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 } 797 798 static void OnPaint_Win32(HWND hWnd) 799 { 800 PAINTSTRUCT ps; 801 HDC hdc; 802 WindowNode current = NULL; 803 804 InvalidateRect(hWnd,NULL,TRUE); 805 WaitForSingleObject(g_hWindowListMutex, INFINITE); 806 current = WindowListHead; 807 hdc = BeginPaint(hWnd, &ps); 808 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); 814 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 } 825 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; 833 PetscErrorCode ierr; 834 835 PetscFunctionBegin; 836 WaitForSingleObject(g_hWindowListMutex, INFINITE); 837 current = WindowListHead; 838 if (current->IsGetMouseOn == TRUE) { 839 840 SetEvent(current->event); 841 while (current) { 842 if (current->hWnd == hWnd) { 843 844 ierr = PetscNew(&newnode);CHKERRQ(ierr); 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; 860 861 break; 862 } 863 current = current->wnext; 864 } 865 } 866 ReleaseMutex(g_hWindowListMutex); 867 PetscFunctionReturn(0); 868 } 869 870 static void OnDestroy_Win32(HWND hWnd) 871 { 872 /* searches linked list of window data and frees corresponding memory */ 873 WindowNode current; 874 875 PetscFunctionBegin; 876 WaitForSingleObject(g_hWindowListMutex, INFINITE); 877 current = WindowListHead; 878 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 } 894