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