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 PWND_DATA pwndData = ThemeGetWndData(pcontext->hWnd); 281 if (!pwndData) 282 return; 283 284 switch(buttonId) 285 { 286 case CLOSEBUTTON: 287 iPartId = pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; 288 break; 289 290 case MAXBUTTON: 291 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX)) 292 { 293 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX)) 294 return; 295 else 296 iStateId = (pcontext->Active ? BUTTON_DISABLED : BUTTON_INACTIVE_DISABLED); 297 } 298 299 iPartId = pcontext->wi.dwStyle & WS_MAXIMIZE ? WP_RESTOREBUTTON : WP_MAXBUTTON; 300 break; 301 302 case MINBUTTON: 303 if (!(pcontext->wi.dwStyle & WS_MINIMIZEBOX)) 304 { 305 if (!(pcontext->wi.dwStyle & WS_MAXIMIZEBOX)) 306 return; 307 else 308 iStateId = (pcontext->Active ? BUTTON_DISABLED : BUTTON_INACTIVE_DISABLED); 309 } 310 311 iPartId = pcontext->wi.dwStyle & WS_MINIMIZE ? WP_RESTOREBUTTON : WP_MINBUTTON; 312 break; 313 314 default: 315 //FIXME: Implement Help Button 316 return; 317 } 318 319 if (prcCurrent) 320 prcCurrent->right = pwndData->rcCaptionButtons[buttonId].left; 321 322 DrawThemeBackground(pcontext->theme, pcontext->hDC, iPartId, iStateId, &pwndData->rcCaptionButtons[buttonId], NULL); 323 } 324 325 static DWORD 326 ThemeGetButtonState(DWORD htCurrect, DWORD htHot, DWORD htDown, BOOL Active) 327 { 328 if (htHot == htCurrect) 329 return (Active ? BUTTON_HOT : BUTTON_INACTIVE_HOT); 330 if (htDown == htCurrect) 331 return (Active ? BUTTON_PRESSED : BUTTON_INACTIVE_PRESSED); 332 333 return (Active ? BUTTON_NORMAL : BUTTON_INACTIVE); 334 } 335 336 /* Used only from mouse event handlers */ 337 static void 338 ThemeDrawCaptionButtons(PDRAW_CONTEXT pcontext, DWORD htHot, DWORD htDown) 339 { 340 /* Draw the buttons */ 341 ThemeDrawCaptionButton(pcontext, NULL, CLOSEBUTTON, 342 ThemeGetButtonState(HTCLOSE, htHot, htDown, pcontext->Active)); 343 ThemeDrawCaptionButton(pcontext, NULL, MAXBUTTON, 344 ThemeGetButtonState(HTMAXBUTTON, htHot, htDown, pcontext->Active)); 345 ThemeDrawCaptionButton(pcontext, NULL, MINBUTTON, 346 ThemeGetButtonState(HTMINBUTTON, htHot, htDown, pcontext->Active)); 347 ThemeDrawCaptionButton(pcontext, NULL, HELPBUTTON, 348 ThemeGetButtonState(HTHELP, htHot, htDown, pcontext->Active)); 349 } 350 351 /* Used from WM_NCPAINT and WM_NCACTIVATE handlers */ 352 static void 353 ThemeDrawCaption(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 354 { 355 RECT rcPart; 356 int iPart, iState; 357 HICON hIcon; 358 359 // See also win32ss/user/ntuser/nonclient.c!UserDrawCaptionBar 360 // and win32ss/user/ntuser/nonclient.c!UserDrawCaption 361 if ((pcontext->wi.dwStyle & WS_SYSMENU) && !(pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW)) 362 hIcon = UserGetWindowIcon(pcontext); 363 else 364 hIcon = NULL; 365 366 /* Get the caption part and state id */ 367 if (pcontext->wi.dwStyle & WS_MINIMIZE) 368 iPart = WP_MINCAPTION; 369 else if (pcontext->wi.dwExStyle & WS_EX_TOOLWINDOW) 370 iPart = WP_SMALLCAPTION; 371 else if (pcontext->wi.dwStyle & WS_MAXIMIZE) 372 iPart = WP_MAXCAPTION; 373 else 374 iPart = WP_CAPTION; 375 376 iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE; 377 378 /* Draw the caption background */ 379 rcPart = *prcCurrent; 380 rcPart.bottom = rcPart.top + pcontext->CaptionHeight; 381 prcCurrent->top = rcPart.bottom; 382 DrawThemeBackground(pcontext->theme, pcontext->hDC,iPart,iState,&rcPart,NULL); 383 384 /* Add a padding around the objects of the caption */ 385 InflateRect(&rcPart, -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE, 386 -(int)pcontext->wi.cyWindowBorders-BUTTON_GAP_SIZE); 387 388 /* Draw the caption buttons */ 389 if (pcontext->wi.dwStyle & WS_SYSMENU) 390 { 391 iState = pcontext->Active ? BUTTON_NORMAL : BUTTON_INACTIVE; 392 393 ThemeDrawCaptionButton(pcontext, &rcPart, CLOSEBUTTON, iState); 394 ThemeDrawCaptionButton(pcontext, &rcPart, MAXBUTTON, iState); 395 ThemeDrawCaptionButton(pcontext, &rcPart, MINBUTTON, iState); 396 ThemeDrawCaptionButton(pcontext, &rcPart, HELPBUTTON, iState); 397 } 398 399 rcPart.top += 3 ; 400 401 /* Draw the icon */ 402 if (hIcon) 403 { 404 int IconHeight = GetSystemMetrics(SM_CYSMICON); 405 int IconWidth = GetSystemMetrics(SM_CXSMICON); 406 DrawIconEx(pcontext->hDC, rcPart.left, rcPart.top , hIcon, IconWidth, IconHeight, 0, NULL, DI_NORMAL); 407 rcPart.left += IconWidth + 4; 408 } 409 410 rcPart.right -= 4; 411 412 /* Draw the caption */ 413 ThemeDrawCaptionText(pcontext, &rcPart, iPart, iState); 414 } 415 416 static void 417 ThemeDrawBorders(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 418 { 419 RECT rcPart; 420 int iState = pcontext->Active ? FS_ACTIVE : FS_INACTIVE; 421 422 /* Draw the bottom border */ 423 rcPart = *prcCurrent; 424 rcPart.top = rcPart.bottom - pcontext->wi.cyWindowBorders; 425 prcCurrent->bottom = rcPart.top; 426 DrawThemeBackground(pcontext->theme, pcontext->hDC, WP_FRAMEBOTTOM, iState, &rcPart, NULL); 427 428 /* Draw the left border */ 429 rcPart = *prcCurrent; 430 rcPart.right = rcPart.left + pcontext->wi.cxWindowBorders ; 431 prcCurrent->left = rcPart.right; 432 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMELEFT, iState, &rcPart, NULL); 433 434 /* Draw the right border */ 435 rcPart = *prcCurrent; 436 rcPart.left = rcPart.right - pcontext->wi.cxWindowBorders; 437 prcCurrent->right = rcPart.left; 438 DrawThemeBackground(pcontext->theme, pcontext->hDC,WP_FRAMERIGHT, iState, &rcPart, NULL); 439 } 440 441 static void 442 DrawClassicFrame(PDRAW_CONTEXT context, RECT* prcCurrent) 443 { 444 /* Draw outer edge */ 445 if (UserHasWindowEdge(context->wi.dwStyle, context->wi.dwExStyle)) 446 { 447 DrawEdge(context->hDC, prcCurrent, EDGE_RAISED, BF_RECT | BF_ADJUST); 448 } 449 else if (context->wi.dwExStyle & WS_EX_STATICEDGE) 450 { 451 DrawEdge(context->hDC, prcCurrent, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT); 452 } 453 454 /* Firstly the "thick" frame */ 455 if ((context->wi.dwStyle & WS_THICKFRAME) && !(context->wi.dwStyle & WS_MINIMIZE)) 456 { 457 INT Width = 458 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) * 459 GetSystemMetrics(SM_CXBORDER); 460 INT Height = 461 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) * 462 GetSystemMetrics(SM_CYBORDER); 463 464 SelectObject(context->hDC, GetSysColorBrush( 465 context->Active ? COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER)); 466 467 /* Draw frame */ 468 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 469 prcCurrent->right - prcCurrent->left, Height, PATCOPY); 470 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 471 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 472 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1, 473 prcCurrent->right - prcCurrent->left, -Height, PATCOPY); 474 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top, 475 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 476 477 InflateRect(prcCurrent, -Width, -Height); 478 } 479 480 /* Now the other bit of the frame */ 481 if (context->wi.dwStyle & (WS_DLGFRAME | WS_BORDER) || (context->wi.dwExStyle & WS_EX_DLGMODALFRAME)) 482 { 483 INT Width = GetSystemMetrics(SM_CXBORDER); 484 INT Height = GetSystemMetrics(SM_CYBORDER); 485 486 SelectObject(context->hDC, GetSysColorBrush( 487 (context->wi.dwExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE : 488 (context->wi.dwExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME : 489 (context->wi.dwStyle & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE : 490 COLOR_WINDOWFRAME)); 491 492 /* Draw frame */ 493 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 494 prcCurrent->right - prcCurrent->left, Height, PATCOPY); 495 PatBlt(context->hDC, prcCurrent->left, prcCurrent->top, 496 Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 497 PatBlt(context->hDC, prcCurrent->left, prcCurrent->bottom - 1, 498 prcCurrent->right - prcCurrent->left, -Height, PATCOPY); 499 PatBlt(context->hDC, prcCurrent->right - 1, prcCurrent->top, 500 -Width, prcCurrent->bottom - prcCurrent->top, PATCOPY); 501 502 InflateRect(prcCurrent, -Width, -Height); 503 } 504 } 505 506 static void ThemeDrawMenuBar(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 507 { 508 /* Let the window manager paint the menu */ 509 prcCurrent->top += PaintMenuBar(pcontext->hWnd, 510 pcontext->hDC, 511 pcontext->wi.cxWindowBorders, 512 pcontext->wi.cxWindowBorders, 513 prcCurrent->top, 514 pcontext->Active); 515 } 516 517 static void ThemeDrawScrollBarsGrip(PDRAW_CONTEXT pcontext, RECT* prcCurrent) 518 { 519 RECT rcPart; 520 HWND hwndParent; 521 RECT ParentClientRect; 522 DWORD ParentStyle; 523 524 rcPart = *prcCurrent; 525 526 if (pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR) 527 rcPart.right = rcPart.left + GetSystemMetrics(SM_CXVSCROLL); 528 else 529 rcPart.left = rcPart.right - GetSystemMetrics(SM_CXVSCROLL); 530 531 rcPart.top = rcPart.bottom - GetSystemMetrics(SM_CYHSCROLL); 532 533 FillRect(pcontext->hDC, &rcPart, GetSysColorBrush(COLOR_BTNFACE)); 534 535 hwndParent = GetParent(pcontext->hWnd); 536 GetClientRect(hwndParent, &ParentClientRect); 537 ParentStyle = GetWindowLongW(hwndParent, GWL_STYLE); 538 539 if (HASSIZEGRIP(pcontext->wi.dwStyle, pcontext->wi.dwExStyle, ParentStyle, pcontext->wi.rcWindow, ParentClientRect)) 540 { 541 int iState; 542 if (pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR) 543 iState = pcontext->wi.dwExStyle & WS_EX_LEFTSCROLLBAR; 544 else 545 iState = SZB_RIGHTALIGN; 546 DrawThemeBackground(pcontext->scrolltheme, pcontext->hDC, SBP_SIZEBOX, iState, &rcPart, NULL); 547 } 548 } 549 550 static void 551 ThemePaintWindow(PDRAW_CONTEXT pcontext, RECT* prcCurrent, BOOL bDoDoubleBuffering) 552 { 553 if(!(pcontext->wi.dwStyle & WS_VISIBLE)) 554 return; 555 556 if((pcontext->wi.dwStyle & WS_CAPTION)==WS_CAPTION) 557 { 558 if (bDoDoubleBuffering) 559 ThemeStartBufferedPaint(pcontext, prcCurrent->right, pcontext->CaptionHeight); 560 ThemeDrawCaption(pcontext, prcCurrent); 561 if (bDoDoubleBuffering) 562 ThemeEndBufferedPaint(pcontext, 0, 0, prcCurrent->right, pcontext->CaptionHeight); 563 ThemeDrawBorders(pcontext, prcCurrent); 564 } 565 else 566 { 567 DrawClassicFrame(pcontext, prcCurrent); 568 } 569 570 if(pcontext->wi.dwStyle & WS_MINIMIZE) 571 return; 572 573 if(HAS_MENU(pcontext->hWnd, pcontext->wi.dwStyle)) 574 ThemeDrawMenuBar(pcontext, prcCurrent); 575 576 if (pcontext->wi.dwExStyle & WS_EX_CLIENTEDGE) 577 DrawEdge(pcontext->hDC, prcCurrent, EDGE_SUNKEN, BF_RECT | BF_ADJUST); 578 579 if((pcontext->wi.dwStyle & WS_HSCROLL) && IsScrollBarVisible(pcontext->hWnd, OBJID_HSCROLL)) 580 ThemeDrawScrollBar(pcontext, SB_HORZ , NULL); 581 582 if((pcontext->wi.dwStyle & WS_VSCROLL) && IsScrollBarVisible(pcontext->hWnd, OBJID_VSCROLL)) 583 ThemeDrawScrollBar(pcontext, SB_VERT, NULL); 584 585 if((pcontext->wi.dwStyle & (WS_HSCROLL|WS_VSCROLL)) == (WS_HSCROLL|WS_VSCROLL) && 586 IsScrollBarVisible(pcontext->hWnd, OBJID_HSCROLL) && 587 IsScrollBarVisible(pcontext->hWnd, OBJID_VSCROLL)) 588 { 589 ThemeDrawScrollBarsGrip(pcontext, prcCurrent); 590 } 591 } 592 593 /* 594 * Message handlers 595 */ 596 597 static LRESULT 598 ThemeHandleNCPaint(HWND hWnd, HRGN hRgn) 599 { 600 DRAW_CONTEXT context; 601 RECT rcCurrent; 602 603 ThemeInitDrawContext(&context, hWnd, hRgn); 604 605 rcCurrent = context.wi.rcWindow; 606 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top); 607 608 ThemePaintWindow(&context, &rcCurrent, TRUE); 609 ThemeCleanupDrawContext(&context); 610 611 return 0; 612 } 613 614 static LRESULT 615 ThemeHandleNcMouseMove(HWND hWnd, DWORD ht, POINT* pt) 616 { 617 DRAW_CONTEXT context; 618 TRACKMOUSEEVENT tme; 619 DWORD style; 620 PWND_DATA pwndData; 621 622 /* First of all check if we have something to do here */ 623 style = GetWindowLongW(hWnd, GWL_STYLE); 624 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0) 625 return 0; 626 627 /* Get theme data for this window */ 628 pwndData = ThemeGetWndData(hWnd); 629 if (pwndData == NULL) 630 return 0; 631 632 /* Begin tracking in the non client area if we are not tracking yet */ 633 tme.cbSize = sizeof(TRACKMOUSEEVENT); 634 tme.dwFlags = TME_QUERY; 635 tme.hwndTrack = hWnd; 636 TrackMouseEvent(&tme); 637 if (tme.dwFlags != (TME_LEAVE | TME_NONCLIENT)) 638 { 639 tme.hwndTrack = hWnd; 640 tme.dwFlags = TME_LEAVE | TME_NONCLIENT; 641 TrackMouseEvent(&tme); 642 } 643 644 ThemeInitDrawContext(&context, hWnd, 0); 645 if (context.wi.dwStyle & WS_SYSMENU) 646 { 647 if (HT_ISBUTTON(ht) || HT_ISBUTTON(pwndData->lastHitTest)) 648 ThemeDrawCaptionButtons(&context, ht, 0); 649 } 650 651 if (context.wi.dwStyle & WS_HSCROLL) 652 { 653 if (ht == HTHSCROLL || pwndData->lastHitTest == HTHSCROLL) 654 ThemeDrawScrollBar(&context, SB_HORZ , ht == HTHSCROLL ? pt : NULL); 655 } 656 657 if (context.wi.dwStyle & WS_VSCROLL) 658 { 659 if (ht == HTVSCROLL || pwndData->lastHitTest == HTVSCROLL) 660 ThemeDrawScrollBar(&context, SB_VERT, ht == HTVSCROLL ? pt : NULL); 661 } 662 ThemeCleanupDrawContext(&context); 663 664 pwndData->lastHitTest = ht; 665 666 return 0; 667 } 668 669 static LRESULT 670 ThemeHandleNcMouseLeave(HWND hWnd) 671 { 672 DRAW_CONTEXT context; 673 DWORD style; 674 PWND_DATA pwndData; 675 676 /* First of all check if we have something to do here */ 677 style = GetWindowLongW(hWnd, GWL_STYLE); 678 if((style & (WS_CAPTION|WS_HSCROLL|WS_VSCROLL))==0) 679 return 0; 680 681 /* Get theme data for this window */ 682 pwndData = ThemeGetWndData(hWnd); 683 if (pwndData == NULL) 684 return 0; 685 686 ThemeInitDrawContext(&context, hWnd, 0); 687 if (context.wi.dwStyle & WS_SYSMENU && HT_ISBUTTON(pwndData->lastHitTest)) 688 ThemeDrawCaptionButtons(&context, 0, 0); 689 690 if (context.wi.dwStyle & WS_HSCROLL && pwndData->lastHitTest == HTHSCROLL) 691 ThemeDrawScrollBar(&context, SB_HORZ, NULL); 692 693 if (context.wi.dwStyle & WS_VSCROLL && pwndData->lastHitTest == HTVSCROLL) 694 ThemeDrawScrollBar(&context, SB_VERT, NULL); 695 696 ThemeCleanupDrawContext(&context); 697 698 pwndData->lastHitTest = HTNOWHERE; 699 700 return 0; 701 } 702 703 static VOID 704 ThemeHandleButton(HWND hWnd, WPARAM wParam) 705 { 706 MSG Msg; 707 BOOL Pressed = TRUE; 708 WPARAM SCMsg, ht; 709 ULONG Style; 710 DRAW_CONTEXT context; 711 PWND_DATA pwndData; 712 713 Style = GetWindowLongW(hWnd, GWL_STYLE); 714 if (!((Style & WS_CAPTION) && (Style & WS_SYSMENU))) 715 return ; 716 717 switch (wParam) 718 { 719 case HTCLOSE: 720 SCMsg = SC_CLOSE; 721 break; 722 case HTMINBUTTON: 723 if (!(Style & WS_MINIMIZEBOX)) 724 return; 725 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE); 726 break; 727 case HTMAXBUTTON: 728 if (!(Style & WS_MAXIMIZEBOX)) 729 return; 730 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE); 731 break; 732 default : 733 return; 734 } 735 736 /* Get theme data for this window */ 737 pwndData = ThemeGetWndData(hWnd); 738 if (pwndData == NULL) 739 return; 740 741 ThemeInitDrawContext(&context, hWnd, 0); 742 ThemeDrawCaptionButtons(&context, 0, wParam); 743 pwndData->lastHitTest = wParam; 744 745 SetCapture(hWnd); 746 747 ht = wParam; 748 749 for (;;) 750 { 751 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0) 752 break; 753 754 if (Msg.message == WM_LBUTTONUP) 755 break; 756 757 if (Msg.message != WM_MOUSEMOVE) 758 continue; 759 760 ht = SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(Msg.pt.x, Msg.pt.y)); 761 Pressed = (ht == wParam); 762 763 /* Only draw the buttons if the hit test changed */ 764 if (ht != pwndData->lastHitTest && 765 (HT_ISBUTTON(ht) || HT_ISBUTTON(pwndData->lastHitTest))) 766 { 767 ThemeDrawCaptionButtons(&context, 0, Pressed ? wParam: 0); 768 pwndData->lastHitTest = ht; 769 } 770 } 771 772 ThemeDrawCaptionButtons(&context, ht, 0); 773 ThemeCleanupDrawContext(&context); 774 775 ReleaseCapture(); 776 777 if (Pressed) 778 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0); 779 } 780 781 782 static LRESULT 783 DefWndNCHitTest(HWND hWnd, POINT Point) 784 { 785 RECT WindowRect; 786 POINT ClientPoint; 787 WINDOWINFO wi; 788 789 wi.cbSize = sizeof(wi); 790 GetWindowInfo(hWnd, &wi); 791 792 if (!PtInRect(&wi.rcWindow, Point)) 793 { 794 return HTNOWHERE; 795 } 796 WindowRect = wi.rcWindow; 797 798 if (UserHasWindowEdge(wi.dwStyle, wi.dwExStyle)) 799 { 800 LONG XSize, YSize; 801 802 InflateRect(&WindowRect, -(int)wi.cxWindowBorders, -(int)wi.cyWindowBorders); 803 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER); 804 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER); 805 if (!PtInRect(&WindowRect, Point)) 806 { 807 BOOL ThickFrame; 808 809 ThickFrame = (wi.dwStyle & WS_THICKFRAME); 810 if (Point.y < WindowRect.top) 811 { 812 if(wi.dwStyle & WS_MINIMIZE) 813 return HTCAPTION; 814 if(!ThickFrame) 815 return HTBORDER; 816 if (Point.x < (WindowRect.left + XSize)) 817 return HTTOPLEFT; 818 if (Point.x >= (WindowRect.right - XSize)) 819 return HTTOPRIGHT; 820 return HTTOP; 821 } 822 if (Point.y >= WindowRect.bottom) 823 { 824 if(wi.dwStyle & WS_MINIMIZE) 825 return HTCAPTION; 826 if(!ThickFrame) 827 return HTBORDER; 828 if (Point.x < (WindowRect.left + XSize)) 829 return HTBOTTOMLEFT; 830 if (Point.x >= (WindowRect.right - XSize)) 831 return HTBOTTOMRIGHT; 832 return HTBOTTOM; 833 } 834 if (Point.x < WindowRect.left) 835 { 836 if(wi.dwStyle & WS_MINIMIZE) 837 return HTCAPTION; 838 if(!ThickFrame) 839 return HTBORDER; 840 if (Point.y < (WindowRect.top + YSize)) 841 return HTTOPLEFT; 842 if (Point.y >= (WindowRect.bottom - YSize)) 843 return HTBOTTOMLEFT; 844 return HTLEFT; 845 } 846 if (Point.x >= WindowRect.right) 847 { 848 if(wi.dwStyle & WS_MINIMIZE) 849 return HTCAPTION; 850 if(!ThickFrame) 851 return HTBORDER; 852 if (Point.y < (WindowRect.top + YSize)) 853 return HTTOPRIGHT; 854 if (Point.y >= (WindowRect.bottom - YSize)) 855 return HTBOTTOMRIGHT; 856 return HTRIGHT; 857 } 858 } 859 } 860 else 861 { 862 if (wi.dwExStyle & WS_EX_STATICEDGE) 863 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER), 864 -GetSystemMetrics(SM_CYBORDER)); 865 if (!PtInRect(&WindowRect, Point)) 866 return HTBORDER; 867 } 868 869 if ((wi.dwStyle & WS_CAPTION) == WS_CAPTION) 870 { 871 if (wi.dwExStyle & WS_EX_TOOLWINDOW) 872 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION); 873 else 874 WindowRect.top += GetSystemMetrics(SM_CYCAPTION); 875 876 if (!PtInRect(&WindowRect, Point)) 877 { 878 if (wi.dwStyle & WS_SYSMENU) 879 { 880 PWND_DATA pwndData = ThemeGetWndData(hWnd); 881 882 if (!(wi.dwExStyle & WS_EX_TOOLWINDOW)) 883 { 884 // if(!(wi.dwExStyle & WS_EX_DLGMODALFRAME)) 885 // FIXME: The real test should check whether there is 886 // an icon for the system window, and if so, do the 887 // rect.left increase. 888 // See win32ss/user/user32/windows/nonclient.c!DefWndNCHitTest 889 // and win32ss/user/ntuser/nonclient.c!GetNCHitEx which does 890 // the test better. 891 WindowRect.left += GetSystemMetrics(SM_CXSMICON); 892 } 893 894 if (pwndData) 895 { 896 POINT pt = {Point.x - wi.rcWindow.left, Point.y - wi.rcWindow.top}; 897 if (PtInRect(&pwndData->rcCaptionButtons[CLOSEBUTTON], pt)) 898 return HTCLOSE; 899 if (PtInRect(&pwndData->rcCaptionButtons[MAXBUTTON], pt)) 900 return HTMAXBUTTON; 901 if (PtInRect(&pwndData->rcCaptionButtons[MINBUTTON], pt)) 902 return HTMINBUTTON; 903 } 904 } 905 if (Point.x < WindowRect.left) 906 return HTSYSMENU; 907 return HTCAPTION; 908 } 909 } 910 911 if(!(wi.dwStyle & WS_MINIMIZE)) 912 { 913 HMENU menu; 914 915 ClientPoint = Point; 916 ScreenToClient(hWnd, &ClientPoint); 917 GetClientRect(hWnd, &wi.rcClient); 918 919 if (PtInRect(&wi.rcClient, ClientPoint)) 920 { 921 return HTCLIENT; 922 } 923 924 if ((menu = GetMenu(hWnd)) && !(wi.dwStyle & WS_CHILD)) 925 { 926 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0) 927 return HTMENU; 928 } 929 930 if (wi.dwExStyle & WS_EX_CLIENTEDGE) 931 { 932 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER), 933 -2 * GetSystemMetrics(SM_CYBORDER)); 934 } 935 936 if ((wi.dwStyle & WS_VSCROLL) && (wi.dwStyle & WS_HSCROLL) && 937 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL)) 938 { 939 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect; 940 HWND Parent = GetParent(hWnd); 941 942 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL); 943 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 944 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL); 945 else 946 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL); 947 if (PtInRect(&TempRect, Point)) 948 return HTVSCROLL; 949 950 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL); 951 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 952 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL); 953 else 954 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL); 955 if (PtInRect(&TempRect2, Point)) 956 return HTHSCROLL; 957 958 TempRect.top = TempRect2.top; 959 TempRect.bottom = TempRect2.bottom; 960 if(Parent) 961 GetClientRect(Parent, &ParentRect); 962 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(wi.dwStyle, wi.dwExStyle, 963 GetWindowLongW(Parent, GWL_STYLE), wi.rcWindow, ParentRect)) 964 { 965 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 966 return HTBOTTOMLEFT; 967 else 968 return HTBOTTOMRIGHT; 969 } 970 } 971 else 972 { 973 if (wi.dwStyle & WS_VSCROLL) 974 { 975 RECT TempRect = WindowRect; 976 977 if ((wi.dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) 978 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL); 979 else 980 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL); 981 if (PtInRect(&TempRect, Point)) 982 return HTVSCROLL; 983 } 984 else if (wi.dwStyle & WS_HSCROLL) 985 { 986 RECT TempRect = WindowRect; 987 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL); 988 if (PtInRect(&TempRect, Point)) 989 return HTHSCROLL; 990 } 991 } 992 } 993 994 return HTNOWHERE; 995 } 996 997 LRESULT CALLBACK 998 ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc) 999 { 1000 switch(Msg) 1001 { 1002 case WM_NCPAINT: 1003 return ThemeHandleNCPaint(hWnd, (HRGN)wParam); 1004 // 1005 // WM_NCUAHDRAWCAPTION : wParam are DC_* flags. 1006 // 1007 case WM_NCUAHDRAWCAPTION: 1008 // 1009 // WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND. 1010 // 1011 case WM_NCUAHDRAWFRAME: 1012 case WM_NCACTIVATE: 1013 1014 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) != WS_CAPTION) 1015 return TRUE; 1016 1017 ThemeHandleNCPaint(hWnd, (HRGN)1); 1018 return TRUE; 1019 case WM_NCMOUSEMOVE: 1020 { 1021 POINT Point; 1022 Point.x = GET_X_LPARAM(lParam); 1023 Point.y = GET_Y_LPARAM(lParam); 1024 return ThemeHandleNcMouseMove(hWnd, wParam, &Point); 1025 } 1026 case WM_NCMOUSELEAVE: 1027 return ThemeHandleNcMouseLeave(hWnd); 1028 case WM_NCLBUTTONDOWN: 1029 switch (wParam) 1030 { 1031 case HTMINBUTTON: 1032 case HTMAXBUTTON: 1033 case HTCLOSE: 1034 { 1035 ThemeHandleButton(hWnd, wParam); 1036 return 0; 1037 } 1038 default: 1039 return DefWndProc(hWnd, Msg, wParam, lParam); 1040 } 1041 case WM_NCHITTEST: 1042 { 1043 POINT Point; 1044 Point.x = GET_X_LPARAM(lParam); 1045 Point.y = GET_Y_LPARAM(lParam); 1046 return DefWndNCHitTest(hWnd, Point); 1047 } 1048 case WM_SYSCOMMAND: 1049 { 1050 if((wParam & 0xfff0) == SC_VSCROLL || 1051 (wParam & 0xfff0) == SC_HSCROLL) 1052 { 1053 POINT Pt; 1054 Pt.x = (short)LOWORD(lParam); 1055 Pt.y = (short)HIWORD(lParam); 1056 NC_TrackScrollBar(hWnd, wParam, Pt); 1057 return 0; 1058 } 1059 else 1060 { 1061 return DefWndProc(hWnd, Msg, wParam, lParam); 1062 } 1063 } 1064 default: 1065 return DefWndProc(hWnd, Msg, wParam, lParam); 1066 } 1067 } 1068 1069 HRESULT WINAPI DrawNCPreview(HDC hDC, 1070 DWORD DNCP_Flag, 1071 LPRECT prcPreview, 1072 LPCWSTR pszThemeFileName, 1073 LPCWSTR pszColorName, 1074 LPCWSTR pszSizeName, 1075 PNONCLIENTMETRICSW pncMetrics, 1076 COLORREF* lpaRgbValues) 1077 { 1078 WNDCLASSEXW DummyPreviewWindowClass; 1079 HWND hwndDummy; 1080 HRESULT hres; 1081 HTHEMEFILE hThemeFile; 1082 DRAW_CONTEXT context; 1083 RECT rcCurrent; 1084 1085 /* FIXME: We also need to implement drawing the rest of the preview windows 1086 * and make use of the ncmetrics and colors passed as parameters */ 1087 1088 /* Create a dummy window that will be used to trick the paint funtions */ 1089 memset(&DummyPreviewWindowClass, 0, sizeof(DummyPreviewWindowClass)); 1090 DummyPreviewWindowClass.cbSize = sizeof(DummyPreviewWindowClass); 1091 DummyPreviewWindowClass.lpszClassName = L"DummyPreviewWindowClass"; 1092 DummyPreviewWindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 1093 DummyPreviewWindowClass.hInstance = hDllInst; 1094 DummyPreviewWindowClass.lpfnWndProc = DefWindowProcW; 1095 if (!RegisterClassExW(&DummyPreviewWindowClass)) 1096 return E_FAIL; 1097 1098 hwndDummy = CreateWindowExW(0, L"DummyPreviewWindowClass", L"Active window", WS_OVERLAPPEDWINDOW,30,30,300,150,0,0,hDllInst,NULL); 1099 if (!hwndDummy) 1100 return E_FAIL; 1101 1102 hres = OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, &hThemeFile,0); 1103 if (FAILED(hres)) 1104 return hres; 1105 1106 /* Initialize the special draw context for the preview */ 1107 context.hDC = hDC; 1108 context.hWnd = hwndDummy; 1109 context.theme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"WINDOW", 0); 1110 if (!context.theme) 1111 return E_FAIL; 1112 context.scrolltheme = OpenThemeDataFromFile(hThemeFile, hwndDummy, L"SCROLLBAR", 0); 1113 if (!context.scrolltheme) 1114 return E_FAIL; 1115 context.Active = TRUE; 1116 context.wi.cbSize = sizeof(context.wi); 1117 if (!GetWindowInfo(hwndDummy, &context.wi)) 1118 return E_FAIL; 1119 context.wi.dwStyle |= WS_VISIBLE; 1120 context.CaptionHeight = context.wi.cyWindowBorders; 1121 context.CaptionHeight += GetSystemMetrics(context.wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION ); 1122 context.hRgn = CreateRectRgnIndirect(&context.wi.rcWindow); 1123 1124 /* Paint the window on the preview hDC */ 1125 rcCurrent = context.wi.rcWindow; 1126 OffsetRect( &rcCurrent, -context.wi.rcWindow.left, -context.wi.rcWindow.top); 1127 SetViewportOrgEx(hDC, context.wi.rcWindow.left, context.wi.rcWindow.top, NULL); 1128 ThemeCalculateCaptionButtonsPos(hwndDummy, context.theme); 1129 ThemePaintWindow(&context, &rcCurrent, FALSE); 1130 SetViewportOrgEx(hDC, 0, 0, NULL); 1131 1132 context.hDC = NULL; 1133 CloseThemeData (context.theme); 1134 CloseThemeData (context.scrolltheme); 1135 ThemeCleanupDrawContext(&context); 1136 1137 /* Cleanup */ 1138 DestroyWindow(hwndDummy); 1139 UnregisterClassW(L"DummyPreviewWindowClass", hDllInst); 1140 1141 return S_OK; 1142 } 1143