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) deletelist->MouseListHead = deletelist->MouseListHead->mnext; 104 PetscFree(node); 105 } 106 deletelist->MouseListHead = deletelist->MouseListTail = NULL; 107 if (deletelist->wprev != NULL) deletelist->wprev->wnext = deletelist->wnext; 108 if (deletelist->wnext != NULL) deletelist->wnext->wprev = deletelist->wprev; 109 PetscFree(deletelist); 110 return 0; 111 } 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 != NULL) { 127 if (current->hWnd == windraw->hWnd) { 128 current->IsGetMouseOn = TRUE; 129 break; 130 } else current = current->wnext; 131 } 132 /* If no actions have occured, wait for one */ 133 node = current->MouseListHead; 134 if (!node) { 135 ReleaseMutex(g_hWindowListMutex); 136 WaitForSingleObject(current->event, INFINITE); 137 WaitForSingleObject(g_hWindowListMutex, INFINITE); 138 } 139 /* once we have the information, assign the pointers to it */ 140 *button = current->MouseListHead->Button; 141 *x_user = current->MouseListHead->user.x; 142 *y_user = current->MouseListHead->user.y; 143 /* optional arguments */ 144 if (x_phys) *x_phys = current->MouseListHead->phys.x; 145 if (y_phys) *y_phys = current->MouseListHead->phys.y; 146 /* remove set of information from sub linked-list, delete the node */ 147 current->MouseListHead = current->MouseListHead->mnext; 148 if (!current->MouseListHead) { 149 ResetEvent(current->event); 150 current->MouseListTail = NULL; 151 } 152 if (node) PetscFree(node); 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 *height = (double)windraw->stringheight*scaleY; 462 *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(windraw); 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 *popdraw) 764 { 765 PetscDraw_Win32 *pop; 766 HANDLE hThread = NULL; 767 WindowNode newnode; 768 PetscErrorCode ierr; 769 770 PetscFunctionBegin; 771 ierr = PetscNew(&pop);CHKERRQ(ierr); 772 773 (*popdraw)->data = pop; 774 775 /* the following is temporary fix for initializing a global datastructure */ 776 if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL); 777 ierr = PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr); 778 779 pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 780 CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread); 781 CloseHandle(hThread); 782 WaitForSingleObject(pop->hReadyEvent, INFINITE); 783 CloseHandle(pop->hReadyEvent); 784 WaitForSingleObject(g_hWindowListMutex, INFINITE); 785 786 draw->popup = (*popdraw); 787 ierr = PetscNew(&newnode);CHKERRQ(ierr); 788 newnode->MouseListHead = NULL; 789 newnode->MouseListTail = NULL; 790 newnode->wnext = WindowListHead; 791 newnode->wprev = NULL; 792 newnode->hWnd = pop->hWnd; 793 if (WindowListHead != NULL) WindowListHead->wprev = newnode; 794 WindowListHead = newnode; 795 pop->hdc = GetDC(pop->hWnd); 796 797 pop->stringheight = 10; 798 pop->stringwidth = 6; 799 pop->linewidth = 1; /* default pixel sizes of graphics until user changes them */ 800 pop->pointdiameter = 1; 801 pop->node = newnode; 802 803 newnode->bitwidth = pop->w; 804 newnode->bitheight = pop->h; 805 806 /* Create and initialize primary graphics buffer */ 807 newnode->Buffer = CreateCompatibleDC(pop->hdc); 808 newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h); 809 newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit); 810 ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 811 812 813 newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL); 814 newnode->DoubleBuffered = PETSC_FALSE; 815 816 ReleaseDC(pop->hWnd,pop->hdc); 817 ReleaseMutex(g_hWindowListMutex); 818 PetscFunctionReturn(0); 819 } 820 821 #undef __FUNCT__ 822 #define __FUNCT__ "PetscDrawCreate_Win32" 823 PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw) 824 { 825 PetscDraw_Win32 *windraw; 826 HANDLE hThread = NULL; 827 PetscErrorCode ierr; 828 WindowNode newnode; 829 830 PetscFunctionBegin; 831 ierr = PetscNew(&windraw);CHKERRQ(ierr); 832 draw->data = windraw; 833 834 /* the following is temporary fix for initializing a global datastructure */ 835 if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL); 836 ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr); 837 838 windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 839 /* makes call to MessageLoopThread to creat window and attach a thread */ 840 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread); 841 CloseHandle(hThread); 842 WaitForSingleObject(windraw->hReadyEvent,INFINITE); 843 CloseHandle(windraw->hReadyEvent); 844 WaitForSingleObject(g_hWindowListMutex,INFINITE); 845 846 ierr = PetscNew(&newnode);CHKERRQ(ierr); 847 newnode->MouseListHead = NULL; 848 newnode->MouseListTail = NULL; 849 newnode->wnext = WindowListHead; 850 newnode->wprev = NULL; 851 newnode->hWnd = windraw->hWnd; 852 if (WindowListHead != NULL) WindowListHead->wprev = newnode; 853 WindowListHead = newnode; 854 windraw->hdc = GetDC(windraw->hWnd); 855 856 windraw->stringheight = 10; 857 windraw->stringwidth = 6; 858 windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */ 859 windraw->pointdiameter = 1; 860 windraw->node = newnode; 861 862 windraw->x = draw->x; 863 windraw->y = draw->y; 864 windraw->w = newnode->bitwidth = draw->w; 865 windraw->h = newnode->bitheight = draw->h; 866 867 /* Create and initialize primary graphics buffer */ 868 newnode->Buffer = CreateCompatibleDC(windraw->hdc); 869 newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h); 870 newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit); 871 ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER); 872 873 newnode->event = CreateEvent(NULL,TRUE,FALSE,NULL); 874 newnode->DoubleBuffered = PETSC_FALSE; 875 876 ReleaseDC(windraw->hWnd,windraw->hdc); 877 ReleaseMutex(g_hWindowListMutex); 878 PetscFunctionReturn(0); 879 } 880 881 882 /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG) 883 PURPOSE: Processes messages for the main window. 884 WM_COMMAND - process the application menu 885 WM_PAINT - Paint the main window 886 WM_DESTROY - post a quit message and return */ 887 888 #undef __FUNCT__ 889 #define __FUNCT__ "PetscWndProc" 890 LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 891 { 892 int wmId, wmEvent; 893 894 PetscFunctionBegin; 895 switch (message) { 896 HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32); 897 HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32); 898 case WM_COMMAND: 899 wmId = LOWORD(wParam); 900 wmEvent = HIWORD(wParam); 901 /* Parse the menu selections:*/ 902 switch (wmId) { 903 case IDM_EXIT: 904 DestroyWindow(hWnd); 905 break; 906 default: 907 return DefWindowProc(hWnd, message, wParam, lParam); 908 } 909 break; 910 case WM_LBUTTONUP: 911 MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT); 912 break; 913 case WM_RBUTTONUP: 914 MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT); 915 break; 916 case WM_MBUTTONUP: 917 MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER); 918 break; 919 default: 920 PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam)); 921 } 922 PetscFunctionReturn(0); 923 } 924 925 #undef __FUNCT__ 926 #define __FUNCT__ "OnPaint_Win32" 927 static void OnPaint_Win32(HWND hWnd) 928 { 929 PAINTSTRUCT ps; 930 HDC hdc; 931 WindowNode current = NULL; 932 933 PetscFunctionBegin; 934 InvalidateRect(hWnd,NULL,TRUE); 935 WaitForSingleObject(g_hWindowListMutex, INFINITE); 936 current = WindowListHead; 937 hdc = BeginPaint(hWnd, &ps); 938 939 while (current != NULL) { 940 if (current->hWnd == hWnd) { 941 /* flushes primary buffer to window */ 942 BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES), 943 current->Buffer,0,0,SRCCOPY); 944 945 /* StretchBlt(hdc,0,0,w,h, 946 current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */ 947 break; 948 } 949 current = current->wnext; 950 } 951 EndPaint(hWnd, &ps); 952 ReleaseMutex(g_hWindowListMutex); 953 PetscFunctionReturnVoid(); 954 } 955 956 #undef __FUNCT__ 957 #define __FUNCT__ "MouseRecord_Win32" 958 static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button) 959 { 960 /* Called by all three mouse button actions 961 Records needed mouse data in windows data structure */ 962 WindowNode current = NULL; 963 MouseNode newnode; 964 POINT mousepos; 965 PetscErrorCode ierr; 966 967 PetscFunctionBegin; 968 WaitForSingleObject(g_hWindowListMutex, INFINITE); 969 current = WindowListHead; 970 if (current->IsGetMouseOn == TRUE) { 971 972 SetEvent(current->event); 973 while (current != NULL) { 974 if (current->hWnd == hWnd) { 975 976 ierr = PetscNew(&newnode);CHKERRQ(ierr); 977 newnode->Button = button; 978 GetCursorPos(&mousepos); 979 newnode->user.x = mousepos.x; 980 newnode->user.y = mousepos.y; 981 ScreenToClient(hWnd,&mousepos); 982 newnode->phys.x = mousepos.x; 983 newnode->phys.y = mousepos.y; 984 if (!current->MouseListTail) { 985 current->MouseListHead = newnode; 986 current->MouseListTail = newnode; 987 } else { 988 current->MouseListTail->mnext = newnode; 989 current->MouseListTail = newnode; 990 } 991 newnode->mnext = NULL; 992 993 break; 994 } 995 current = current->wnext; 996 } 997 } 998 ReleaseMutex(g_hWindowListMutex); 999 PetscFunctionReturn(0); 1000 } 1001 1002 #undef __FUNCT__ 1003 #define __FUNCT__ "OnDestroy_Win32" 1004 static void OnDestroy_Win32(HWND hWnd) 1005 { 1006 /* searches linked list of window data and frees corresponding memory */ 1007 WindowNode current; 1008 1009 PetscFunctionBegin; 1010 WaitForSingleObject(g_hWindowListMutex, INFINITE); 1011 current = WindowListHead; 1012 1013 SetEvent(current->event); 1014 while (current != NULL) { 1015 if (current->hWnd == hWnd) { 1016 if (current->wprev != NULL) current->wprev->wnext = current->wnext; 1017 else WindowListHead = current->wnext; 1018 if (current->MouseListHead) deletemouselist_Win32(current); 1019 else PetscFree(current); 1020 break; 1021 } 1022 current = current->wnext; 1023 } 1024 ReleaseMutex(g_hWindowListMutex); 1025 PostQuitMessage(0); 1026 PetscFunctionReturnVoid(); 1027 } 1028