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