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 #undef __FUNCT__ 55 #define __FUNCT__ "PetscDrawSetDoubleBuffer_Win32" 56 static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw) 57 { 58 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 59 HDC hdc = GetDC(windraw->hWnd); 60 61 PetscFunctionBegin; 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, 69 0,0, 70 windraw->w,windraw->h, 71 windraw->node->Buffer, 72 0,0, 73 SRCCOPY); 74 75 windraw->node->DoubleBuffered = PETSC_TRUE; 76 ReleaseDC(windraw->hWnd,hdc); 77 PetscFunctionReturn(0); 78 } 79 80 #undef __FUNCT__ 81 #define __FUNCT__ "PetscDrawFlush_Win32" 82 static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw) 83 { 84 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 85 HDC hdc = GetDC(windraw->hWnd); 86 87 PetscFunctionBegin; 88 /* flush double buffer into primary buffer */ 89 BitBlt(windraw->node->Buffer, 90 0,0, 91 windraw->w,windraw->h, 92 windraw->node->DoubleBuffer, 93 0,0, 94 SRCCOPY); 95 /* flush double buffer into window */ 96 BitBlt(hdc, 97 0,0, 98 windraw->w,windraw->h, 99 windraw->node->DoubleBuffer, 100 0,0, 101 SRCCOPY); 102 ReleaseDC(windraw->hWnd,hdc); 103 PetscFunctionReturn(0); 104 } 105 106 #undef __FUNCT__ 107 #define __FUNCT__ "deletemouselist_Win32" 108 static PetscErrorCode deletemouselist_Win32(WindowNode deletelist) 109 { 110 /* Called upon window close. Frees memory of linked list of stored mouse commands */ 111 MouseNode node; 112 113 while (deletelist->MouseListHead != NULL) { 114 node = deletelist->MouseListHead; 115 if (deletelist->MouseListHead->mnext != NULL) { 116 deletelist->MouseListHead = deletelist->MouseListHead->mnext; 117 } 118 PetscFree(node); 119 } 120 deletelist->MouseListHead = deletelist->MouseListTail = NULL; 121 if (deletelist->wprev != NULL) { 122 deletelist->wprev->wnext = deletelist->wnext; 123 } 124 if (deletelist->wnext != NULL) { 125 deletelist->wnext->wprev = deletelist->wprev; 126 } 127 PetscFree(deletelist); 128 return 0; 129 } 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "PetscDrawGetMouseButton_Win32" 133 static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys) 134 { 135 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 136 WindowNode current; 137 MouseNode node=0; 138 139 PetscFunctionBegin; 140 /* Make sure no other code is using the linked list at this moment */ 141 WaitForSingleObject(g_hWindowListMutex, INFINITE); 142 /* Look for the node that matches the window you are using */ 143 current = WindowListHead; 144 while (current != NULL) { 145 if (current->hWnd == windraw->hWnd) { 146 current->IsGetMouseOn = TRUE; 147 break; 148 } else { 149 current = current->wnext; 150 } 151 } 152 /* If no actions have occured, wait for one */ 153 node = current->MouseListHead; 154 if (!node) { 155 ReleaseMutex(g_hWindowListMutex); 156 WaitForSingleObject(current->event, INFINITE); 157 WaitForSingleObject(g_hWindowListMutex, INFINITE); 158 } 159 /* once we have the information, assign the pointers to it */ 160 *button = current->MouseListHead->Button; 161 *x_user = current->MouseListHead->user.x; 162 *y_user = current->MouseListHead->user.y; 163 /* optional arguments */ 164 if (x_phys) *x_phys = current->MouseListHead->phys.x; 165 if (y_phys) *y_phys = current->MouseListHead->phys.y; 166 /* remove set of information from sub linked-list, delete the node */ 167 current->MouseListHead = current->MouseListHead->mnext; 168 if (!current->MouseListHead) { 169 ResetEvent(current->event); 170 current->MouseListTail = NULL; 171 } 172 if (node) PetscFree(node); 173 174 /* Release mutex so that other code can use 175 the linked list now that we are done with it */ 176 ReleaseMutex(g_hWindowListMutex); 177 PetscFunctionReturn(0); 178 } 179 180 #undef __FUNCT__ 181 #define __FUNCT__ "PetscDrawPause_Win32" 182 static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw) 183 { 184 PetscFunctionBegin; 185 PetscSleep(draw->pause); 186 PetscFunctionReturn(0); 187 } 188 189 #undef __FUNCT__ 190 #define __FUNCT__ "TranslateColor_Win32" 191 static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color) 192 { 193 /* Maps single color value into the RGB colors in our tables */ 194 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 195 windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]); 196 return 0; 197 } 198 199 #undef __FUNCT__ 200 #define __FUNCT__ "AverageColorRectangle_Win32" 201 static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4) 202 { 203 /* Averages colors given at points of rectangle and sets color from color table 204 will be changed once the color gradient problem is worked out */ 205 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 206 windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4), 207 ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4), 208 ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4)); 209 return 0; 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "AverageColorTriangle_Win32" 214 static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3) 215 { 216 /* Averages colors given at points of rectangle and sets color from color table 217 will be changed once the color gradient problem is worked out */ 218 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 219 windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3, 220 (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3, 221 (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3); 222 return 0; 223 } 224 225 #undef __FUNCT__ 226 #define __FUNCT__ "PetscDrawRectangle_Win32" 227 static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4) 228 { 229 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 230 HBRUSH hbrush; 231 RECT rect; 232 int x1,yone,x2,y2; 233 HDC hdc; 234 235 PetscFunctionBegin; 236 x1 = XTRANS(draw,windraw,xl); 237 x2 = XTRANS(draw,windraw,xr); 238 yone = YTRANS(draw,windraw,yl); 239 y2 = YTRANS(draw,windraw,yr); 240 SetRect(&rect,x1,y2,x2,yone); 241 if (c1==c2 && c2==c3 && c3==c4) { 242 TranslateColor_Win32(draw,c1); 243 } else { 244 AverageColorRectangle_Win32(draw,c1,c2,c3,c4); 245 } 246 hbrush = CreateSolidBrush(windraw->currentcolor); 247 248 if (windraw->node->DoubleBuffered) { 249 hdc = windraw->node->DoubleBuffer; 250 } else { 251 hdc = windraw->node->Buffer; 252 } 253 FillRect(hdc,&rect,hbrush); 254 /* Forces a WM_PAINT message and erases background */ 255 InvalidateRect(windraw->hWnd,NULL,TRUE); 256 UpdateWindow(windraw->hWnd); 257 PetscFunctionReturn(0); 258 } 259 260 #undef __FUNCT__ 261 #define __FUNCT__ "PetscDrawLine_Win32" 262 static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color) 263 { 264 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 265 HPEN hpen; 266 int x1,yone,x2,y2; 267 HDC hdc; 268 269 PetscFunctionBegin; 270 TranslateColor_Win32(draw,color); 271 x1 = XTRANS(draw,windraw,xl);x2 = XTRANS(draw,windraw,xr); 272 yone = YTRANS(draw,windraw,yl);y2 = YTRANS(draw,windraw,yr); 273 hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor); 274 if (windraw->node->DoubleBuffered) { 275 hdc = windraw->node->DoubleBuffer; 276 } else { 277 hdc = windraw->node->Buffer; 278 } 279 SelectPen(hdc,hpen); 280 MoveToEx(hdc,x1,yone,NULL); 281 LineTo(hdc,x2,y2); 282 /* Forces a WM_PAINT message and erases background */ 283 InvalidateRect(windraw->hWnd,NULL,TRUE); 284 UpdateWindow(windraw->hWnd); 285 PetscFunctionReturn(0); 286 } 287 288 #undef __FUNCT__ 289 #define __FUNCT__ "PetscDrawLineSetWidth_Win32" 290 static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width) 291 { 292 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 293 int averagesize,finalwidth; 294 RECT rect; 295 296 PetscFunctionBegin; 297 GetClientRect(windraw->hWnd,&rect); 298 averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2; 299 finalwidth = (int)floor(averagesize*width); 300 if (finalwidth < 1) { 301 finalwidth = 1; /* minimum size PetscDrawLine can except */ 302 } 303 windraw->linewidth = finalwidth; 304 PetscFunctionReturn(0); 305 } 306 307 #undef __FUNCT__ 308 #define __FUNCT__ "PetscDrawLineGetWidth_Win32" 309 static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width) 310 { 311 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 312 313 PetscFunctionBegin; 314 *width = (PetscReal)windraw->linewidth; 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "PetscDrawPoint_Win32" 320 static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color) 321 { 322 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 323 HBRUSH hbrush; 324 HRGN hrgn; 325 int radius; 326 int x1,yone; 327 HDC hdc; 328 329 PetscFunctionBegin; 330 TranslateColor_Win32(draw,color); 331 x1 = XTRANS(draw,windraw,x); 332 yone = YTRANS(draw,windraw,y); 333 hbrush = CreateSolidBrush(windraw->currentcolor); 334 if (windraw->node->DoubleBuffered) { 335 hdc = windraw->node->DoubleBuffer; 336 } else { 337 hdc = windraw->node->Buffer; 338 } 339 /* desired size is one logical pixel so just turn it on */ 340 if (windraw->pointdiameter == 1) { 341 SetPixelV(hdc,x1,yone,windraw->currentcolor); 342 } else { 343 /* draw point around position determined */ 344 radius = windraw->pointdiameter/2; /* integer division */ 345 hrgn = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius); 346 FillRgn(hdc,hrgn,hbrush); 347 } 348 /* Forces a WM_PAINT and erases background */ 349 InvalidateRect(windraw->hWnd,NULL,TRUE); 350 UpdateWindow(windraw->hWnd); 351 PetscFunctionReturn(0); 352 } 353 354 #undef __FUNCT__ 355 #define __FUNCT__ "PetscDrawPointSetSize_Win32" 356 static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width) 357 { 358 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 359 int averagesize,diameter; 360 RECT rect; 361 362 PetscFunctionBegin; 363 GetClientRect(windraw->hWnd,&rect); 364 averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2; 365 diameter = (int)floor(averagesize*width); 366 if (diameter < 1) diameter = 1; 367 windraw->pointdiameter = diameter; 368 PetscFunctionReturn(0); 369 } 370 371 #undef __FUNCT__ 372 #define __FUNCT__ "PetscDrawString_Win32" 373 static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text) 374 { 375 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 376 RECT r; 377 HFONT hfont; 378 LOGFONT logfont; 379 int x1,yone; 380 HDC hdc; 381 382 PetscFunctionBegin; 383 x1 = XTRANS(draw,windraw,x); 384 yone = YTRANS(draw,windraw,y); 385 r.bottom = yone; 386 r.left = x1; 387 r.right = x1 + 1; 388 r.top = yone + 1; 389 logfont.lfHeight = windraw->stringheight; 390 logfont.lfWidth = windraw->stringwidth; 391 logfont.lfEscapement = 0; 392 logfont.lfOrientation = 0; 393 logfont.lfCharSet = 0; 394 logfont.lfClipPrecision = 0; 395 logfont.lfItalic = 0; 396 logfont.lfOutPrecision = 0; 397 logfont.lfPitchAndFamily = DEFAULT_PITCH; 398 logfont.lfQuality = DEFAULT_QUALITY; 399 logfont.lfStrikeOut = 0; 400 logfont.lfUnderline = 0; 401 logfont.lfWeight = FW_NORMAL; 402 hfont = CreateFontIndirect(&logfont); 403 TranslateColor_Win32(draw,color); 404 if (windraw->node->DoubleBuffered) { 405 hdc = windraw->node->DoubleBuffer; 406 } else { 407 hdc = windraw->node->Buffer; 408 } 409 SelectFont(hdc,hfont); 410 SetTextColor(hdc,windraw->currentcolor); 411 DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP); 412 DeleteObject(hfont); 413 /* Forces a WM_PAINT message and erases background */ 414 InvalidateRect(windraw->hWnd,NULL,TRUE); 415 UpdateWindow(windraw->hWnd); 416 PetscFunctionReturn(0); 417 } 418 419 #undef __FUNCT__ 420 #define __FUNCT__ "PetscDrawStringVertical_Win32" 421 static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text) 422 { 423 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 424 RECT r; 425 HFONT hfont; 426 LOGFONT logfont; 427 int x1,yone; 428 HDC hdc; 429 430 PetscFunctionBegin; 431 x1 = XTRANS(draw,windraw,x); 432 yone = YTRANS(draw,windraw,y); 433 r.left = x1; 434 r.bottom = yone + 30; 435 r.right = x1 + 1; 436 r.top = yone - 30; 437 logfont.lfEscapement = 2700; /* Causes verticle text drawing */ 438 logfont.lfHeight = windraw->stringheight; 439 logfont.lfWidth = windraw->stringwidth; 440 logfont.lfOrientation = 0; 441 logfont.lfCharSet = DEFAULT_CHARSET; 442 logfont.lfClipPrecision = 0; 443 logfont.lfItalic = 0; 444 logfont.lfOutPrecision = 0; 445 logfont.lfPitchAndFamily = DEFAULT_PITCH; 446 logfont.lfQuality = DEFAULT_QUALITY; 447 logfont.lfStrikeOut = 0; 448 logfont.lfUnderline = 0; 449 logfont.lfWeight = FW_NORMAL; 450 hfont = CreateFontIndirect(&logfont); 451 TranslateColor_Win32(draw,color); 452 if (windraw->node->DoubleBuffered) { 453 hdc = windraw->node->DoubleBuffer; 454 } else { 455 hdc = windraw->node->Buffer; 456 } 457 SelectFont(hdc,hfont); 458 SetTextColor(hdc,windraw->currentcolor); 459 DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE); 460 DeleteObject(hfont); 461 /* Forces a WM_PAINT message and erases background */ 462 InvalidateRect(windraw->hWnd,NULL,TRUE); 463 UpdateWindow(windraw->hWnd); 464 PetscFunctionReturn(0); 465 } 466 467 #undef __FUNCT__ 468 #define __FUNCT__ "PetscDrawStringSetSize_Win32" 469 static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height) 470 { 471 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 472 int w,h; 473 474 PetscFunctionBegin; 475 w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl)); 476 h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl)); 477 if (h < 1) h = 1; 478 if (w < 1) w = 1; 479 windraw->stringheight = h; 480 windraw->stringwidth = w; 481 PetscFunctionReturn(0); 482 } 483 #undef __FUNCT__ 484 #define __FUNCT__ "PetscDrawStringGetSize_Win32" 485 static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height) 486 { 487 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 488 double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl); 489 double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl); 490 491 PetscFunctionBegin; 492 *height = (double)windraw->stringheight*scaleY; 493 *width = (double)windraw->stringwidth*scaleX; 494 PetscFunctionReturn(0); 495 } 496 497 #undef __FUNCT__ 498 #define __FUNCT__ "PetscDrawResizeWindow_Win32" 499 static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h) 500 { 501 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 502 RECT r; 503 504 PetscFunctionBegin; 505 GetWindowRect(windraw->hWnd,&r); 506 MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE); 507 /* set all variable dealing with window dimensions */ 508 windraw->node->bitheight = windraw->h = draw->h = h; 509 windraw->node->bitwidth = windraw->w = draw->w = w; 510 /* set up graphic buffers with the new size of window */ 511 SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL); 512 if (windraw->node->DoubleBuffered) { 513 SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL); 514 } 515 windraw->haveresized = PETSC_TRUE; 516 PetscFunctionReturn(0); 517 } 518 519 #undef __FUNCT__ 520 #define __FUNCT__ "PetscDrawCheckResizeWindow_Win32" 521 static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw) 522 { 523 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 524 525 PetscFunctionBegin; 526 if (windraw->haveresized == 1) { 527 PetscFunctionReturn(1); 528 } else { 529 PetscFunctionReturn(0); 530 } 531 532 } 533 534 #undef __FUNCT__ 535 #define __FUNCT__ "PetscDrawSetTitle_Win32" 536 static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[]) 537 { 538 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 539 540 PetscFunctionBegin; 541 SetWindowText(windraw->hWnd,title); 542 PetscFunctionReturn(0); 543 } 544 545 #undef __FUNCT__ 546 #define __FUNCT__ "PetscDrawClear_Win32" 547 static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw) 548 { 549 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 550 551 PetscFunctionBegin; 552 /* clear primary buffer */ 553 ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 554 /* if exists clear secondary buffer */ 555 if (windraw->node->DoubleBuffered) { 556 ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 557 } 558 /* force WM_PAINT message so cleared buffer will show */ 559 InvalidateRect(windraw->hWnd,NULL,TRUE); 560 UpdateWindow(windraw->hWnd); 561 PetscFunctionReturn(0); 562 } 563 564 #undef __FUNCT__ 565 #define __FUNCT__ "PetscDrawTriangle_Win32" 566 static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2, 567 PetscReal x3,PetscReal y3,int c1,int c2,int c3) 568 { 569 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 570 HBRUSH hbrush; 571 HPEN hpen; 572 int p1x,p1y,p2x,p2y,p3x,p3y; 573 HDC bit; 574 575 PetscFunctionBegin; 576 AverageColorTriangle_Win32(draw,c1,c2,c3); 577 hbrush = CreateSolidBrush(windraw->currentcolor); 578 hpen = CreatePen(PS_SOLID,0,windraw->currentcolor); 579 p1x = XTRANS(draw,windraw,x1); 580 p2x = XTRANS(draw,windraw,x2); 581 p3x = XTRANS(draw,windraw,x3); 582 p1y = YTRANS(draw,windraw,yone); 583 p2y = YTRANS(draw,windraw,y2); 584 p3y = YTRANS(draw,windraw,y3); 585 586 if (windraw->node->DoubleBuffered) { 587 bit = windraw->node->DoubleBuffer; 588 } else { 589 bit = windraw->node->Buffer; 590 } 591 BeginPath(bit); 592 MoveToEx(bit,p1x,p1y,NULL); 593 LineTo(bit,p2x,p2y); 594 LineTo(bit,p3x,p3y); 595 LineTo(bit,p1x,p1y); 596 EndPath(bit); 597 SelectPen(bit,hpen); 598 SelectBrush(bit,hbrush); 599 StrokeAndFillPath(bit); 600 /* Forces a WM_PAINT message and erases background */ 601 InvalidateRect(windraw->hWnd,NULL,TRUE); 602 UpdateWindow(windraw->hWnd); 603 PetscFunctionReturn(0); 604 } 605 606 #undef __FUNCT__ 607 #define __FUNCT__ "PopMessageLoopThread_Win32" 608 void PopMessageLoopThread_Win32(PetscDraw popdraw) 609 { 610 PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data; 611 MSG msg; 612 HWND hWnd = NULL; 613 char PopClassName [MAX_LOADSTRING + 1]; 614 RECT r; 615 int width,height; 616 WNDCLASSEX myclass; 617 LPVOID lpMsgBuf; 618 619 PetscFunctionBegin; 620 /* initialize window class parameters */ 621 myclass.cbSize = sizeof(WNDCLASSEX); 622 myclass.style = CS_OWNDC; 623 myclass.lpfnWndProc = (WNDPROC)PetscWndProc; 624 myclass.cbClsExtra = 0; 625 myclass.cbWndExtra = 0; 626 myclass.hInstance = NULL; 627 myclass.hIcon = NULL; 628 myclass.hCursor = LoadCursor(NULL, IDC_ARROW); 629 myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 630 myclass.lpszMenuName = NULL; 631 myclass.lpszClassName = PopClassName; 632 myclass.hIconSm = NULL; 633 634 RegisterClassEx(&myclass); 635 636 SetRect(&r,0,0,450,450); 637 638 width = (r.right - r.left) / 3; 639 height = (r.bottom - r.top) / 3; 640 641 hWnd = CreateWindowEx(0, 642 PopClassName, 643 NULL, 644 WS_POPUPWINDOW | WS_CAPTION, 645 0,0, 646 width,height, 647 NULL, 648 NULL, 649 hInst, 650 NULL); 651 pop->x = 0; 652 pop->y = 0; 653 pop->w = width; 654 pop->h = height; 655 656 if (!hWnd) { 657 lpMsgBuf = (LPVOID)"Window Not Succesfully Created"; 658 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION); 659 LocalFree(lpMsgBuf); 660 exit(0); 661 } 662 pop->hWnd = hWnd; 663 /* display and update new popup window */ 664 ShowWindow(pop->hWnd, SW_SHOWNORMAL); 665 UpdateWindow(pop->hWnd); 666 SetEvent(pop->hReadyEvent); 667 668 while (GetMessage(&msg, pop->hWnd, 0, 0)) { 669 TranslateMessage(&msg); 670 DispatchMessage(&msg); 671 } 672 PetscFunctionReturnVoid(); 673 } 674 675 #undef __FUNCT__ 676 #define __FUNCT__ "PetscDrawDestroy_Win32" 677 static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw) 678 { 679 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 680 681 PetscFunctionBegin; 682 SendMessage(windraw->hWnd,WM_DESTROY,0,0); 683 PetscFree(windraw); 684 PetscFunctionReturn(0); 685 } 686 687 #undef __FUNCT__ 688 #define __FUNCT__ "PetscDrawSynchronizedFlush_Win32" 689 static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw) 690 { 691 /* Multi Processor is not implemeted yet */ 692 PetscFunctionBegin; 693 PetscDrawFlush_Win32(draw); 694 PetscFunctionReturn(0); 695 } 696 697 #undef __FUNCT__ 698 #define __FUNCT__ "PetscDrawSynchronizedClear_Win32" 699 static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw) 700 { 701 /* Multi Processor is not implemeted yet */ 702 PetscFunctionBegin; 703 PetscDrawClear_Win32(draw); 704 PetscFunctionReturn(0); 705 } 706 707 #undef __FUNCT__ 708 #define __FUNCT__ "MessageLoopThread_Win32" 709 void MessageLoopThread_Win32(PetscDraw draw) 710 { 711 PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data; 712 MSG msg; 713 HWND hWnd = NULL; 714 char classname[MAX_LOADSTRING + 1]; 715 WNDCLASSEX wclass; 716 LPVOID lpMsgBuf; 717 718 PetscFunctionBegin; 719 /* initialize window class parameters */ 720 wclass.cbSize = sizeof(WNDCLASSEX); 721 wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW; 722 wclass.lpfnWndProc = (WNDPROC)PetscWndProc; 723 wclass.cbClsExtra = 0; 724 wclass.cbWndExtra = 0; 725 wclass.hInstance = NULL; 726 wclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); 727 wclass.hCursor = LoadCursor(NULL,IDC_ARROW); 728 wclass.hbrBackground = GetStockBrush(WHITE_BRUSH); 729 wclass.lpszMenuName = NULL; 730 wclass.lpszClassName = classname; 731 wclass.hIconSm = NULL; 732 733 RegisterClassEx(&wclass); 734 735 736 hWnd = CreateWindowEx(0, 737 classname, 738 NULL, 739 WS_OVERLAPPEDWINDOW, 740 draw->x, 741 draw->y, 742 draw->w, 743 draw->h, 744 NULL, 745 NULL, 746 hInst, 747 NULL); 748 749 if (!hWnd) { 750 lpMsgBuf = (LPVOID)"Window Not Succesfully Created"; 751 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION); 752 LocalFree(lpMsgBuf); 753 exit(0); 754 } 755 windraw->hWnd = hWnd; 756 /* display and update new window */ 757 ShowWindow(hWnd,SW_SHOWNORMAL); 758 UpdateWindow(hWnd); 759 SetEvent(windraw->hReadyEvent); 760 761 while (GetMessage(&msg,hWnd, 0, 0)) { 762 TranslateMessage(&msg); 763 DispatchMessage(&msg); 764 } 765 PetscFunctionReturnVoid(); 766 } 767 768 769 static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32, 770 PetscDrawFlush_Win32, 771 PetscDrawLine_Win32, 772 PetscDrawLineSetWidth_Win32, 773 PetscDrawLineGetWidth_Win32, 774 PetscDrawPoint_Win32, 775 PetscDrawPointSetSize_Win32, 776 PetscDrawString_Win32, 777 PetscDrawStringVertical_Win32, 778 PetscDrawStringSetSize_Win32, 779 PetscDrawStringGetSize_Win32, 780 0, 781 PetscDrawClear_Win32, 782 PetscDrawSynchronizedFlush_Win32, 783 PetscDrawRectangle_Win32, 784 PetscDrawTriangle_Win32, 785 0, 786 PetscDrawGetMouseButton_Win32, 787 PetscDrawPause_Win32, 788 PetscDrawSynchronizedClear_Win32, 789 0, 790 0, 791 PetscDrawGetPopup_Win32, 792 PetscDrawSetTitle_Win32, 793 PetscDrawCheckResizedWindow_Win32, 794 PetscDrawResizeWindow_Win32, 795 PetscDrawDestroy_Win32, 796 0, 797 0, 798 0, 799 0}; 800 801 #undef __FUNCT__ 802 #define __FUNCT__ "PetscDrawGetPopup_Win32" 803 static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw) 804 { 805 PetscDraw_Win32 *pop; 806 HANDLE hThread = NULL; 807 WindowNode newnode; 808 PetscErrorCode ierr; 809 810 PetscFunctionBegin; 811 ierr = PetscNew(PetscDraw_Win32,&pop);CHKERRQ(ierr); 812 (*popdraw)->data = pop; 813 814 /* the following is temporary fix for initializing a global datastructure */ 815 if (!g_hWindowListMutex) { 816 g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL); 817 } 818 ierr = PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr); 819 820 pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 821 CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread); 822 CloseHandle(hThread); 823 WaitForSingleObject(pop->hReadyEvent, INFINITE); 824 CloseHandle(pop->hReadyEvent); 825 WaitForSingleObject(g_hWindowListMutex, INFINITE); 826 827 draw->popup = (*popdraw); 828 ierr = PetscNew(struct _p_WindowNode,&newnode);CHKERRQ(ierr); 829 newnode->MouseListHead = NULL; 830 newnode->MouseListTail = NULL; 831 newnode->wnext = WindowListHead; 832 newnode->wprev = NULL; 833 newnode->hWnd = pop->hWnd; 834 if (WindowListHead != NULL) { 835 WindowListHead->wprev = newnode; 836 } 837 WindowListHead = newnode; 838 pop->hdc = GetDC(pop->hWnd); 839 840 pop->stringheight = 10; 841 pop->stringwidth = 6; 842 pop->linewidth = 1; /* default pixel sizes of graphics until user changes them */ 843 pop->pointdiameter = 1; 844 pop->node = newnode; 845 846 newnode->bitwidth = pop->w; 847 newnode->bitheight = pop->h; 848 849 /* Create and initialize primary graphics buffer */ 850 newnode->Buffer = CreateCompatibleDC(pop->hdc); 851 newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h); 852 newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit); 853 ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 854 855 856 newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL); 857 newnode->DoubleBuffered = PETSC_FALSE; 858 859 ReleaseDC(pop->hWnd,pop->hdc); 860 ReleaseMutex(g_hWindowListMutex); 861 PetscFunctionReturn(0); 862 } 863 864 EXTERN_C_BEGIN 865 #undef __FUNCT__ 866 #define __FUNCT__ "PetscDrawCreate_Win32" 867 PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw) 868 { 869 PetscDraw_Win32 *windraw; 870 HANDLE hThread = NULL; 871 PetscErrorCode ierr; 872 WindowNode newnode; 873 874 PetscFunctionBegin; 875 ierr = PetscNew(PetscDraw_Win32,&windraw);CHKERRQ(ierr); 876 draw->data = windraw; 877 878 /* the following is temporary fix for initializing a global datastructure */ 879 if (!g_hWindowListMutex) { 880 g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL); 881 } 882 ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr); 883 884 windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 885 /* makes call to MessageLoopThread to creat window and attach a thread */ 886 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread); 887 CloseHandle(hThread); 888 WaitForSingleObject(windraw->hReadyEvent,INFINITE); 889 CloseHandle(windraw->hReadyEvent); 890 WaitForSingleObject(g_hWindowListMutex,INFINITE); 891 892 ierr = PetscNew(struct _p_WindowNode,&newnode);CHKERRQ(ierr); 893 newnode->MouseListHead = NULL; 894 newnode->MouseListTail = NULL; 895 newnode->wnext = WindowListHead; 896 newnode->wprev = NULL; 897 newnode->hWnd = windraw->hWnd; 898 if (WindowListHead != NULL) { 899 WindowListHead->wprev = newnode; 900 } 901 WindowListHead = newnode; 902 windraw->hdc = GetDC(windraw->hWnd); 903 904 windraw->stringheight = 10; 905 windraw->stringwidth = 6; 906 windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */ 907 windraw->pointdiameter = 1; 908 windraw->node = newnode; 909 910 windraw->x = draw->x; 911 windraw->y = draw->y; 912 windraw->w = newnode->bitwidth = draw->w; 913 windraw->h = newnode->bitheight = draw->h; 914 915 /* Create and initialize primary graphics buffer */ 916 newnode->Buffer = CreateCompatibleDC(windraw->hdc); 917 newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h); 918 newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit); 919 ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 920 921 newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL); 922 newnode->DoubleBuffered = PETSC_FALSE; 923 924 ReleaseDC(windraw->hWnd,windraw->hdc); 925 ReleaseMutex(g_hWindowListMutex); 926 PetscFunctionReturn(0); 927 } 928 EXTERN_C_END 929 930 931 /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG) 932 PURPOSE: Processes messages for the main window. 933 WM_COMMAND - process the application menu 934 WM_PAINT - Paint the main window 935 WM_DESTROY - post a quit message and return */ 936 937 #undef __FUNCT__ 938 #define __FUNCT__ "PetscWndProc" 939 LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 940 { 941 int wmId, wmEvent; 942 943 PetscFunctionBegin; 944 switch (message) { 945 HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32); 946 HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32); 947 case WM_COMMAND: 948 wmId = LOWORD(wParam); 949 wmEvent = HIWORD(wParam); 950 /* Parse the menu selections:*/ 951 switch (wmId) { 952 case IDM_EXIT: 953 DestroyWindow(hWnd); 954 break; 955 default: 956 return DefWindowProc(hWnd, message, wParam, lParam); 957 } 958 break; 959 case WM_LBUTTONUP: 960 MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT); 961 break; 962 case WM_RBUTTONUP: 963 MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT); 964 break; 965 case WM_MBUTTONUP: 966 MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER); 967 break; 968 default: 969 PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam)); 970 } 971 PetscFunctionReturn(0); 972 } 973 974 #undef __FUNCT__ 975 #define __FUNCT__ "OnPaint_Win32" 976 static void OnPaint_Win32(HWND hWnd) 977 { 978 PAINTSTRUCT ps; 979 HDC hdc; 980 WindowNode current = NULL; 981 982 PetscFunctionBegin; 983 InvalidateRect(hWnd,NULL,TRUE); 984 WaitForSingleObject(g_hWindowListMutex, INFINITE); 985 current = WindowListHead; 986 hdc = BeginPaint(hWnd, &ps); 987 988 while (current != NULL) { 989 if (current->hWnd == hWnd) { 990 /* flushes primary buffer to window */ 991 BitBlt(hdc, 992 0,0, 993 GetDeviceCaps(hdc,HORZRES), 994 GetDeviceCaps(hdc,VERTRES), 995 current->Buffer, 996 0,0, 997 SRCCOPY); 998 999 /* StretchBlt(hdc, 1000 0,0, 1001 w,h, 1002 current->Buffer, 1003 0,0, 1004 current->bitwidth, 1005 current->bitheight, 1006 SRCCOPY); */ 1007 break; 1008 } 1009 current = current->wnext; 1010 } 1011 EndPaint(hWnd, &ps); 1012 ReleaseMutex(g_hWindowListMutex); 1013 PetscFunctionReturnVoid(); 1014 } 1015 1016 #undef __FUNCT__ 1017 #define __FUNCT__ "MouseRecord_Win32" 1018 static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button) 1019 { 1020 /* Called by all three mouse button actions 1021 Records needed mouse data in windows data structure */ 1022 WindowNode current = NULL; 1023 MouseNode newnode; 1024 POINT mousepos; 1025 PetscErrorCode ierr; 1026 1027 PetscFunctionBegin; 1028 WaitForSingleObject(g_hWindowListMutex, INFINITE); 1029 current = WindowListHead; 1030 if (current->IsGetMouseOn == TRUE) { 1031 1032 SetEvent(current->event); 1033 while (current != NULL) { 1034 if (current->hWnd == hWnd) { 1035 1036 ierr = PetscNew(struct _p_MouseNode,&newnode);CHKERRQ(ierr); 1037 newnode->Button = button; 1038 GetCursorPos(&mousepos); 1039 newnode->user.x = mousepos.x; 1040 newnode->user.y = mousepos.y; 1041 ScreenToClient(hWnd,&mousepos); 1042 newnode->phys.x = mousepos.x; 1043 newnode->phys.y = mousepos.y; 1044 if (!current->MouseListTail) { 1045 current->MouseListHead = newnode; 1046 current->MouseListTail = newnode; 1047 } else { 1048 current->MouseListTail->mnext = newnode; 1049 current->MouseListTail = newnode; 1050 } 1051 newnode->mnext = NULL; 1052 1053 break; 1054 } 1055 current = current->wnext; 1056 } 1057 } 1058 ReleaseMutex(g_hWindowListMutex); 1059 PetscFunctionReturn(0); 1060 } 1061 1062 #undef __FUNCT__ 1063 #define __FUNCT__ "OnDestroy_Win32" 1064 static void OnDestroy_Win32(HWND hWnd) 1065 { 1066 /* searches linked list of window data and frees corresponding memory */ 1067 WindowNode current; 1068 1069 PetscFunctionBegin; 1070 WaitForSingleObject(g_hWindowListMutex, INFINITE); 1071 current = WindowListHead; 1072 1073 SetEvent(current->event); 1074 while (current != NULL) { 1075 if (current->hWnd == hWnd) { 1076 if (current->wprev != NULL) { 1077 current->wprev->wnext = current->wnext; 1078 } else { 1079 WindowListHead = current->wnext; 1080 } 1081 if (current->MouseListHead) { 1082 deletemouselist_Win32(current); 1083 } else { 1084 PetscFree(current); 1085 } 1086 break; 1087 } 1088 current = current->wnext; 1089 } 1090 ReleaseMutex(g_hWindowListMutex); 1091 PostQuitMessage(0); 1092 PetscFunctionReturnVoid(); 1093 } 1094