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