1 #include <petscsys.h> 2 #include <petsc/private/drawimpl.h> 3 #include <../src/sys/classes/draw/impls/win32/win32draw.h> 4 5 #define IDC_FOUR 109 6 #define IDI_FOUR 107 7 #define IDM_EXIT 105 8 #define IDR_POPUP 103 9 #define MAX_LOADSTRING 100 10 11 #if !defined(SelectPen) 12 #define SelectPen(hdc, hpen) ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen))) 13 #endif 14 #if !defined(SelectFont) 15 #define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont))) 16 #endif 17 #if !defined(SelectBrush) 18 #define SelectBrush(hdc, hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush))) 19 #endif 20 #if !defined(GetStockBrush) 21 #define GetStockBrush(i) ((HBRUSH)GetStockObject(i)) 22 #endif 23 24 #define XTRANS(draw, win, x) (int)(((win)->w) * ((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl)))) 25 #define YTRANS(draw, win, y) (int)(((win)->h) * (1.0 - (draw)->port_yl - (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl)))) 26 27 HINSTANCE hInst; 28 HANDLE g_hWindowListMutex = NULL; 29 WindowNode WindowListHead = NULL; 30 31 /* Hard coded color hue until hue.c works with this */ 32 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}; 33 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}; 34 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}; 35 36 /* Forward declarations of functions included in this code module: */ 37 LRESULT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM); 38 static PetscErrorCode TranslateColor_Win32(PetscDraw, int); 39 static PetscErrorCode AverageColorRectangle_Win32(PetscDraw, int, int, int, int); 40 static PetscErrorCode AverageColorTriangle_Win32(PetscDraw, int, int, int); 41 static PetscErrorCode deletemouselist_Win32(WindowNode); 42 static void OnPaint_Win32(HWND); 43 static void OnDestroy_Win32(HWND); 44 static PetscErrorCode MouseRecord_Win32(HWND, PetscDrawButton); 45 static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw, PetscDraw *); 46 47 static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw) 48 { 49 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 50 HDC hdc = GetDC(windraw->hWnd); 51 52 PetscFunctionBegin; 53 windraw->node->DoubleBuffer = CreateCompatibleDC(hdc); 54 windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc, windraw->w, windraw->h); 55 windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer, windraw->node->DoubleBufferBit); 56 /* Fill background of second buffer */ 57 ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER); 58 /* Copy current buffer into second buffer and set window data as double buffered */ 59 BitBlt(windraw->node->DoubleBuffer, 0, 0, windraw->w, windraw->h, windraw->node->Buffer, 0, 0, SRCCOPY); 60 61 windraw->node->DoubleBuffered = PETSC_TRUE; 62 ReleaseDC(windraw->hWnd, hdc); 63 PetscFunctionReturn(PETSC_SUCCESS); 64 } 65 66 static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw) 67 { 68 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 69 HDC hdc = GetDC(windraw->hWnd); 70 71 PetscFunctionBegin; 72 /* flush double buffer into primary buffer */ 73 BitBlt(windraw->node->Buffer, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY); 74 /* flush double buffer into window */ 75 BitBlt(hdc, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY); 76 ReleaseDC(windraw->hWnd, hdc); 77 PetscFunctionReturn(PETSC_SUCCESS); 78 } 79 80 static PetscErrorCode deletemouselist_Win32(WindowNode deletelist) 81 { 82 /* Called upon window close. Frees memory of linked list of stored mouse commands */ 83 MouseNode node; 84 85 while (deletelist->MouseListHead) { 86 node = deletelist->MouseListHead; 87 if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext; 88 PetscFree(node); 89 } 90 deletelist->MouseListHead = deletelist->MouseListTail = NULL; 91 if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext; 92 if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev; 93 PetscFree(deletelist); 94 return PETSC_SUCCESS; 95 } 96 97 static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button, PetscReal *x_user, PetscReal *y_user, PetscReal *x_phys, PetscReal *y_phys) 98 { 99 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 100 WindowNode current; 101 MouseNode node = 0; 102 103 PetscFunctionBegin; 104 /* Make sure no other code is using the linked list at this moment */ 105 WaitForSingleObject(g_hWindowListMutex, INFINITE); 106 /* Look for the node that matches the window you are using */ 107 current = WindowListHead; 108 while (current) { 109 if (current->hWnd == windraw->hWnd) { 110 current->IsGetMouseOn = TRUE; 111 break; 112 } else current = current->wnext; 113 } 114 /* If no actions have occurred, wait for one */ 115 node = current->MouseListHead; 116 if (!node) { 117 ReleaseMutex(g_hWindowListMutex); 118 WaitForSingleObject(current->event, INFINITE); 119 WaitForSingleObject(g_hWindowListMutex, INFINITE); 120 } 121 /* once we have the information, assign the pointers to it */ 122 *button = current->MouseListHead->Button; 123 *x_user = current->MouseListHead->user.x; 124 *y_user = current->MouseListHead->user.y; 125 /* optional arguments */ 126 if (x_phys) *x_phys = current->MouseListHead->phys.x; 127 if (y_phys) *y_phys = current->MouseListHead->phys.y; 128 /* remove set of information from sub linked-list, delete the node */ 129 current->MouseListHead = current->MouseListHead->mnext; 130 if (!current->MouseListHead) { 131 ResetEvent(current->event); 132 current->MouseListTail = NULL; 133 } 134 if (node) PetscFree(node); 135 136 /* Release mutex so that other code can use 137 the linked list now that we are done with it */ 138 ReleaseMutex(g_hWindowListMutex); 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw) 143 { 144 PetscFunctionBegin; 145 PetscSleep(draw->pause); 146 PetscFunctionReturn(PETSC_SUCCESS); 147 } 148 149 static PetscErrorCode TranslateColor_Win32(PetscDraw draw, int color) 150 { 151 /* Maps single color value into the RGB colors in our tables */ 152 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 153 windraw->currentcolor = RGB(RedMap[color], GreenMap[color], BlueMap[color]); 154 return PETSC_SUCCESS; 155 } 156 157 static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw, int c1, int c2, int c3, int c4) 158 { 159 /* Averages colors given at points of rectangle and sets color from color table 160 will be changed once the color gradient problem is worked out */ 161 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 162 windraw->currentcolor = RGB(((RedMap[c1] + RedMap[c2] + RedMap[c3] + RedMap[c4]) / 4), ((GreenMap[c1] + GreenMap[c2] + GreenMap[c3] + GreenMap[c4]) / 4), ((BlueMap[c1] + BlueMap[c2] + BlueMap[c3] + BlueMap[c4]) / 4)); 163 return PETSC_SUCCESS; 164 } 165 166 static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw, int c1, int c2, int c3) 167 { 168 /* Averages colors given at points of rectangle and sets color from color table 169 will be changed once the color gradient problem is worked out */ 170 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 171 windraw->currentcolor = RGB((RedMap[c1] + RedMap[c2] + RedMap[c3]) / 3, (GreenMap[c1] + GreenMap[c2] + GreenMap[c3]) / 3, (BlueMap[c1] + BlueMap[c2] + BlueMap[c3]) / 3); 172 return PETSC_SUCCESS; 173 } 174 175 static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4) 176 { 177 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 178 HBRUSH hbrush; 179 RECT rect; 180 int x1, yone, x2, y2; 181 HDC hdc; 182 183 PetscFunctionBegin; 184 x1 = XTRANS(draw, windraw, xl); 185 x2 = XTRANS(draw, windraw, xr); 186 yone = YTRANS(draw, windraw, yl); 187 y2 = YTRANS(draw, windraw, yr); 188 SetRect(&rect, x1, y2, x2, yone); 189 if (c1 == c2 && c2 == c3 && c3 == c4) TranslateColor_Win32(draw, c1); 190 else AverageColorRectangle_Win32(draw, c1, c2, c3, c4); 191 hbrush = CreateSolidBrush(windraw->currentcolor); 192 193 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 194 else hdc = windraw->node->Buffer; 195 196 FillRect(hdc, &rect, hbrush); 197 /* Forces a WM_PAINT message and erases background */ 198 InvalidateRect(windraw->hWnd, NULL, TRUE); 199 UpdateWindow(windraw->hWnd); 200 PetscFunctionReturn(PETSC_SUCCESS); 201 } 202 203 static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int color) 204 { 205 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 206 HPEN hpen; 207 int x1, yone, x2, y2; 208 HDC hdc; 209 210 PetscFunctionBegin; 211 TranslateColor_Win32(draw, color); 212 x1 = XTRANS(draw, windraw, xl); 213 x2 = XTRANS(draw, windraw, xr); 214 yone = YTRANS(draw, windraw, yl); 215 y2 = YTRANS(draw, windraw, yr); 216 hpen = CreatePen(PS_SOLID, windraw->linewidth, windraw->currentcolor); 217 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 218 else hdc = windraw->node->Buffer; 219 220 SelectPen(hdc, hpen); 221 MoveToEx(hdc, x1, yone, NULL); 222 LineTo(hdc, x2, y2); 223 /* Forces a WM_PAINT message and erases background */ 224 InvalidateRect(windraw->hWnd, NULL, TRUE); 225 UpdateWindow(windraw->hWnd); 226 PetscFunctionReturn(PETSC_SUCCESS); 227 } 228 229 static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw, PetscReal width) 230 { 231 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 232 int averagesize, finalwidth; 233 RECT rect; 234 235 PetscFunctionBegin; 236 GetClientRect(windraw->hWnd, &rect); 237 averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2; 238 finalwidth = (int)PetscFloorReal(averagesize * width); 239 if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */ 240 241 windraw->linewidth = finalwidth; 242 PetscFunctionReturn(PETSC_SUCCESS); 243 } 244 245 static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width) 246 { 247 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 248 249 PetscFunctionBegin; 250 *width = (PetscReal)windraw->linewidth; 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 254 static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color) 255 { 256 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 257 HBRUSH hbrush; 258 HRGN hrgn; 259 int radius; 260 int x1, yone; 261 HDC hdc; 262 263 PetscFunctionBegin; 264 TranslateColor_Win32(draw, color); 265 x1 = XTRANS(draw, windraw, x); 266 yone = YTRANS(draw, windraw, y); 267 hbrush = CreateSolidBrush(windraw->currentcolor); 268 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 269 else hdc = windraw->node->Buffer; 270 271 /* desired size is one logical pixel so just turn it on */ 272 if (windraw->pointdiameter == 1) SetPixelV(hdc, x1, yone, windraw->currentcolor); 273 else { 274 /* draw point around position determined */ 275 radius = windraw->pointdiameter / 2; /* integer division */ 276 hrgn = CreateEllipticRgn(x1 - radius, yone - radius, x1 + radius, yone + radius); 277 FillRgn(hdc, hrgn, hbrush); 278 } 279 /* Forces a WM_PAINT and erases background */ 280 InvalidateRect(windraw->hWnd, NULL, TRUE); 281 UpdateWindow(windraw->hWnd); 282 PetscFunctionReturn(PETSC_SUCCESS); 283 } 284 285 static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw, PetscReal width) 286 { 287 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 288 int averagesize, diameter; 289 RECT rect; 290 291 PetscFunctionBegin; 292 GetClientRect(windraw->hWnd, &rect); 293 averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2; 294 diameter = (int)PetscFloorReal(averagesize * width); 295 if (diameter < 1) diameter = 1; 296 windraw->pointdiameter = diameter; 297 PetscFunctionReturn(PETSC_SUCCESS); 298 } 299 300 static PetscErrorCode PetscDrawString_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text) 301 { 302 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 303 RECT r; 304 HFONT hfont; 305 LOGFONT logfont; 306 int x1, yone; 307 HDC hdc; 308 309 PetscFunctionBegin; 310 x1 = XTRANS(draw, windraw, x); 311 yone = YTRANS(draw, windraw, y); 312 r.bottom = yone; 313 r.left = x1; 314 r.right = x1 + 1; 315 r.top = yone + 1; 316 317 logfont.lfHeight = windraw->stringheight; 318 logfont.lfWidth = windraw->stringwidth; 319 logfont.lfEscapement = 0; 320 logfont.lfOrientation = 0; 321 logfont.lfCharSet = 0; 322 logfont.lfClipPrecision = 0; 323 logfont.lfItalic = 0; 324 logfont.lfOutPrecision = 0; 325 logfont.lfPitchAndFamily = DEFAULT_PITCH; 326 logfont.lfQuality = DEFAULT_QUALITY; 327 logfont.lfStrikeOut = 0; 328 logfont.lfUnderline = 0; 329 logfont.lfWeight = FW_NORMAL; 330 331 hfont = CreateFontIndirect(&logfont); 332 TranslateColor_Win32(draw, color); 333 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 334 else hdc = windraw->node->Buffer; 335 336 SelectFont(hdc, hfont); 337 SetTextColor(hdc, windraw->currentcolor); 338 DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP); 339 DeleteObject(hfont); 340 /* Forces a WM_PAINT message and erases background */ 341 InvalidateRect(windraw->hWnd, NULL, TRUE); 342 UpdateWindow(windraw->hWnd); 343 PetscFunctionReturn(PETSC_SUCCESS); 344 } 345 346 static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text) 347 { 348 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 349 RECT r; 350 HFONT hfont; 351 LOGFONT logfont; 352 int x1, yone; 353 HDC hdc; 354 355 PetscFunctionBegin; 356 x1 = XTRANS(draw, windraw, x); 357 yone = YTRANS(draw, windraw, y); 358 r.left = x1; 359 r.bottom = yone + 30; 360 r.right = x1 + 1; 361 r.top = yone - 30; 362 363 logfont.lfEscapement = 2700; /* Causes vertical text drawing */ 364 logfont.lfHeight = windraw->stringheight; 365 logfont.lfWidth = windraw->stringwidth; 366 logfont.lfOrientation = 0; 367 logfont.lfCharSet = DEFAULT_CHARSET; 368 logfont.lfClipPrecision = 0; 369 logfont.lfItalic = 0; 370 logfont.lfOutPrecision = 0; 371 logfont.lfPitchAndFamily = DEFAULT_PITCH; 372 logfont.lfQuality = DEFAULT_QUALITY; 373 logfont.lfStrikeOut = 0; 374 logfont.lfUnderline = 0; 375 logfont.lfWeight = FW_NORMAL; 376 377 hfont = CreateFontIndirect(&logfont); 378 TranslateColor_Win32(draw, color); 379 if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer; 380 else hdc = windraw->node->Buffer; 381 382 SelectFont(hdc, hfont); 383 SetTextColor(hdc, windraw->currentcolor); 384 DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP | DT_SINGLELINE); 385 DeleteObject(hfont); 386 /* Forces a WM_PAINT message and erases background */ 387 InvalidateRect(windraw->hWnd, NULL, TRUE); 388 UpdateWindow(windraw->hWnd); 389 PetscFunctionReturn(PETSC_SUCCESS); 390 } 391 392 static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height) 393 { 394 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 395 int w, h; 396 397 PetscFunctionBegin; 398 w = (int)((windraw->w) * width * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl)); 399 h = (int)((windraw->h) * height * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl)); 400 if (h < 1) h = 1; 401 if (w < 1) w = 1; 402 windraw->stringheight = h; 403 windraw->stringwidth = w; 404 PetscFunctionReturn(PETSC_SUCCESS); 405 } 406 static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw, PetscReal *width, PetscReal *height) 407 { 408 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 409 double scaleX = (draw->coor_xr - draw->coor_xl) / (draw->w) * (draw->port_xr - draw->port_xl); 410 double scaleY = (draw->coor_yr - draw->coor_yl) / (draw->h) * (draw->port_yr - draw->port_yl); 411 412 PetscFunctionBegin; 413 if (height) *height = (double)windraw->stringheight * scaleY; 414 if (width) *width = (double)windraw->stringwidth * scaleX; 415 PetscFunctionReturn(PETSC_SUCCESS); 416 } 417 418 static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h) 419 { 420 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 421 RECT r; 422 423 PetscFunctionBegin; 424 GetWindowRect(windraw->hWnd, &r); 425 MoveWindow(windraw->hWnd, r.left, r.top, (int)w, (int)h, TRUE); 426 /* set all variable dealing with window dimensions */ 427 windraw->node->bitheight = windraw->h = draw->h = h; 428 windraw->node->bitwidth = windraw->w = draw->w = w; 429 /* set up graphic buffers with the new size of window */ 430 SetBitmapDimensionEx(windraw->node->BufferBit, w, h, NULL); 431 if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit, w, h, NULL); 432 windraw->haveresized = PETSC_TRUE; 433 PetscFunctionReturn(PETSC_SUCCESS); 434 } 435 436 static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw) 437 { 438 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 439 440 PetscFunctionBegin; 441 PetscCheck(windraw->haveresized != 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for resizing windows on Microsoft Windows"); 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[]) 446 { 447 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 448 449 PetscFunctionBegin; 450 SetWindowText(windraw->hWnd, title); 451 PetscFunctionReturn(PETSC_SUCCESS); 452 } 453 454 static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw) 455 { 456 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 457 458 PetscFunctionBegin; 459 /* clear primary buffer */ 460 ExtFloodFill(windraw->node->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER); 461 /* if exists clear secondary buffer */ 462 if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER); 463 464 /* force WM_PAINT message so cleared buffer will show */ 465 InvalidateRect(windraw->hWnd, NULL, TRUE); 466 UpdateWindow(windraw->hWnd); 467 PetscFunctionReturn(PETSC_SUCCESS); 468 } 469 470 static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw, PetscReal x1, PetscReal yone, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3) 471 { 472 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 473 HBRUSH hbrush; 474 HPEN hpen; 475 int p1x, p1y, p2x, p2y, p3x, p3y; 476 HDC bit; 477 478 PetscFunctionBegin; 479 AverageColorTriangle_Win32(draw, c1, c2, c3); 480 hbrush = CreateSolidBrush(windraw->currentcolor); 481 hpen = CreatePen(PS_SOLID, 0, windraw->currentcolor); 482 p1x = XTRANS(draw, windraw, x1); 483 p2x = XTRANS(draw, windraw, x2); 484 p3x = XTRANS(draw, windraw, x3); 485 p1y = YTRANS(draw, windraw, yone); 486 p2y = YTRANS(draw, windraw, y2); 487 p3y = YTRANS(draw, windraw, y3); 488 489 if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer; 490 else bit = windraw->node->Buffer; 491 492 BeginPath(bit); 493 MoveToEx(bit, p1x, p1y, NULL); 494 LineTo(bit, p2x, p2y); 495 LineTo(bit, p3x, p3y); 496 LineTo(bit, p1x, p1y); 497 EndPath(bit); 498 SelectPen(bit, hpen); 499 SelectBrush(bit, hbrush); 500 StrokeAndFillPath(bit); 501 /* Forces a WM_PAINT message and erases background */ 502 InvalidateRect(windraw->hWnd, NULL, TRUE); 503 UpdateWindow(windraw->hWnd); 504 PetscFunctionReturn(PETSC_SUCCESS); 505 } 506 507 static PetscErrorCode PetscDrawSetVisible_Win32(PetscDraw draw, PetscBool visible) 508 { 509 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 510 511 PetscFunctionBegin; 512 ShowWindow(windraw->hWnd, visible ? SW_SHOWNA : SW_HIDE); 513 PetscFunctionReturn(PETSC_SUCCESS); 514 } 515 516 static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw) 517 { 518 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 519 520 PetscFunctionBegin; 521 SendMessage(windraw->hWnd, WM_DESTROY, 0, 0); 522 PetscFree(draw->data); 523 PetscFunctionReturn(PETSC_SUCCESS); 524 } 525 526 static void MessageLoopThread_Win32(PetscDraw draw) 527 { 528 PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data; 529 MSG msg; 530 HWND hWnd = NULL; 531 const char classname[] = "PETSc Window Class"; 532 WNDCLASSEX wclass; 533 LPVOID lpMsgBuf; 534 535 /* initialize window class parameters */ 536 wclass.cbSize = sizeof(WNDCLASSEX); 537 wclass.style = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW; 538 wclass.lpfnWndProc = (WNDPROC)PetscWndProc; 539 wclass.cbClsExtra = 0; 540 wclass.cbWndExtra = 0; 541 wclass.hInstance = NULL; 542 wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 543 wclass.hCursor = LoadCursor(NULL, IDC_ARROW); 544 wclass.hbrBackground = GetStockBrush(WHITE_BRUSH); 545 wclass.lpszMenuName = NULL; 546 wclass.lpszClassName = classname; 547 wclass.hIconSm = NULL; 548 549 RegisterClassEx(&wclass); 550 551 hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL); 552 553 if (!hWnd) { 554 lpMsgBuf = (LPVOID) "Window Not Successfully Created"; 555 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION); 556 LocalFree(lpMsgBuf); 557 exit(0); 558 } 559 windraw->hWnd = hWnd; 560 /* display and update new window */ 561 ShowWindow(hWnd, SW_SHOWNORMAL); 562 UpdateWindow(hWnd); 563 SetEvent(windraw->hReadyEvent); 564 565 while (GetMessage(&msg, hWnd, 0, 0)) { 566 TranslateMessage(&msg); 567 DispatchMessage(&msg); 568 } 569 return; 570 } 571 572 static struct _PetscDrawOps DvOps = {PetscDrawSetDoubleBuffer_Win32, PetscDrawFlush_Win32, PetscDrawLine_Win32, PetscDrawLineSetWidth_Win32, PetscDrawLineGetWidth_Win32, PetscDrawPoint_Win32, PetscDrawPointSetSize_Win32, PetscDrawString_Win32, PetscDrawStringVertical_Win32, PetscDrawStringSetSize_Win32, PetscDrawStringGetSize_Win32, 0, PetscDrawClear_Win32, PetscDrawRectangle_Win32, PetscDrawTriangle_Win32, 0, PetscDrawGetMouseButton_Win32, PetscDrawPause_Win32, 0, 0, PetscDrawGetPopup_Win32, PetscDrawSetTitle_Win32, PetscDrawCheckResizedWindow_Win32, PetscDrawResizeWindow_Win32, PetscDrawDestroy_Win32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PetscDrawSetVisible_Win32}; 573 574 static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup) 575 { 576 PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data; 577 PetscBool flg = PETSC_TRUE; 578 579 PetscFunctionBegin; 580 PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL)); 581 if (flg) { 582 PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, win->x, win->y + win->h + 36, 220, 220, popup)); 583 PetscCall(PetscDrawSetType(*popup, PETSC_DRAW_WIN32)); 584 draw->popup = *popup; 585 } else { 586 *popup = NULL; 587 } 588 PetscFunctionReturn(PETSC_SUCCESS); 589 } 590 PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw) 591 { 592 PetscDraw_Win32 *windraw; 593 HANDLE hThread = NULL; 594 WindowNode newnode; 595 596 PetscFunctionBegin; 597 PetscCall(PetscNew(&windraw)); 598 draw->data = windraw; 599 600 /* the following is temporary fix for initializing a global datastructure */ 601 if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL, FALSE, NULL); 602 draw->ops[0] = DvOps; 603 604 windraw->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 605 /* makes call to MessageLoopThread to creat window and attach a thread */ 606 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoopThread_Win32, draw, 0, (LPDWORD)hThread); 607 CloseHandle(hThread); 608 WaitForSingleObject(windraw->hReadyEvent, INFINITE); 609 CloseHandle(windraw->hReadyEvent); 610 WaitForSingleObject(g_hWindowListMutex, INFINITE); 611 612 PetscCall(PetscNew(&newnode)); 613 newnode->MouseListHead = NULL; 614 newnode->MouseListTail = NULL; 615 newnode->wnext = WindowListHead; 616 newnode->wprev = NULL; 617 newnode->hWnd = windraw->hWnd; 618 if (WindowListHead) WindowListHead->wprev = newnode; 619 WindowListHead = newnode; 620 windraw->hdc = GetDC(windraw->hWnd); 621 622 windraw->stringheight = 10; 623 windraw->stringwidth = 6; 624 windraw->linewidth = 1; /* default pixel sizes of graphics until user changes them */ 625 windraw->pointdiameter = 1; 626 windraw->node = newnode; 627 628 windraw->x = draw->x; 629 windraw->y = draw->y; 630 windraw->w = newnode->bitwidth = draw->w; 631 windraw->h = newnode->bitheight = draw->h; 632 633 /* Create and initialize primary graphics buffer */ 634 newnode->Buffer = CreateCompatibleDC(windraw->hdc); 635 newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc, windraw->w, windraw->h); 636 newnode->store = SelectObject(newnode->Buffer, newnode->BufferBit); 637 ExtFloodFill(newnode->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER); 638 639 newnode->event = CreateEvent(NULL, TRUE, FALSE, NULL); 640 newnode->DoubleBuffered = PETSC_FALSE; 641 642 ReleaseDC(windraw->hWnd, windraw->hdc); 643 ReleaseMutex(g_hWindowListMutex); 644 PetscFunctionReturn(PETSC_SUCCESS); 645 } 646 647 /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG) 648 PURPOSE: Processes messages for the main window. 649 WM_COMMAND - process the application menu 650 WM_PAINT - Paint the main window 651 WM_DESTROY - post a quit message and return */ 652 653 LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 654 { 655 int wmId; 656 657 switch (message) { 658 HANDLE_MSG(hWnd, WM_PAINT, OnPaint_Win32); 659 HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy_Win32); 660 case WM_COMMAND: 661 wmId = LOWORD(wParam); 662 /* Parse the menu selections:*/ 663 switch (wmId) { 664 case IDM_EXIT: 665 DestroyWindow(hWnd); 666 break; 667 default: 668 return DefWindowProc(hWnd, message, wParam, lParam); 669 } 670 break; 671 case WM_LBUTTONUP: 672 MouseRecord_Win32(hWnd, PETSC_BUTTON_LEFT); 673 break; 674 case WM_RBUTTONUP: 675 MouseRecord_Win32(hWnd, PETSC_BUTTON_RIGHT); 676 break; 677 case WM_MBUTTONUP: 678 MouseRecord_Win32(hWnd, PETSC_BUTTON_CENTER); 679 break; 680 default: 681 return DefWindowProc(hWnd, message, wParam, lParam); 682 } 683 return 0; 684 } 685 686 static void OnPaint_Win32(HWND hWnd) 687 { 688 PAINTSTRUCT ps; 689 HDC hdc; 690 WindowNode current = NULL; 691 692 InvalidateRect(hWnd, NULL, TRUE); 693 WaitForSingleObject(g_hWindowListMutex, INFINITE); 694 current = WindowListHead; 695 hdc = BeginPaint(hWnd, &ps); 696 697 while (current) { 698 if (current->hWnd == hWnd) { 699 /* flushes primary buffer to window */ 700 BitBlt(hdc, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), current->Buffer, 0, 0, SRCCOPY); 701 702 /* StretchBlt(hdc,0,0,w,h, 703 current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */ 704 break; 705 } 706 current = current->wnext; 707 } 708 EndPaint(hWnd, &ps); 709 ReleaseMutex(g_hWindowListMutex); 710 return; 711 } 712 713 static PetscErrorCode MouseRecord_Win32(HWND hWnd, PetscDrawButton button) 714 { 715 /* Called by all three mouse button actions 716 Records needed mouse data in windows data structure */ 717 WindowNode current = NULL; 718 MouseNode newnode; 719 POINT mousepos; 720 721 PetscFunctionBegin; 722 WaitForSingleObject(g_hWindowListMutex, INFINITE); 723 current = WindowListHead; 724 if (current->IsGetMouseOn == TRUE) { 725 SetEvent(current->event); 726 while (current) { 727 if (current->hWnd == hWnd) { 728 PetscCall(PetscNew(&newnode)); 729 newnode->Button = button; 730 GetCursorPos(&mousepos); 731 newnode->user.x = mousepos.x; 732 newnode->user.y = mousepos.y; 733 ScreenToClient(hWnd, &mousepos); 734 newnode->phys.x = mousepos.x; 735 newnode->phys.y = mousepos.y; 736 if (!current->MouseListTail) { 737 current->MouseListHead = newnode; 738 current->MouseListTail = newnode; 739 } else { 740 current->MouseListTail->mnext = newnode; 741 current->MouseListTail = newnode; 742 } 743 newnode->mnext = NULL; 744 745 break; 746 } 747 current = current->wnext; 748 } 749 } 750 ReleaseMutex(g_hWindowListMutex); 751 PetscFunctionReturn(PETSC_SUCCESS); 752 } 753 754 static void OnDestroy_Win32(HWND hWnd) 755 { 756 /* searches linked list of window data and frees corresponding memory */ 757 WindowNode current; 758 759 PetscFunctionBegin; 760 WaitForSingleObject(g_hWindowListMutex, INFINITE); 761 current = WindowListHead; 762 763 SetEvent(current->event); 764 while (current) { 765 if (current->hWnd == hWnd) { 766 if (current->wprev) current->wprev->wnext = current->wnext; 767 else WindowListHead = current->wnext; 768 if (current->MouseListHead) deletemouselist_Win32(current); 769 else PetscFree(current); 770 break; 771 } 772 current = current->wnext; 773 } 774 ReleaseMutex(g_hWindowListMutex); 775 PostQuitMessage(0); 776 PetscFunctionReturnVoid(); 777 } 778