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