1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS uxtheme.dll 4 * FILE: dll/win32/uxtheme/nonclient.c 5 * PURPOSE: uxtheme non client area management 6 * PROGRAMMER: Giannis Adamopoulos 7 */ 8 9 #include "uxthemep.h" 10 11 static BOOL 12 IsWindowActive(HWND hWnd, DWORD ExStyle) 13 { 14 BOOL ret; 15 16 if (ExStyle & WS_EX_MDICHILD) 17 { 18 ret = IsChild(GetForegroundWindow(), hWnd); 19 if (ret) 20 ret = (hWnd == (HWND)SendMessageW(GetParent(hWnd), WM_MDIGETACTIVE, 0, 0)); 21 } 22 else 23 { 24 ret = (GetForegroundWindow() == hWnd); 25 } 26 27 return ret; 28 } 29 30 BOOL 31 IsScrollBarVisible(HWND hWnd, INT hBar) 32 { 33 SCROLLBARINFO sbi = {sizeof(SCROLLBARINFO)}; 34 if(!GetScrollBarInfo(hWnd, hBar, &sbi)) 35 return FALSE; 36 37 return !(sbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN); 38 } 39 40 static BOOL 41 UserHasWindowEdge(DWORD Style, DWORD ExStyle) 42 { 43 if (Style & WS_MINIMIZE) 44 return TRUE; 45 if (ExStyle & WS_EX_DLGMODALFRAME) 46 return TRUE; 47 if (ExStyle & WS_EX_STATICEDGE) 48 return FALSE; 49 if (Style & WS_THICKFRAME) 50 return TRUE; 51 Style &= WS_CAPTION; 52 if (Style == WS_DLGFRAME || Style == WS_CAPTION) 53 return TRUE; 54 return FALSE; 55 } 56 57 static HICON 58 UserGetWindowIcon(PDRAW_CONTEXT pcontext) 59 { 60 HICON hIcon = NULL; 61 62 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); 63 64 if (!hIcon) 65 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); 66 67 if (!hIcon) 68 SendMessageTimeout(pcontext->hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); 69 70 if (!hIcon) 71 hIcon = (HICON)GetClassLongPtr(pcontext->hWnd, GCLP_HICONSM); 72 73 if (!hIcon) 74 hIcon = (HICON)GetClassLongPtr(pcontext->hWnd, GCLP_HICON); 75 76 // See also win32ss/user/ntuser/nonclient.c!NC_IconForWindow 77 if (!hIcon && !(pcontext->wi.dwExStyle & WS_EX_DLGMODALFRAME)) 78 hIcon = LoadIconW(NULL, (LPCWSTR)IDI_WINLOGO); 79 80 return hIcon; 81 } 82 83 HRESULT WINAPI ThemeDrawCaptionText(PDRAW_CONTEXT pcontext, RECT* pRect, int iPartId, int iStateId) 84 { 85 HRESULT hr; 86 HFONT hFont = NULL; 87 HGDIOBJ oldFont = NULL; 88 LOGFONTW logfont; 89 COLORREF textColor; 90 COLORREF oldTextColor; 91 int align = CA_LEFT; 92 int drawStyles = DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS; 93 94 WCHAR buffer[50]; 95 WCHAR *pszText = buffer; 96 INT len; 97 98 len = InternalGetWindowText(pcontext->hWnd, NULL, 0); 99 if (!len) 100 return S_OK; 101 102 len++; /* From now on this is the size of the buffer so include the null */ 103 104 if (len > ARRAYSIZE(buffer)) 105 { 106 pszText = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 107 if (!pszText) 108 return E_OUTOFMEMORY; 109 } 110 111 InternalGetWindowText(pcontext->hWnd, pszText, len); 112 113 hr = GetThemeSysFont(0,TMT_CAPTIONFONT,&logfont); 114 if(SUCCEEDED(hr)) 115 hFont = CreateFontIndirectW(&logfont); 116 117 if(hFont) 118 oldFont = SelectObject(pcontext->hDC, hFont); 119 120 if (!pcontext->Active) 121 textColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT); 122 else 123 textColor = GetSysColor(COLOR_CAPTIONTEXT); 124 125 GetThemeEnumValue(pcontext->theme, iPartId, iStateId, TMT_CONTENTALIGNMENT, &align); 126 if (align == CA_CENTER) 127 drawStyles |= DT_CENTER; 128 else if (align == CA_RIGHT) 129 drawStyles |= DT_RIGHT; 130 131 oldTextColor = SetTextColor(pcontext->hDC, textColor); 132 DrawThemeText(pcontext->theme, 133 pcontext->hDC, 134 iPartId, 135 iStateId, 136 pszText, 137 len - 1, 138 drawStyles, 139 0, 140 pRect); 141 SetTextColor(pcontext->hDC, oldTextColor); 142 143 if (hFont) 144 { 145 SelectObject(pcontext->hDC, oldFont); 146 DeleteObject(hFont); 147 } 148 if (pszText != buffer) 149 { 150 HeapFree(GetProcessHeap(), 0, pszText); 151 } 152 return S_OK; 153 } 154 155 void 156 ThemeInitDrawContext(PDRAW_CONTEXT pcontext, 157 HWND hWnd, 158 HRGN hRgn) 159 { 160 pcontext->wi.cbSize = sizeof(pcontext->wi); 161 GetWindowInfo(hWnd, &pcontext->wi); 162 pcontext->hWnd = hWnd; 163 pcontext->Active = IsWindowActive(hWnd, pcontext->wi.dwExStyle); 164 pcontext->theme = GetNCCaptionTheme(hWnd, pcontext->wi.dwStyle); 165 pcontext->scrolltheme = GetNCScrollbarTheme(hWnd, pcontext->wi.dwStyle); 166 167 pcontext->CaptionHeight = pcontext->wi.cyWindowBorders; 168 pcontext->CaptionHeight += GetSystemMetrics(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION ); 169 170 if(hRgn <= (HRGN)1) 171 { 172 hRgn = CreateRectRgnIndirect(&pcontext->wi.rcWindow); 173 } 174 pcontext->hRgn = hRgn; 175 176 pcontext->hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN); 177 } 178 179 void 180 ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext) 181 { 182 ReleaseDC(pcontext->hWnd ,pcontext->hDC); 183 184 if(pcontext->hRgn != NULL) 185 { 186 DeleteObject(pcontext->hRgn); 187 } 188 } 189 190 static void 191 ThemeStartBufferedPaint(PDRAW_CONTEXT pcontext, int cx, int cy) 192 { 193 HBITMAP hbmp; 194 195 pcontext->hDCScreen = pcontext->hDC; 196 pcontext->hDC = CreateCompatibleDC(pcontext->hDCScreen); 197 hbmp = CreateCompatibleBitmap(pcontext->hDCScreen, cx, cy); 198 pcontext->hbmpOld = (HBITMAP)SelectObject(pcontext->hDC, hbmp); 199 } 200 201 static void 202 ThemeEndBufferedPaint(PDRAW_CONTEXT pcontext, int x, int y, int cx, int cy) 203 { 204 HBITMAP hbmp; 205 BitBlt(pcontext->hDCScreen, 0, 0, cx, cy, pcontext->hDC, x, y, SRCCOPY); 206 hbmp = (HBITMAP) SelectObject(pcontext->hDC, pcontext->hbmpOld); 207 DeleteObject(pcontext->hDC); 208 DeleteObject(hbmp); 209 210 pcontext->hDC = pcontext->hDCScreen; 211 } 212 213 void ThemeCalculateCaptionButtonsPos(HWND hWnd, HTHEME htheme) 214 { 215 PWND_DATA pwndData; 216 DWORD style; 217 INT ButtonWidth, ButtonHeight, iPartId, i; 218 WINDOWINFO wi = {sizeof(wi)}; 219 RECT rcCurrent; 220 SIZE ButtonSize; 221 222 /* First of all check if we have something to do here */ 223 style = GetWindowLongW(hWnd, GWL_STYLE); 224 if((style & (WS_CAPTION | WS_SYSMENU)) != (WS_CAPTION | WS_SYSMENU)) 225 return; 226 227 /* Get theme data for this window */ 228 pwndData = ThemeGetWndData(hWnd); 229 if (pwndData == NULL) 230 return; 231 232 if (!htheme) 233 { 234 htheme = GetNCCaptionTheme(hWnd, style); 235 if (!htheme) 236 return; 237 } 238 239 if(!GetWindowInfo(hWnd, &wi)) 240 return; 241 242 /* Calculate the area of the caption */ 243 rcCurrent.top = rcCurrent.left = 0; 244 rcCurrent.right = wi.rcWindow.right - wi.rcWindow.left; 245 rcCurrent.bottom = wi.rcWindow.bottom - wi.rcWindow.top; 246 247 /* Add a padding around the objects of the caption */ 248 InflateRect(&rcCurrent, -(int)wi.cyWindowBorders-BUTTON_GAP_SIZE, 249 -(int)wi.cyWindowBorders-BUTTON_GAP_SIZE); 250 251 iPartId = wi.dwExStyle & WS_EX_TOOLWINDOW ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; 252 253 GetThemePartSize(htheme, NULL, iPartId, 0, NULL, TS_MIN, &ButtonSize); 254 255 ButtonHeight = GetSystemMetrics( wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMSIZE : SM_CYSIZE); 256 ButtonWidth = MulDiv(ButtonSize.cx, ButtonHeight, ButtonSize.cy); 257 258 ButtonHeight -= 4; 259 ButtonWidth -= 4; 260 261 for (i = CLOSEBUTTON; i <= HELPBUTTON; i++) 262 { 263 SetRect(&pwndData->rcCaptionButtons[i], 264 rcCurrent.right - ButtonWidth, 265 rcCurrent.top, 266 rcCurrent.right, 267 rcCurrent.top + ButtonHeight); 268 269 rcCurrent.right -= ButtonWidth + BUTTON_GAP_SIZE; 270 } 271 } 272 273 static void 274 ThemeDrawCaptionButton(PDRAW_CONTEXT pcontext, 275 RECT* prcCurrent, 276 CAPTIONBUTTON buttonId, 277 INT iStateId) 278 { 279 INT iPartId; 280 HMENU SysMenu; 281 UINT MenuState; 282 PWND_DATA pwndData = ThemeGetWndData(pcontext->hWnd); 283 if (!pwndData) 284 return; 285 286 switch(buttonId) 287 { 288 case CLOSEBUTTON: 289 SysMenu = GetSystemMenu(pcontext->hWnd, FALSE); 290 MenuState = GetMenuState(SysMenu, SC_CLOSE, MF_BYCOMMAND); 291 if (!(pcontext->wi.dwStyle & WS_SYSMENU) || (MenuState & (MF_GRAYED | MF_DISABLED)) || pcontext->wi.dwStyle & CS_NOCLOSE) 292 { 293 iStateId = (pcontext->Active ? BUTTON_DISABLED : BUTTON_INACTIVE_DISABLED); 294 } 295 296 iPartId = pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; 297 break; 298 299 case MAXBUTTON: 300 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX)) 301 { 302 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX)) 303 return; 304 else 305 iStateId = (pcontext->Active ? BUTTON_DISABLED : BUTTON_INACTIVE_DISABLED); 306 } 307 308 iPartId = pcontext->wi.dwStyle & WS_MAXIMIZE ? WP_RESTOREBUTTON : WP_MAXBUTTON; 309 break; 310 311 case MINBUTTON: 312 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX)) 313 { 314 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX)) 315 return; 316 else 317 iStateId = (pcontext->Active ? BUTTON_DISABLED : BUTTON_INACTIVE_DISABLED); 318 } 319 320 iPartId = pcontext->wi.dwStyle & WS_MINIMIZE ? WP_RESTOREBUTTON : WP_MINBUTTON; 321 break; 322 323 default: 324 //FIXME: Implement Help Button 325 return; 326 } 327 328 if (prcCurrent) 329 prcCurrent->right = pwndData->rcCaptionButtons[buttonId].left; 330 331 DrawThemeBackground(pcontext->theme, pcontext->hDC, iPartId, iStateId, &pwndData->rcCaptionButtons[buttonId], NULL); 332 } 333 334 static DWORD 335 ThemeGetButtonState(DWORD htCurrect, DWORD htHot, DWORD htDown, BOOL Active) 336 { 337 if (htHot == htCurrect) 338 return (Active ? BUTTON_HOT : BUTTON_INACTIVE_HOT); 339 if (htDown == htCurrect) 340 return (Active ? BUTTON_PRESSED : BUTTON_INACTIVE_PRESSED); 341 342 return (Active ? BUTTON_NORMAL : BUTTON_INACTIVE); 343 } 344 345 /* Used only from mouse event handlers */ 346 static void 347 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext, DWORD htHot, DWORD htDown) 348 { 349 /* Draw the buttons */ 350 ThemeDrawCaptionButton(pcontext, NULL, CLOSEBUTTON, 351 ThemeGetButtonState(HTCLOSE, htHot, htDown, pcontext->Active)); 352 ThemeDrawCaptionButton(pcontext, NULL, MAXBUTTON, 353 ThemeGetButtonState(HTMAXBUTTON, htHot, htDown, pcontext->Active)); 354 ThemeDrawCaptionButton(pcontext, NULL, MINBUTTON, 355 ThemeGetButtonState(HTMINBUTTON, htHot, htDown, pcontext->Active)); 356 ThemeDrawCaptionButton(pcontext, NULL, HELPBUTTON, 357 ThemeGetButtonState(HTHELP, htHot, htDown, pcontext->Active)); 358 } 359 360 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */ 361 static void 362 ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 363 { 364 RECT rcPart; 365 int iPart, iState; 366 HICON hIcon; 367 368 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar 369 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption 370 if ((pcontext->wi.dwStyle & WS_SYSMENU) && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)) 371 hIcon = UserGetWindowIcon(pcontext); 372 else 373 hIcon = NULL; 374 375 /* Get the caption part and state id */ 376 if (pcontext->wi.dwStyle & WS_MINIMIZE) 377 iPart = WP_MINCAPTION; 378 else if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW) 379 iPart = WP_SMALLCAPTION; 380 else if (pcontext->wi.dwStyle & WS_MAXIMIZE) 381 iPart = WP_MAXCAPTION; 382 else 383 iPart = WP_CAPTION; 384 385 iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE; 386 387 /* Draw the caption background */ 388 rcPart = *prcCurrent; 389 rcPart.bottom = rcPart.top + pcontext->CaptionHeight; 390 prcCurrent->top = rcPart.bottom; 391 DrawThemeBackground(pcontext->theme, pcontext->hDC,iPart,iState,&rcPart,NULL); 392 393 /* Add a padding around the objects of the caption */ 394 InflateRect(&rcPart, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE, 395 -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE); 396 397 /* Draw the caption buttons */ 398 if (pcontext->wi.dwStyle & WS_SYSMENU) 399 { 400 iState = pcontext->Active ? BUTTON_NORMAL : BUTTON_INACTIVE; 401 402 ThemeDrawCaptionButton(pcontext, &rcPart, CLOSEBUTTON, iState); 403 ThemeDrawCaptionButton(pcontext, &rcPart, MAXBUTTON, iState); 404 ThemeDrawCaptionButton(pcontext, &rcPart, MINBUTTON, iState); 405 ThemeDrawCaptionButton(pcontext, &rcPart, HELPBUTTON, iState); 406 } 407 408 rcPart.top += 3 ; 409 410 /* Draw the icon */ 411 if (hIcon) 412 { 413 int IconHeight = GetSystemMetrics(SM_CYSMICON); 414 int IconWidth = GetSystemMetrics(SM_CXSMICON); 415 DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, IconHeight, 0, NULL, DI_NORMAL); 416 rcPart.left += IconWidth + 4; 417 } 418 419 rcPart.right -= 4; 420 421 /* Draw the caption */ 422 ThemeDrawCaptionText(pcontext, &rcPart, iPart, iState); 423 } 424 425 static void 426 ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 427 { 428 RECT rcPart; 429 int iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE; 430 431 /* Draw the bottom border */ 432 rcPart = *prcCurrent; 433 rcPart.top = rcPart.bottom - pcontext->wi.cyWindowBorders; 434 prcCurrent->bottom = rcPart.top; 435 DrawThemeBackground(pcontext->theme, pcontext->hDC, WP_FRAMEBOTTOM, iState, &rcPart, NULL); 436 437 /* Draw the left border */ 438 rcPart = *prcCurrent; 439 rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ; 440 prcCurrent->left = rcPart.right; 441 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL); 442 443 /* Draw the right border */ 444 rcPart = *prcCurrent; 445 rcPart.left = rcPart.right - pcontext->wi.cxWindowBorders; 446 prcCurrent->right = rcPart.left; 447 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMERIGHT, iState, &rcPart, NULL); 448 } 449 450 static void 451 DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent) 452 { 453 /* Draw outer edge */ 454 if (UserHasWindowEdge(context->wi.dwStyle, context->wi.dwExStyle)) 455 { 456 DrawEdge(context->hDC, prcCurrent, EDGE_RAISED, BF_RECT | BF_ADJUST); 457 } 458 else if (context->wi.dwExStyle & WS_EX_STATICEDGE) 459 { 460 DrawEdge(context->hDC, prcCurrent, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT); 461 } 462 463 /* Firstly the "thick" frame */ 464 if ((context->wi.dwStyle & WS_THICKFRAME) && !(context->wi.dwStyle & WS_MINIMIZE)) 465 { 466 INT Width = 467 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) * 468 GetSystemMetrics(SM_CXBORDER); 469 INT Height = 470 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) * 471 GetSystemMetrics(SM_CYBORDER); 472 473 SelectObject(context->hDC, GetSysColorBrush( 474 context->Active ? COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER)); 475 476 /* Draw frame */ 477 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 478 prcCurrent->right - prcCurrent->left, Height, PATCOPY); 479 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 480 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 481 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1, 482 prcCurrent->right - prcCurrent->left, -Height, PATCOPY); 483 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top, 484 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 485 486 InflateRect(prcCurrent, -Width, -Height); 487 } 488 489 /* Now the other bit of the frame */ 490 if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || (context->wi.dwExStyle & WS_EX_DLGMODALFRAME)) 491 { 492 INT Width = GetSystemMetrics(SM_CXBORDER); 493 INT Height = GetSystemMetrics(SM_CYBORDER); 494 495 SelectObject(context->hDC, GetSysColorBrush( 496 (context->wi.dwExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE : 497 (context->wi.dwExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME : 498 (context->wi.dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE : 499 COLOR_WINDOWFRAME)); 500 501 /* Draw frame */ 502 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 503 prcCurrent->right - prcCurrent->left, Height, PATCOPY); 504 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 505 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 506 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1, 507 prcCurrent->right - prcCurrent->left, -Height, PATCOPY); 508 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top, 509 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 510 511 InflateRect(prcCurrent, -Width, -Height); 512 } 513 } 514 515 static void ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 516 { 517 /* Let the window manager paint the menu */ 518 prcCurrent->top += PaintMenuBar(pcontext->hWnd, 519 pcontext->hDC, 520 pcontext->wi.cxWindowBorders, 521 pcontext->wi.cxWindowBorders, 522 prcCurrent->top, 523 pcontext->Active); 524 } 525 526 static void ThemeDrawScrollBarsGrip(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 527 { 528 RECT rcPart; 529 HWND hwndParent; 530 RECT ParentClientRect; 531 DWORD ParentStyle; 532 533 rcPart = *prcCurrent; 534 535 if (pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR) 536 rcPart.right = rcPart.left + GetSystemMetrics(SM_CXVSCROLL); 537 else 538 rcPart.left = rcPart.right - GetSystemMetrics(SM_CXVSCROLL); 539 540 rcPart.top = rcPart.bottom - GetSystemMetrics(SM_CYHSCROLL); 541 542 FillRect(pcontext->hDC, &rcPart, GetSysColorBrush(COLOR_BTNFACE)); 543 544 hwndParent = GetParent(pcontext->hWnd); 545 GetClientRect(hwndParent, &ParentClientRect); 546 ParentStyle = GetWindowLongW(hwndParent, GWL_STYLE); 547 548 if (HASSIZEGRIP(pcontext->wi.dwStyle, pcontext->wi.dwExStyle, ParentStyle, pcontext->wi.rcWindow, ParentClientRect)) 549 { 550 int iState; 551 if (pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR) 552 iState = pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR; 553 else 554 iState = SZB_RIGHTALIGN; 555 DrawThemeBackground(pcontext->scrolltheme, pcontext->hDC, SBP_SIZEBOX, iState, &rcPart, NULL); 556 } 557 } 558 559 static void 560 ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent, BOOL bDoDoubleBuffering) 561 { 562 if(!(pcontext->wi.dwStyle & WS_VISIBLE)) 563 return; 564 565 if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION) 566 { 567 if (bDoDoubleBuffering) 568 ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight); 569 ThemeDrawCaption(pcontext, prcCurrent); 570 if (bDoDoubleBuffering) 571 ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight); 572 ThemeDrawBorders(pcontext, prcCurrent); 573 } 574 else 575 { 576 DrawClassicFrame(pcontext, prcCurrent); 577 } 578 579 if(pcontext->wi.dwStyle & WS_MINIMIZE) 580 return; 581 582 if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle)) 583 ThemeDrawMenuBar(pcontext, prcCurrent); 584 585 if (pcontext->wi.dwExStyle & WS_EX_CLIENTEDGE) 586 DrawEdge(pcontext->hDC, prcCurrent, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 587 588 if((pcontext->wi.dwStyle & WS_HSCROLL) && IsScrollBarVisible(pcontext->hWnd, OBJID_HSCROLL)) 589 ThemeDrawScrollBar(pcontext, SB_HORZ , NULL); 590 591 if((pcontext->wi.dwStyle & WS_VSCROLL) && IsScrollBarVisible(pcontext->hWnd, OBJID_VSCROLL)) 592 ThemeDrawScrollBar(pcontext, SB_VERT, NULL); 593 594 if((pcontext->wi.dwStyle & (WS_HSCROLL|WS_VSCROLL)) == (WS_HSCROLL|WS_VSCROLL) && 595 IsScrollBarVisible(pcontext->hWnd, OBJID_HSCROLL) && 596 IsScrollBarVisible(pcontext->hWnd, OBJID_VSCROLL)) 597 { 598 ThemeDrawScrollBarsGrip(pcontext, prcCurrent); 599 } 600 } 601 602 /* 603 * Message handlers 604 */ 605 606 static LRESULT 607 ThemeHandleNCPaint(HWND hWnd, HRGN hRgn) 608 { 609 DRAW_CONTEXT context; 610 RECT rcCurrent; 611 612 ThemeInitDrawContext(&context, hWnd, hRgn); 613 614 rcCurrent = context.wi.rcWindow; 615 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top); 616 617 ThemePaintWindow(&context, &rcCurrent, TRUE); 618 ThemeCleanupDrawContext(&context); 619 620 return 0; 621 } 622 623 static LRESULT 624 ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt) 625 { 626 DRAW_CONTEXT context; 627 TRACKMOUSEEVENT tme; 628 DWORD style; 629 PWND_DATA pwndData; 630 631 /* First of all check if we have something to do here */ 632 style = GetWindowLongW(hWnd, GWL_STYLE); 633 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0) 634 return 0; 635 636 /* Get theme data for this window */ 637 pwndData = ThemeGetWndData(hWnd); 638 if (pwndData == NULL) 639 return 0; 640 641 /* Begin tracking in the non client area if we are not tracking yet */ 642 tme.cbSize = sizeof(TRACKMOUSEEVENT); 643 tme.dwFlags = TME_QUERY; 644 tme.hwndTrack = hWnd; 645 TrackMouseEvent(&tme); 646 if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT)) 647 { 648 tme.hwndTrack = hWnd; 649 tme.dwFlags = TME_LEAVE | TME_NONCLIENT; 650 TrackMouseEvent(&tme); 651 } 652 653 ThemeInitDrawContext(&context, hWnd, 0); 654 if (context.wi.dwStyle & WS_SYSMENU) 655 { 656 if (HT_ISBUTTON(ht) || HT_ISBUTTON(pwndData->lastHitTest)) 657 ThemeDrawCaptionButtons(&context, ht, 0); 658 } 659 660 if (context.wi.dwStyle & WS_HSCROLL) 661 { 662 if (ht == HTHSCROLL || pwndData->lastHitTest == HTHSCROLL) 663 ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL); 664 } 665 666 if (context.wi.dwStyle & WS_VSCROLL) 667 { 668 if (ht == HTVSCROLL || pwndData->lastHitTest == HTVSCROLL) 669 ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL); 670 } 671 ThemeCleanupDrawContext(&context); 672 673 pwndData->lastHitTest = ht; 674 675 return 0; 676 } 677 678 static LRESULT 679 ThemeHandleNcMouseLeave(HWND hWnd) 680 { 681 DRAW_CONTEXT context; 682 DWORD style; 683 PWND_DATA pwndData; 684 685 /* First of all check if we have something to do here */ 686 style = GetWindowLongW(hWnd, GWL_STYLE); 687 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0) 688 return 0; 689 690 /* Get theme data for this window */ 691 pwndData = ThemeGetWndData(hWnd); 692 if (pwndData == NULL) 693 return 0; 694 695 ThemeInitDrawContext(&context, hWnd, 0); 696 if (context.wi.dwStyle & WS_SYSMENU && HT_ISBUTTON(pwndData->lastHitTest)) 697 ThemeDrawCaptionButtons(&context, 0, 0); 698 699 if (context.wi.dwStyle & WS_HSCROLL && pwndData->lastHitTest == HTHSCROLL) 700 ThemeDrawScrollBar(&context, SB_HORZ, NULL); 701 702 if (context.wi.dwStyle & WS_VSCROLL && pwndData->lastHitTest == HTVSCROLL) 703 ThemeDrawScrollBar(&context, SB_VERT, NULL); 704 705 ThemeCleanupDrawContext(&context); 706 707 pwndData->lastHitTest = HTNOWHERE; 708 709 return 0; 710 } 711 712 static VOID 713 ThemeHandleButton(HWND hWnd, WPARAM wParam) 714 { 715 MSG Msg; 716 BOOL Pressed = TRUE; 717 WPARAM SCMsg, ht; 718 ULONG Style; 719 DRAW_CONTEXT context; 720 PWND_DATA pwndData; 721 722 Style = GetWindowLongW(hWnd, GWL_STYLE); 723 if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU))) 724 return ; 725 726 switch (wParam) 727 { 728 case HTCLOSE: 729 SCMsg = SC_CLOSE; 730 break; 731 case HTMINBUTTON: 732 if (!(Style & WS_MINIMIZEBOX)) 733 return; 734 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE); 735 break; 736 case HTMAXBUTTON: 737 if (!(Style & WS_MAXIMIZEBOX)) 738 return; 739 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE); 740 break; 741 default : 742 return; 743 } 744 745 /* Get theme data for this window */ 746 pwndData = ThemeGetWndData(hWnd); 747 if (pwndData == NULL) 748 return; 749 750 ThemeInitDrawContext(&context, hWnd, 0); 751 ThemeDrawCaptionButtons(&context, 0, wParam); 752 pwndData->lastHitTest = wParam; 753 754 SetCapture(hWnd); 755 756 ht = wParam; 757 758 for (;;) 759 { 760 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0) 761 break; 762 763 if (Msg.message == WM_LBUTTONUP) 764 break; 765 766 if (Msg.message != WM_MOUSEMOVE) 767 continue; 768 769 ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y)); 770 Pressed = (ht == wParam); 771 772 /* Only draw the buttons if the hit test changed */ 773 if (ht != pwndData->lastHitTest && 774 (HT_ISBUTTON(ht) || HT_ISBUTTON(pwndData->lastHitTest))) 775 { 776 ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0); 777 pwndData->lastHitTest = ht; 778 } 779 } 780 781 ThemeDrawCaptionButtons(&context, ht, 0); 782 ThemeCleanupDrawContext(&context); 783 784 ReleaseCapture(); 785 786 if (Pressed) 787 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0); 788 } 789 790 791 static LRESULT 792 DefWndNCHitTest(HWND hWnd, POINT Point) 793 { 794 RECT WindowRect; 795 POINT ClientPoint; 796 WINDOWINFO wi; 797 798 wi.cbSize = sizeof(wi); 799 GetWindowInfo(hWnd, &wi); 800 801 if (!PtInRect(&wi.rcWindow, Point)) 802 { 803 return HTNOWHERE; 804 } 805 WindowRect = wi.rcWindow; 806 807 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle)) 808 { 809 LONG XSize, YSize; 810 811 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders); 812 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER); 813 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER); 814 if (!PtInRect(&WindowRect, Point)) 815 { 816 BOOL ThickFrame; 817 818 ThickFrame = (wi.dwStyle & WS_THICKFRAME); 819 if (Point.y < WindowRect.top) 820 { 821 if(wi.dwStyle & WS_MINIMIZE) 822 return HTCAPTION; 823 if(!ThickFrame) 824 return HTBORDER; 825 if (Point.x < (WindowRect.left + XSize)) 826 return HTTOPLEFT; 827 if (Point.x >= (WindowRect.right - XSize)) 828 return HTTOPRIGHT; 829 return HTTOP; 830 } 831 if (Point.y >= WindowRect.bottom) 832 { 833 if(wi.dwStyle & WS_MINIMIZE) 834 return HTCAPTION; 835 if(!ThickFrame) 836 return HTBORDER; 837 if (Point.x < (WindowRect.left + XSize)) 838 return HTBOTTOMLEFT; 839 if (Point.x >= (WindowRect.right - XSize)) 840 return HTBOTTOMRIGHT; 841 return HTBOTTOM; 842 } 843 if (Point.x < WindowRect.left) 844 { 845 if(wi.dwStyle & WS_MINIMIZE) 846 return HTCAPTION; 847 if(!ThickFrame) 848 return HTBORDER; 849 if (Point.y < (WindowRect.top + YSize)) 850 return HTTOPLEFT; 851 if (Point.y >= (WindowRect.bottom - YSize)) 852 return HTBOTTOMLEFT; 853 return HTLEFT; 854 } 855 if (Point.x >= WindowRect.right) 856 { 857 if(wi.dwStyle & WS_MINIMIZE) 858 return HTCAPTION; 859 if(!ThickFrame) 860 return HTBORDER; 861 if (Point.y < (WindowRect.top + YSize)) 862 return HTTOPRIGHT; 863 if (Point.y >= (WindowRect.bottom - YSize)) 864 return HTBOTTOMRIGHT; 865 return HTRIGHT; 866 } 867 } 868 } 869 else 870 { 871 if (wi.dwExStyle & WS_EX_STATICEDGE) 872 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER), 873 -GetSystemMetrics(SM_CYBORDER)); 874 if (!PtInRect(&WindowRect, Point)) 875 return HTBORDER; 876 } 877 878 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION) 879 { 880 if (wi.dwExStyle & WS_EX_TOOLWINDOW) 881 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION); 882 else 883 WindowRect.top += GetSystemMetrics(SM_CYCAPTION); 884 885 if (!PtInRect(&WindowRect, Point)) 886 { 887 if (wi.dwStyle & WS_SYSMENU) 888 { 889 PWND_DATA pwndData = ThemeGetWndData(hWnd); 890 891 if (!(wi.dwExStyle & WS_EX_TOOLWINDOW)) 892 { 893 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME)) 894 // FIXME: The real test should check whether there is 895 // an icon for the system window, and if so, do the 896 // rect.left increase. 897 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest 898 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does 899 // the test better. 900 WindowRect.left += GetSystemMetrics(SM_CXSMICON); 901 } 902 903 if (pwndData) 904 { 905 POINT pt = {Point.x - wi.rcWindow.left, Point.y - wi.rcWindow.top}; 906 if (PtInRect(&pwndData->rcCaptionButtons[CLOSEBUTTON], pt)) 907 return HTCLOSE; 908 if (PtInRect(&pwndData->rcCaptionButtons[MAXBUTTON], pt)) 909 return HTMAXBUTTON; 910 if (PtInRect(&pwndData->rcCaptionButtons[MINBUTTON], pt)) 911 return HTMINBUTTON; 912 } 913 } 914 if (Point.x < WindowRect.left) 915 return HTSYSMENU; 916 return HTCAPTION; 917 } 918 } 919 920 if(!(wi.dwStyle & WS_MINIMIZE)) 921 { 922 HMENU menu; 923 924 ClientPoint = Point; 925 ScreenToClient(hWnd, &ClientPoint); 926 GetClientRect(hWnd, &wi.rcClient); 927 928 if (PtInRect(&wi.rcClient, ClientPoint)) 929 { 930 return HTCLIENT; 931 } 932 933 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD)) 934 { 935 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0) 936 return HTMENU; 937 } 938 939 if (wi.dwExStyle & WS_EX_CLIENTEDGE) 940 { 941 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER), 942 -2 * GetSystemMetrics(SM_CYBORDER)); 943 } 944 945 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) && 946 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL)) 947 { 948 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect; 949 HWND Parent = GetParent(hWnd); 950 951 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL); 952 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 953 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL); 954 else 955 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL); 956 if (PtInRect(&TempRect, Point)) 957 return HTVSCROLL; 958 959 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL); 960 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 961 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL); 962 else 963 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL); 964 if (PtInRect(&TempRect2, Point)) 965 return HTHSCROLL; 966 967 TempRect.top = TempRect2.top; 968 TempRect.bottom = TempRect2.bottom; 969 if(Parent) 970 GetClientRect(Parent, &ParentRect); 971 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle, 972 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect)) 973 { 974 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 975 return HTBOTTOMLEFT; 976 else 977 return HTBOTTOMRIGHT; 978 } 979 } 980 else 981 { 982 if (wi.dwStyle & WS_VSCROLL) 983 { 984 RECT TempRect = WindowRect; 985 986 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 987 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL); 988 else 989 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL); 990 if (PtInRect(&TempRect, Point)) 991 return HTVSCROLL; 992 } 993 else if (wi.dwStyle & WS_HSCROLL) 994 { 995 RECT TempRect = WindowRect; 996 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL); 997 if (PtInRect(&TempRect, Point)) 998 return HTHSCROLL; 999 } 1000 } 1001 } 1002 1003 return HTNOWHERE; 1004 } 1005 1006 LRESULT CALLBACK 1007 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc) 1008 { 1009 switch(Msg) 1010 { 1011 case WM_NCPAINT: 1012 return ThemeHandleNCPaint(hWnd, (HRGN)wParam); 1013 // 1014 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags. 1015 // 1016 case WM_NCUAHDRAWCAPTION: 1017 // 1018 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND. 1019 // 1020 case WM_NCUAHDRAWFRAME: 1021 case WM_NCACTIVATE: 1022 1023 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) != WS_CAPTION) 1024 return TRUE; 1025 1026 ThemeHandleNCPaint(hWnd, (HRGN)1); 1027 return TRUE; 1028 case WM_NCMOUSEMOVE: 1029 { 1030 POINT Point; 1031 Point.x = GET_X_LPARAM(lParam); 1032 Point.y = GET_Y_LPARAM(lParam); 1033 return ThemeHandleNcMouseMove(hWnd, wParam, &Point); 1034 } 1035 case WM_NCMOUSELEAVE: 1036 return ThemeHandleNcMouseLeave(hWnd); 1037 case WM_NCLBUTTONDOWN: 1038 switch (wParam) 1039 { 1040 case HTMINBUTTON: 1041 case HTMAXBUTTON: 1042 case HTCLOSE: 1043 { 1044 ThemeHandleButton(hWnd, wParam); 1045 return 0; 1046 } 1047 default: 1048 return DefWndProc(hWnd, Msg, wParam, lParam); 1049 } 1050 case WM_NCHITTEST: 1051 { 1052 POINT Point; 1053 Point.x = GET_X_LPARAM(lParam); 1054 Point.y = GET_Y_LPARAM(lParam); 1055 return DefWndNCHitTest(hWnd, Point); 1056 } 1057 case WM_SYSCOMMAND: 1058 { 1059 if((wParam & 0xfff0) == SC_VSCROLL || 1060 (wParam & 0xfff0) == SC_HSCROLL) 1061 { 1062 POINT Pt; 1063 Pt.x = (short)LOWORD(lParam); 1064 Pt.y = (short)HIWORD(lParam); 1065 NC_TrackScrollBar(hWnd, wParam, Pt); 1066 return 0; 1067 } 1068 else 1069 { 1070 return DefWndProc(hWnd, Msg, wParam, lParam); 1071 } 1072 } 1073 default: 1074 return DefWndProc(hWnd, Msg, wParam, lParam); 1075 } 1076 } 1077 1078 HRESULT WINAPI DrawNCPreview(HDC hDC, 1079 DWORD DNCP_Flag, 1080 LPRECT prcPreview, 1081 LPCWSTR pszThemeFileName, 1082 LPCWSTR pszColorName, 1083 LPCWSTR pszSizeName, 1084 PNONCLIENTMETRICSW pncMetrics, 1085 COLORREF* lpaRgbValues) 1086 { 1087 WNDCLASSEXW DummyPreviewWindowClass; 1088 HWND hwndDummy; 1089 HRESULT hres; 1090 HTHEMEFILE hThemeFile; 1091 DRAW_CONTEXT context; 1092 RECT rcCurrent; 1093 1094 /* FIXME: We also need to implement drawing the rest of the preview windows 1095 * and make use of the ncmetrics and colors passed as parameters */ 1096 1097 /* Create a dummy window that will be used to trick the paint funtions */ 1098 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass)); 1099 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass); 1100 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass"; 1101 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 1102 DummyPreviewWindowClass.hInstance = hDllInst; 1103 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW; 1104 if (!RegisterClassExW(&DummyPreviewWindowClass)) 1105 return E_FAIL; 1106 1107 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL); 1108 if (!hwndDummy) 1109 return E_FAIL; 1110 1111 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0); 1112 if (FAILED(hres)) 1113 return hres; 1114 1115 /* Initialize the special draw context for the preview */ 1116 context.hDC = hDC; 1117 context.hWnd = hwndDummy; 1118 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0); 1119 if (!context.theme) 1120 return E_FAIL; 1121 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0); 1122 if (!context.scrolltheme) 1123 return E_FAIL; 1124 context.Active = TRUE; 1125 context.wi.cbSize = sizeof(context.wi); 1126 if (!GetWindowInfo(hwndDummy, &context.wi)) 1127 return E_FAIL; 1128 context.wi.dwStyle |= WS_VISIBLE; 1129 context.CaptionHeight = context.wi.cyWindowBorders; 1130 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION ); 1131 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow); 1132 1133 /* Paint the window on the preview hDC */ 1134 rcCurrent = context.wi.rcWindow; 1135 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top); 1136 SetViewportOrgEx(hDC, context.wi.rcWindow.left, context.wi.rcWindow.top, NULL); 1137 ThemeCalculateCaptionButtonsPos(hwndDummy, context.theme); 1138 ThemePaintWindow(&context, &rcCurrent, FALSE); 1139 SetViewportOrgEx(hDC, 0, 0, NULL); 1140 1141 context.hDC = NULL; 1142 CloseThemeData (context.theme); 1143 CloseThemeData (context.scrolltheme); 1144 ThemeCleanupDrawContext(&context); 1145 1146 /* Cleanup */ 1147 DestroyWindow(hwndDummy); 1148 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst); 1149 1150 return S_OK; 1151 } 1152