1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #define _SV_SALNATIVEWIDGETS_CXX 32 33 #include "rtl/ustring.h" 34 35 #include "osl/module.h" 36 37 #include "vcl/svapp.hxx" 38 39 #include "win/svsys.h" 40 #include "win/salgdi.h" 41 #include "win/saldata.hxx" 42 43 #include "uxtheme.h" 44 #include "vssym32.h" 45 46 #include <map> 47 #include <string> 48 49 using namespace rtl; 50 using namespace std; 51 52 typedef map< wstring, HTHEME > ThemeMap; 53 static ThemeMap aThemeMap; 54 55 56 /**************************************************** 57 wrap visual styles API to avoid linking against it 58 it is not available on all Windows platforms 59 *****************************************************/ 60 61 class VisualStylesAPI 62 { 63 private: 64 typedef HTHEME (WINAPI * OpenThemeData_Proc_T) ( HWND hwnd, LPCWSTR pszClassList ); 65 typedef HRESULT (WINAPI * CloseThemeData_Proc_T) ( HTHEME hTheme ); 66 typedef HRESULT (WINAPI * GetThemeBackgroundContentRect_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ); 67 typedef HRESULT (WINAPI * DrawThemeBackground_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ); 68 typedef HRESULT (WINAPI * DrawThemeText_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect ); 69 typedef HRESULT (WINAPI * GetThemePartSize_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ); 70 71 OpenThemeData_Proc_T lpfnOpenThemeData; 72 CloseThemeData_Proc_T lpfnCloseThemeData; 73 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect; 74 DrawThemeBackground_Proc_T lpfnDrawThemeBackground; 75 DrawThemeText_Proc_T lpfnDrawThemeText; 76 GetThemePartSize_Proc_T lpfnGetThemePartSize; 77 78 oslModule mhModule; 79 80 public: 81 VisualStylesAPI(); 82 ~VisualStylesAPI(); 83 sal_Bool IsAvailable() { return (mhModule != NULL); } 84 85 HTHEME OpenThemeData( HWND hwnd, LPCWSTR pszClassList ); 86 HRESULT CloseThemeData( HTHEME hTheme ); 87 HRESULT GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ); 88 HRESULT DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ); 89 HRESULT DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect ); 90 HRESULT GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ); 91 }; 92 93 static VisualStylesAPI vsAPI; 94 95 VisualStylesAPI::VisualStylesAPI() 96 { 97 OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "uxtheme.dll" ) ); 98 mhModule = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT ); 99 100 if ( mhModule ) 101 { 102 lpfnOpenThemeData = (OpenThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "OpenThemeData" ); 103 lpfnCloseThemeData = (CloseThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "CloseThemeData" ); 104 lpfnGetThemeBackgroundContentRect = (GetThemeBackgroundContentRect_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemeBackgroundContentRect" ); 105 lpfnDrawThemeBackground = (DrawThemeBackground_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeBackground" ); 106 lpfnDrawThemeText = (DrawThemeText_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeText" ); 107 lpfnGetThemePartSize = (GetThemePartSize_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemePartSize" ); 108 } 109 else 110 { 111 lpfnOpenThemeData = NULL; 112 lpfnCloseThemeData = NULL; 113 lpfnGetThemeBackgroundContentRect = NULL; 114 lpfnDrawThemeBackground = NULL; 115 lpfnDrawThemeText = NULL; 116 lpfnGetThemePartSize = NULL; 117 } 118 } 119 VisualStylesAPI::~VisualStylesAPI() 120 { 121 if( mhModule ) 122 osl_unloadModule( mhModule ); 123 } 124 HTHEME VisualStylesAPI::OpenThemeData( HWND hwnd, LPCWSTR pszClassList ) 125 { 126 if(lpfnOpenThemeData) 127 return (*lpfnOpenThemeData) (hwnd, pszClassList); 128 else 129 return NULL; 130 } 131 132 HRESULT VisualStylesAPI::CloseThemeData( HTHEME hTheme ) 133 { 134 if(lpfnCloseThemeData) 135 return (*lpfnCloseThemeData) (hTheme); 136 else 137 return S_FALSE; 138 } 139 HRESULT VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ) 140 { 141 if(lpfnGetThemeBackgroundContentRect) 142 return (*lpfnGetThemeBackgroundContentRect) ( hTheme, hdc, iPartId, iStateId, pBoundingRect, pContentRect ); 143 else 144 return S_FALSE; 145 } 146 HRESULT VisualStylesAPI::DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ) 147 { 148 if(lpfnDrawThemeBackground) 149 return (*lpfnDrawThemeBackground) (hTheme, hdc, iPartId, iStateId, pRect, pClipRect); 150 else 151 return S_FALSE; 152 } 153 HRESULT VisualStylesAPI::DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect ) 154 { 155 if(lpfnDrawThemeText) 156 return (*lpfnDrawThemeText) (hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect); 157 else 158 return S_FALSE; 159 } 160 HRESULT VisualStylesAPI::GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ) 161 { 162 if(lpfnGetThemePartSize) 163 return (*lpfnGetThemePartSize) (hTheme, hdc, iPartId, iStateId, prc, eSize, psz); 164 else 165 return S_FALSE; 166 } 167 168 169 /********************************************************* 170 * Initialize XP theming and local stuff 171 *********************************************************/ 172 void SalData::initNWF( void ) 173 { 174 ImplSVData* pSVData = ImplGetSVData(); 175 176 // the menu bar and the top docking area should have a common background (gradient) 177 pSVData->maNWFData.mbMenuBarDockingAreaCommonBG = true; 178 } 179 180 181 // ********************************************************* 182 // * Release theming handles 183 // ******************************************************** 184 void SalData::deInitNWF( void ) 185 { 186 ThemeMap::iterator iter = aThemeMap.begin(); 187 while( iter != aThemeMap.end() ) 188 { 189 vsAPI.CloseThemeData(iter->second); 190 iter++; 191 } 192 aThemeMap.clear(); 193 if( maDwmLib ) 194 osl_unloadModule( maDwmLib ); 195 } 196 197 static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name ) 198 { 199 if( GetSalData()->mbThemeChanged ) 200 { 201 // throw away invalid theme handles 202 GetSalData()->deInitNWF(); 203 GetSalData()->mbThemeChanged = FALSE; 204 } 205 206 ThemeMap::iterator iter; 207 if( (iter = aThemeMap.find( name )) != aThemeMap.end() ) 208 return iter->second; 209 // theme not found -> add it to map 210 HTHEME hTheme = vsAPI.OpenThemeData( hWnd, name ); 211 if( hTheme != NULL ) 212 aThemeMap[name] = hTheme; 213 return hTheme; 214 } 215 216 /* 217 * IsNativeControlSupported() 218 * 219 * Returns TRUE if the platform supports native 220 * drawing of the control defined by nPart 221 */ 222 sal_Bool WinSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) 223 { 224 HTHEME hTheme = NULL; 225 226 switch( nType ) 227 { 228 case CTRL_PUSHBUTTON: 229 case CTRL_RADIOBUTTON: 230 case CTRL_CHECKBOX: 231 if( nPart == PART_ENTIRE_CONTROL ) 232 hTheme = getThemeHandle( mhWnd, L"Button"); 233 break; 234 case CTRL_SCROLLBAR: 235 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 236 return FALSE; // no background painting needed 237 if( nPart == PART_ENTIRE_CONTROL ) 238 hTheme = getThemeHandle( mhWnd, L"Scrollbar"); 239 break; 240 case CTRL_COMBOBOX: 241 if( nPart == HAS_BACKGROUND_TEXTURE ) 242 return FALSE; // we do not paint the inner part (ie the selection background/focus indication) 243 if( nPart == PART_ENTIRE_CONTROL ) 244 hTheme = getThemeHandle( mhWnd, L"Edit"); 245 else if( nPart == PART_BUTTON_DOWN ) 246 hTheme = getThemeHandle( mhWnd, L"Combobox"); 247 break; 248 case CTRL_SPINBOX: 249 if( nPart == PART_ENTIRE_CONTROL ) 250 hTheme = getThemeHandle( mhWnd, L"Edit"); 251 else if( nPart == PART_ALL_BUTTONS || 252 nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN || 253 nPart == PART_BUTTON_LEFT|| nPart == PART_BUTTON_RIGHT ) 254 hTheme = getThemeHandle( mhWnd, L"Spin"); 255 break; 256 case CTRL_SPINBUTTONS: 257 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_ALL_BUTTONS ) 258 hTheme = getThemeHandle( mhWnd, L"Spin"); 259 break; 260 case CTRL_EDITBOX: 261 case CTRL_MULTILINE_EDITBOX: 262 if( nPart == HAS_BACKGROUND_TEXTURE ) 263 return FALSE; // we do not paint the inner part (ie the selection background/focus indication) 264 //return TRUE; 265 if( nPart == PART_ENTIRE_CONTROL ) 266 hTheme = getThemeHandle( mhWnd, L"Edit"); 267 break; 268 case CTRL_LISTBOX: 269 if( nPart == HAS_BACKGROUND_TEXTURE ) 270 return FALSE; // we do not paint the inner part (ie the selection background/focus indication) 271 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) 272 hTheme = getThemeHandle( mhWnd, L"Listview"); 273 else if( nPart == PART_BUTTON_DOWN ) 274 hTheme = getThemeHandle( mhWnd, L"Combobox"); 275 break; 276 case CTRL_TAB_PANE: 277 case CTRL_TAB_BODY: 278 case CTRL_TAB_ITEM: 279 case CTRL_FIXEDBORDER: 280 if( nPart == PART_ENTIRE_CONTROL ) 281 hTheme = getThemeHandle( mhWnd, L"Tab"); 282 break; 283 case CTRL_TOOLBAR: 284 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON ) 285 hTheme = getThemeHandle( mhWnd, L"Toolbar"); 286 else 287 // use rebar theme for grip and background 288 hTheme = getThemeHandle( mhWnd, L"Rebar"); 289 break; 290 case CTRL_MENUBAR: 291 if( nPart == PART_ENTIRE_CONTROL ) 292 hTheme = getThemeHandle( mhWnd, L"Rebar"); 293 else if( GetSalData()->mbThemeMenuSupport ) 294 { 295 if( nPart == PART_MENU_ITEM ) 296 hTheme = getThemeHandle( mhWnd, L"Menu" ); 297 } 298 break; 299 case CTRL_MENU_POPUP: 300 if( GetSalData()->mbThemeMenuSupport ) 301 { 302 if( nPart == PART_ENTIRE_CONTROL || 303 nPart == PART_MENU_ITEM || 304 nPart == PART_MENU_ITEM_CHECK_MARK || 305 nPart == PART_MENU_ITEM_RADIO_MARK || 306 nPart == PART_MENU_SEPARATOR ) 307 hTheme = getThemeHandle( mhWnd, L"Menu" ); 308 } 309 break; 310 case CTRL_PROGRESS: 311 if( nPart == PART_ENTIRE_CONTROL ) 312 hTheme = getThemeHandle( mhWnd, L"Progress"); 313 break; 314 case CTRL_SLIDER: 315 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) 316 hTheme = getThemeHandle( mhWnd, L"Trackbar" ); 317 break; 318 case CTRL_LISTNODE: 319 if( nPart == PART_ENTIRE_CONTROL ) 320 hTheme = getThemeHandle( mhWnd, L"TreeView" ); 321 break; 322 default: 323 hTheme = NULL; 324 break; 325 } 326 327 return (hTheme != NULL); 328 } 329 330 331 /* 332 * HitTestNativeControl() 333 * 334 * If the return value is TRUE, bIsInside contains information whether 335 * aPos was or was not inside the native widget specified by the 336 * nType/nPart combination. 337 */ 338 sal_Bool WinSalGraphics::hitTestNativeControl( ControlType, 339 ControlPart, 340 const Rectangle&, 341 const Point&, 342 sal_Bool& ) 343 { 344 return FALSE; 345 } 346 347 sal_Bool ImplDrawTheme( HTHEME hTheme, HDC hDC, int iPart, int iState, RECT rc, const OUString& aStr) 348 { 349 HRESULT hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 350 351 if( aStr.getLength() ) 352 { 353 RECT rcContent; 354 hr = vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, iPart, iState, &rc, &rcContent); 355 hr = vsAPI.DrawThemeText( hTheme, hDC, iPart, iState, 356 reinterpret_cast<LPCWSTR>(aStr.getStr()), -1, 357 DT_CENTER | DT_VCENTER | DT_SINGLELINE, 358 0, &rcContent); 359 } 360 return (hr == S_OK); 361 } 362 363 364 Rectangle ImplGetThemeRect( HTHEME hTheme, HDC hDC, int iPart, int iState, const Rectangle& aRect, THEMESIZE eTS = TS_TRUE ) 365 { 366 SIZE aSz; 367 RECT rc; 368 rc.left = aRect.nLeft; 369 rc.right = aRect.nRight; 370 rc.top = aRect.nTop; 371 rc.bottom = aRect.nBottom; 372 HRESULT hr = vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, NULL, eTS, &aSz ); // TS_TRUE returns optimal size 373 if( hr == S_OK ) 374 return Rectangle( 0, 0, aSz.cx, aSz.cy ); 375 else 376 return Rectangle(); 377 } 378 379 // Helper functions 380 // ---- 381 382 void ImplConvertSpinbuttonValues( int nControlPart, const ControlState& rState, const Rectangle& rRect, 383 int* pLunaPart, int *pLunaState, RECT *pRect ) 384 { 385 if( nControlPart == PART_BUTTON_DOWN ) 386 { 387 *pLunaPart = SPNP_DOWN; 388 if( rState & CTRL_STATE_PRESSED ) 389 *pLunaState = DNS_PRESSED; 390 else if( !(rState & CTRL_STATE_ENABLED) ) 391 *pLunaState = DNS_DISABLED; 392 else if( rState & CTRL_STATE_ROLLOVER ) 393 *pLunaState = DNS_HOT; 394 else 395 *pLunaState = DNS_NORMAL; 396 } 397 if( nControlPart == PART_BUTTON_UP ) 398 { 399 *pLunaPart = SPNP_UP; 400 if( rState & CTRL_STATE_PRESSED ) 401 *pLunaState = UPS_PRESSED; 402 else if( !(rState & CTRL_STATE_ENABLED) ) 403 *pLunaState = UPS_DISABLED; 404 else if( rState & CTRL_STATE_ROLLOVER ) 405 *pLunaState = UPS_HOT; 406 else 407 *pLunaState = UPS_NORMAL; 408 } 409 if( nControlPart == PART_BUTTON_RIGHT ) 410 { 411 *pLunaPart = SPNP_UPHORZ; 412 if( rState & CTRL_STATE_PRESSED ) 413 *pLunaState = DNHZS_PRESSED; 414 else if( !(rState & CTRL_STATE_ENABLED) ) 415 *pLunaState = DNHZS_DISABLED; 416 else if( rState & CTRL_STATE_ROLLOVER ) 417 *pLunaState = DNHZS_HOT; 418 else 419 *pLunaState = DNHZS_NORMAL; 420 } 421 if( nControlPart == PART_BUTTON_LEFT ) 422 { 423 *pLunaPart = SPNP_DOWNHORZ; 424 if( rState & CTRL_STATE_PRESSED ) 425 *pLunaState = UPHZS_PRESSED; 426 else if( !(rState & CTRL_STATE_ENABLED) ) 427 *pLunaState = UPHZS_DISABLED; 428 else if( rState & CTRL_STATE_ROLLOVER ) 429 *pLunaState = UPHZS_HOT; 430 else 431 *pLunaState = UPHZS_NORMAL; 432 } 433 434 pRect->left = rRect.Left(); 435 pRect->right = rRect.Right()+1; 436 pRect->top = rRect.Top(); 437 pRect->bottom = rRect.Bottom()+1; 438 } 439 440 // ---- 441 442 sal_Bool ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc, 443 ControlType nType, 444 ControlPart nPart, 445 ControlState nState, 446 const ImplControlValue& aValue, 447 OUString aCaption ) 448 { 449 // a listbox dropdown is actually a combobox dropdown 450 if( nType == CTRL_LISTBOX ) 451 if( nPart == PART_BUTTON_DOWN ) 452 nType = CTRL_COMBOBOX; 453 454 // draw entire combobox as a large edit box 455 if( nType == CTRL_COMBOBOX ) 456 if( nPart == PART_ENTIRE_CONTROL ) 457 nType = CTRL_EDITBOX; 458 459 // draw entire spinbox as a large edit box 460 if( nType == CTRL_SPINBOX ) 461 if( nPart == PART_ENTIRE_CONTROL ) 462 nType = CTRL_EDITBOX; 463 464 int iPart(0), iState(0); 465 if( nType == CTRL_SCROLLBAR ) 466 { 467 HRESULT hr; 468 if( nPart == PART_BUTTON_UP ) 469 { 470 iPart = SBP_ARROWBTN; 471 if( nState & CTRL_STATE_PRESSED ) 472 iState = ABS_UPPRESSED; 473 else if( !(nState & CTRL_STATE_ENABLED) ) 474 iState = ABS_UPDISABLED; 475 else if( nState & CTRL_STATE_ROLLOVER ) 476 iState = ABS_UPHOT; 477 else 478 iState = ABS_UPNORMAL; 479 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 480 return (hr == S_OK); 481 } 482 if( nPart == PART_BUTTON_DOWN ) 483 { 484 iPart = SBP_ARROWBTN; 485 if( nState & CTRL_STATE_PRESSED ) 486 iState = ABS_DOWNPRESSED; 487 else if( !(nState & CTRL_STATE_ENABLED) ) 488 iState = ABS_DOWNDISABLED; 489 else if( nState & CTRL_STATE_ROLLOVER ) 490 iState = ABS_DOWNHOT; 491 else 492 iState = ABS_DOWNNORMAL; 493 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 494 return (hr == S_OK); 495 } 496 if( nPart == PART_BUTTON_LEFT ) 497 { 498 iPart = SBP_ARROWBTN; 499 if( nState & CTRL_STATE_PRESSED ) 500 iState = ABS_LEFTPRESSED; 501 else if( !(nState & CTRL_STATE_ENABLED) ) 502 iState = ABS_LEFTDISABLED; 503 else if( nState & CTRL_STATE_ROLLOVER ) 504 iState = ABS_LEFTHOT; 505 else 506 iState = ABS_LEFTNORMAL; 507 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 508 return (hr == S_OK); 509 } 510 if( nPart == PART_BUTTON_RIGHT ) 511 { 512 iPart = SBP_ARROWBTN; 513 if( nState & CTRL_STATE_PRESSED ) 514 iState = ABS_RIGHTPRESSED; 515 else if( !(nState & CTRL_STATE_ENABLED) ) 516 iState = ABS_RIGHTDISABLED; 517 else if( nState & CTRL_STATE_ROLLOVER ) 518 iState = ABS_RIGHTHOT; 519 else 520 iState = ABS_RIGHTNORMAL; 521 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 522 return (hr == S_OK); 523 } 524 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 525 { 526 iPart = (nPart == PART_THUMB_HORZ) ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; 527 if( nState & CTRL_STATE_PRESSED ) 528 iState = SCRBS_PRESSED; 529 else if( !(nState & CTRL_STATE_ENABLED) ) 530 iState = SCRBS_DISABLED; 531 else if( nState & CTRL_STATE_ROLLOVER ) 532 iState = SCRBS_HOT; 533 else 534 iState = SCRBS_NORMAL; 535 536 SIZE sz; 537 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_MIN, &sz); 538 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_TRUE, &sz); 539 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_DRAW, &sz); 540 541 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 542 // paint gripper on thumb if enough space 543 if( ( (nPart == PART_THUMB_VERT) && (rc.bottom-rc.top > 12) ) || 544 ( (nPart == PART_THUMB_HORZ) && (rc.right-rc.left > 12) ) ) 545 { 546 iPart = (nPart == PART_THUMB_HORZ) ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; 547 iState = 0; 548 vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 549 } 550 return (hr == S_OK); 551 } 552 if( nPart == PART_TRACK_HORZ_LEFT || nPart == PART_TRACK_HORZ_RIGHT || nPart == PART_TRACK_VERT_UPPER || nPart == PART_TRACK_VERT_LOWER ) 553 { 554 switch( nPart ) 555 { 556 case PART_TRACK_HORZ_LEFT: iPart = SBP_UPPERTRACKHORZ; break; 557 case PART_TRACK_HORZ_RIGHT: iPart = SBP_LOWERTRACKHORZ; break; 558 case PART_TRACK_VERT_UPPER: iPart = SBP_UPPERTRACKVERT; break; 559 case PART_TRACK_VERT_LOWER: iPart = SBP_LOWERTRACKVERT; break; 560 } 561 562 if( nState & CTRL_STATE_PRESSED ) 563 iState = SCRBS_PRESSED; 564 else if( !(nState & CTRL_STATE_ENABLED) ) 565 iState = SCRBS_DISABLED; 566 else if( nState & CTRL_STATE_ROLLOVER ) 567 iState = SCRBS_HOT; 568 else 569 iState = SCRBS_NORMAL; 570 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); 571 return (hr == S_OK); 572 } 573 } 574 if( nType == CTRL_SPINBUTTONS && nPart == PART_ALL_BUTTONS ) 575 { 576 if( aValue.getType() == CTRL_SPINBUTTONS ) 577 { 578 const SpinbuttonValue *pValue = static_cast<const SpinbuttonValue*>(&aValue); 579 sal_Bool bOk = sal_False; 580 581 RECT rect; 582 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect ); 583 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); 584 585 if( bOk ) 586 { 587 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect ); 588 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); 589 } 590 591 return bOk; 592 } 593 } 594 if( nType == CTRL_SPINBOX ) 595 { 596 // decrease spinbutton rects a little 597 //rc.right--; 598 //rc.bottom--; 599 if( nPart == PART_ALL_BUTTONS ) 600 { 601 if( aValue.getType() == CTRL_SPINBUTTONS ) 602 { 603 const SpinbuttonValue *pValue = static_cast<const SpinbuttonValue*>(&aValue); 604 sal_Bool bOk = sal_False; 605 606 RECT rect; 607 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect ); 608 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); 609 610 if( bOk ) 611 { 612 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect ); 613 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); 614 } 615 616 return bOk; 617 } 618 } 619 620 if( nPart == PART_BUTTON_DOWN ) 621 { 622 iPart = SPNP_DOWN; 623 if( nState & CTRL_STATE_PRESSED ) 624 iState = DNS_PRESSED; 625 else if( !(nState & CTRL_STATE_ENABLED) ) 626 iState = DNS_DISABLED; 627 else if( nState & CTRL_STATE_ROLLOVER ) 628 iState = DNS_HOT; 629 else 630 iState = DNS_NORMAL; 631 } 632 if( nPart == PART_BUTTON_UP ) 633 { 634 iPart = SPNP_UP; 635 if( nState & CTRL_STATE_PRESSED ) 636 iState = UPS_PRESSED; 637 else if( !(nState & CTRL_STATE_ENABLED) ) 638 iState = UPS_DISABLED; 639 else if( nState & CTRL_STATE_ROLLOVER ) 640 iState = UPS_HOT; 641 else 642 iState = UPS_NORMAL; 643 } 644 if( nPart == PART_BUTTON_RIGHT ) 645 { 646 iPart = SPNP_DOWNHORZ; 647 if( nState & CTRL_STATE_PRESSED ) 648 iState = DNHZS_PRESSED; 649 else if( !(nState & CTRL_STATE_ENABLED) ) 650 iState = DNHZS_DISABLED; 651 else if( nState & CTRL_STATE_ROLLOVER ) 652 iState = DNHZS_HOT; 653 else 654 iState = DNHZS_NORMAL; 655 } 656 if( nPart == PART_BUTTON_LEFT ) 657 { 658 iPart = SPNP_UPHORZ; 659 if( nState & CTRL_STATE_PRESSED ) 660 iState = UPHZS_PRESSED; 661 else if( !(nState & CTRL_STATE_ENABLED) ) 662 iState = UPHZS_DISABLED; 663 else if( nState & CTRL_STATE_ROLLOVER ) 664 iState = UPHZS_HOT; 665 else 666 iState = UPHZS_NORMAL; 667 } 668 if( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN ) 669 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 670 } 671 if( nType == CTRL_COMBOBOX ) 672 { 673 if( nPart == PART_BUTTON_DOWN ) 674 { 675 iPart = CP_DROPDOWNBUTTON; 676 if( nState & CTRL_STATE_PRESSED ) 677 iState = CBXS_PRESSED; 678 else if( !(nState & CTRL_STATE_ENABLED) ) 679 iState = CBXS_DISABLED; 680 else if( nState & CTRL_STATE_ROLLOVER ) 681 iState = CBXS_HOT; 682 else 683 iState = CBXS_NORMAL; 684 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 685 } 686 } 687 if( nType == CTRL_PUSHBUTTON ) 688 { 689 iPart = BP_PUSHBUTTON; 690 if( nState & CTRL_STATE_PRESSED ) 691 iState = PBS_PRESSED; 692 else if( !(nState & CTRL_STATE_ENABLED) ) 693 iState = PBS_DISABLED; 694 else if( nState & CTRL_STATE_ROLLOVER ) 695 iState = PBS_HOT; 696 else if( nState & CTRL_STATE_DEFAULT ) 697 iState = PBS_DEFAULTED; 698 //else if( nState & CTRL_STATE_FOCUSED ) 699 // iState = PBS_DEFAULTED; // may need to draw focus rect 700 else 701 iState = PBS_NORMAL; 702 703 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 704 } 705 706 if( nType == CTRL_RADIOBUTTON ) 707 { 708 iPart = BP_RADIOBUTTON; 709 sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON ); 710 711 if( nState & CTRL_STATE_PRESSED ) 712 iState = bChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED; 713 else if( !(nState & CTRL_STATE_ENABLED) ) 714 iState = bChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED; 715 else if( nState & CTRL_STATE_ROLLOVER ) 716 iState = bChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT; 717 else 718 iState = bChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL; 719 720 //if( nState & CTRL_STATE_FOCUSED ) 721 // iState |= PBS_DEFAULTED; // may need to draw focus rect 722 723 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 724 } 725 726 if( nType == CTRL_CHECKBOX ) 727 { 728 iPart = BP_CHECKBOX; 729 ButtonValue v = aValue.getTristateVal(); 730 731 if( nState & CTRL_STATE_PRESSED ) 732 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDPRESSED : 733 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED ); 734 else if( !(nState & CTRL_STATE_ENABLED) ) 735 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDDISABLED : 736 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED ); 737 else if( nState & CTRL_STATE_ROLLOVER ) 738 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDHOT : 739 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT ); 740 else 741 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDNORMAL : 742 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL ); 743 744 //if( nState & CTRL_STATE_FOCUSED ) 745 // iState |= PBS_DEFAULTED; // may need to draw focus rect 746 747 //SIZE sz; 748 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW 749 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz); 750 751 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 752 } 753 754 if( ( nType == CTRL_EDITBOX ) || ( nType == CTRL_MULTILINE_EDITBOX ) ) 755 { 756 iPart = EP_EDITTEXT; 757 if( !(nState & CTRL_STATE_ENABLED) ) 758 iState = ETS_DISABLED; 759 else if( nState & CTRL_STATE_FOCUSED ) 760 iState = ETS_FOCUSED; 761 else if( nState & CTRL_STATE_ROLLOVER ) 762 iState = ETS_HOT; 763 else 764 iState = ETS_NORMAL; 765 766 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 767 } 768 769 if( nType == CTRL_LISTBOX ) 770 { 771 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) 772 { 773 iPart = LVP_EMPTYTEXT; // ??? no idea which part to choose here 774 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 775 } 776 } 777 778 if( nType == CTRL_TAB_PANE ) 779 { 780 iPart = TABP_PANE; 781 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 782 } 783 784 if( nType == CTRL_FIXEDBORDER ) 785 { 786 /* 787 iPart = BP_GROUPBOX; 788 if( !(nState & CTRL_STATE_ENABLED) ) 789 iState = GBS_DISABLED; 790 else 791 iState = GBS_NORMAL; 792 */ 793 // The fixed border is only used around the tools->options tabpage where 794 // TABP_PANE fits best 795 iPart = TABP_PANE; 796 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 797 } 798 799 if( nType == CTRL_TAB_BODY ) 800 { 801 iPart = TABP_BODY; 802 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 803 } 804 805 if( nType == CTRL_TAB_ITEM ) 806 { 807 iPart = TABP_TABITEMLEFTEDGE; 808 rc.bottom--; 809 810 OSL_ASSERT( aValue.getType() == CTRL_TAB_ITEM ); 811 812 const TabitemValue *pValue = static_cast<const TabitemValue*>(&aValue); 813 if( pValue->isBothAligned() ) 814 { 815 iPart = TABP_TABITEMLEFTEDGE; 816 rc.right--; 817 } 818 else if( pValue->isLeftAligned() ) 819 iPart = TABP_TABITEMLEFTEDGE; 820 else if( pValue->isRightAligned() ) 821 iPart = TABP_TABITEMRIGHTEDGE; 822 else iPart = TABP_TABITEM; 823 824 if( !(nState & CTRL_STATE_ENABLED) ) 825 iState = TILES_DISABLED; 826 else if( nState & CTRL_STATE_SELECTED ) 827 { 828 iState = TILES_SELECTED; 829 // increase the selected tab 830 rc.left-=2; 831 if( pValue && !pValue->isBothAligned() ) 832 { 833 if( pValue->isLeftAligned() || pValue->isNotAligned() ) 834 rc.right+=2; 835 if( pValue->isRightAligned() ) 836 rc.right+=1; 837 } 838 rc.top-=2; 839 rc.bottom+=2; 840 } 841 else if( nState & CTRL_STATE_ROLLOVER ) 842 iState = TILES_HOT; 843 else if( nState & CTRL_STATE_FOCUSED ) 844 iState = TILES_FOCUSED; // may need to draw focus rect 845 else 846 iState = TILES_NORMAL; 847 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 848 } 849 850 if( nType == CTRL_TOOLBAR ) 851 { 852 if( nPart == PART_BUTTON ) 853 { 854 iPart = TP_BUTTON; 855 sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON ); 856 if( !(nState & CTRL_STATE_ENABLED) ) 857 //iState = TS_DISABLED; 858 // disabled buttons are typically not painted at all but we need visual 859 // feedback when travelling by keyboard over disabled entries 860 iState = TS_HOT; 861 else if( nState & CTRL_STATE_PRESSED ) 862 iState = TS_PRESSED; 863 else if( nState & CTRL_STATE_ROLLOVER ) 864 iState = bChecked ? TS_HOTCHECKED : TS_HOT; 865 else 866 iState = bChecked ? TS_CHECKED : TS_NORMAL; 867 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 868 } 869 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 870 { 871 // the vertical gripper is not supported in most themes and it makes no 872 // sense to only support horizontal gripper 873 //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER; 874 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 875 } 876 else if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 877 { 878 if( aValue.getType() == CTRL_TOOLBAR ) 879 { 880 const ToolbarValue *pValue = static_cast<const ToolbarValue*>(&aValue); 881 if( pValue->mbIsTopDockingArea ) 882 rc.top = 0; // extend potential gradient to cover menu bar as well 883 } 884 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 885 } 886 } 887 888 if( nType == CTRL_MENUBAR ) 889 { 890 if( nPart == PART_ENTIRE_CONTROL ) 891 { 892 if( aValue.getType() == CTRL_MENUBAR ) 893 { 894 const MenubarValue *pValue = static_cast<const MenubarValue*>(&aValue); 895 rc.bottom += pValue->maTopDockingAreaHeight; // extend potential gradient to cover docking area as well 896 } 897 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); 898 } 899 else if( nPart == PART_MENU_ITEM ) 900 { 901 if( (nState & CTRL_STATE_ENABLED) ) 902 iState = (nState & CTRL_STATE_SELECTED) ? MBI_HOT : MBI_NORMAL; 903 else 904 iState = (nState & CTRL_STATE_SELECTED) ? MBI_DISABLEDHOT : MBI_DISABLED; 905 return ImplDrawTheme( hTheme, hDC, MENU_BARITEM, iState, rc, aCaption ); 906 } 907 } 908 909 if( nType == CTRL_PROGRESS ) 910 { 911 if( nPart != PART_ENTIRE_CONTROL ) 912 return FALSE; 913 914 if( ! ImplDrawTheme( hTheme, hDC, PP_BAR, iState, rc, aCaption) ) 915 return false; 916 RECT aProgressRect = rc; 917 if( vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, PP_BAR, iState, &rc, &aProgressRect) != S_OK ) 918 return false; 919 920 long nProgressWidth = aValue.getNumericVal(); 921 nProgressWidth *= (aProgressRect.right - aProgressRect.left); 922 nProgressWidth /= (rc.right - rc.left); 923 if( Application::GetSettings().GetLayoutRTL() ) 924 aProgressRect.left = aProgressRect.right - nProgressWidth; 925 else 926 aProgressRect.right = aProgressRect.left + nProgressWidth; 927 928 return ImplDrawTheme( hTheme, hDC, PP_CHUNK, iState, aProgressRect, aCaption ); 929 } 930 931 if( nType == CTRL_SLIDER ) 932 { 933 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_TRACK : TKP_TRACKVERT; 934 iState = (nPart == PART_TRACK_HORZ_AREA) ? TRS_NORMAL : TRVS_NORMAL; 935 936 Rectangle aTrackRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() ); 937 RECT aTRect = rc; 938 if( nPart == PART_TRACK_HORZ_AREA ) 939 { 940 long nH = aTrackRect.GetHeight(); 941 aTRect.top += (rc.bottom - rc.top - nH)/2; 942 aTRect.bottom = aTRect.top + nH; 943 } 944 else 945 { 946 long nW = aTrackRect.GetWidth(); 947 aTRect.left += (rc.right - rc.left - nW)/2; 948 aTRect.right = aTRect.left + nW; 949 } 950 ImplDrawTheme( hTheme, hDC, iPart, iState, aTRect, aCaption ); 951 952 RECT aThumbRect; 953 OSL_ASSERT( aValue.getType() == CTRL_SLIDER ); 954 const SliderValue* pVal = static_cast<const SliderValue*>(&aValue); 955 aThumbRect.left = pVal->maThumbRect.Left(); 956 aThumbRect.top = pVal->maThumbRect.Top(); 957 aThumbRect.right = pVal->maThumbRect.Right(); 958 aThumbRect.bottom = pVal->maThumbRect.Bottom(); 959 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_THUMB : TKP_THUMBVERT; 960 iState = (nState & CTRL_STATE_ENABLED) ? TUS_NORMAL : TUS_DISABLED; 961 return ImplDrawTheme( hTheme, hDC, iPart, iState, aThumbRect, aCaption ); 962 } 963 964 if( nType == CTRL_LISTNODE ) 965 { 966 if( nPart != PART_ENTIRE_CONTROL ) 967 return FALSE; 968 969 ButtonValue aButtonValue = aValue.getTristateVal(); 970 iPart = TVP_GLYPH; 971 switch( aButtonValue ) 972 { 973 case BUTTONVALUE_ON: 974 iState = GLPS_OPENED; 975 break; 976 case BUTTONVALUE_OFF: 977 iState = GLPS_CLOSED; 978 break; 979 default: 980 return FALSE; 981 } 982 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption ); 983 } 984 985 if( GetSalData()->mbThemeMenuSupport ) 986 { 987 if( nType == CTRL_MENU_POPUP ) 988 { 989 if( nPart == PART_ENTIRE_CONTROL ) 990 { 991 RECT aGutterRC = rc; 992 aGutterRC.left += aValue.getNumericVal(); 993 aGutterRC.right = aGutterRC.left+3; 994 return 995 ImplDrawTheme( hTheme, hDC, MENU_POPUPBACKGROUND, 0, rc, aCaption ) && 996 ImplDrawTheme( hTheme, hDC, MENU_POPUPGUTTER, 0, aGutterRC, aCaption ) 997 ; 998 } 999 else if( nPart == PART_MENU_ITEM ) 1000 { 1001 if( (nState & CTRL_STATE_ENABLED) ) 1002 iState = (nState & CTRL_STATE_SELECTED) ? MPI_HOT : MPI_NORMAL; 1003 else 1004 iState = (nState & CTRL_STATE_SELECTED) ? MPI_DISABLEDHOT : MPI_DISABLED; 1005 return ImplDrawTheme( hTheme, hDC, MENU_POPUPITEM, iState, rc, aCaption ); 1006 } 1007 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ) 1008 { 1009 if( (nState & CTRL_STATE_PRESSED) ) 1010 { 1011 RECT aBGRect = rc; 1012 if( aValue.getType() == CTRL_MENU_POPUP ) 1013 { 1014 const MenupopupValue& rMVal( static_cast<const MenupopupValue&>(aValue) ); 1015 aBGRect.left = rMVal.maItemRect.Left(); 1016 aBGRect.top = rMVal.maItemRect.Top(); 1017 aBGRect.bottom = rMVal.maItemRect.Bottom()+1; // see below in drawNativeControl 1018 aBGRect.right = rMVal.getNumericVal(); 1019 1020 // FIXME: magic 1021 aBGRect.left += 1; aBGRect.top += 1; aBGRect.bottom +=1; 1022 } 1023 iState = (nState & CTRL_STATE_ENABLED) ? MCB_NORMAL : MCB_DISABLED; 1024 ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECKBACKGROUND, iState, aBGRect, aCaption ); 1025 if( nPart == PART_MENU_ITEM_CHECK_MARK ) 1026 iState = (nState & CTRL_STATE_ENABLED) ? MC_CHECKMARKNORMAL : MC_CHECKMARKDISABLED; 1027 else 1028 iState = (nState & CTRL_STATE_ENABLED) ? MC_BULLETNORMAL : MC_BULLETDISABLED; 1029 return ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECK, iState, rc, aCaption ); 1030 } 1031 else 1032 return true; // unchecked: do nothing 1033 } 1034 else if( nPart == PART_MENU_SEPARATOR ) 1035 { 1036 rc.left += aValue.getNumericVal(); // adjust for gutter position 1037 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, 1038 MENU_POPUPSEPARATOR, 0, Rectangle( rc.left, rc.top, rc.right, rc.bottom ) ) ); 1039 // center the separator inside the passed rectangle 1040 long nDY = ((rc.bottom - rc.top + 1) - aRect.GetHeight()) / 2; 1041 rc.top += nDY; 1042 rc.bottom = rc.top+aRect.GetHeight()-1; 1043 return ImplDrawTheme( hTheme, hDC, MENU_POPUPSEPARATOR, 0, rc, aCaption ); 1044 } 1045 } 1046 } 1047 1048 return false; 1049 } 1050 1051 /* 1052 * DrawNativeControl() 1053 * 1054 * Draws the requested control described by nPart/nState. 1055 * 1056 * rControlRegion: The bounding region of the complete control in VCL frame coordinates. 1057 * aValue: An optional value (tristate/numerical/string) 1058 * aCaption: A caption or title string (like button text etc) 1059 */ 1060 sal_Bool WinSalGraphics::drawNativeControl( ControlType nType, 1061 ControlPart nPart, 1062 const Rectangle& rControlRegion, 1063 ControlState nState, 1064 const ImplControlValue& aValue, 1065 const OUString& aCaption ) 1066 { 1067 sal_Bool bOk = false; 1068 HTHEME hTheme = NULL; 1069 1070 switch( nType ) 1071 { 1072 case CTRL_PUSHBUTTON: 1073 case CTRL_RADIOBUTTON: 1074 case CTRL_CHECKBOX: 1075 hTheme = getThemeHandle( mhWnd, L"Button"); 1076 break; 1077 case CTRL_SCROLLBAR: 1078 hTheme = getThemeHandle( mhWnd, L"Scrollbar"); 1079 break; 1080 case CTRL_COMBOBOX: 1081 if( nPart == PART_ENTIRE_CONTROL ) 1082 hTheme = getThemeHandle( mhWnd, L"Edit"); 1083 else if( nPart == PART_BUTTON_DOWN ) 1084 hTheme = getThemeHandle( mhWnd, L"Combobox"); 1085 break; 1086 case CTRL_SPINBOX: 1087 if( nPart == PART_ENTIRE_CONTROL ) 1088 hTheme = getThemeHandle( mhWnd, L"Edit"); 1089 else 1090 hTheme = getThemeHandle( mhWnd, L"Spin"); 1091 break; 1092 case CTRL_SPINBUTTONS: 1093 hTheme = getThemeHandle( mhWnd, L"Spin"); 1094 break; 1095 case CTRL_EDITBOX: 1096 case CTRL_MULTILINE_EDITBOX: 1097 hTheme = getThemeHandle( mhWnd, L"Edit"); 1098 break; 1099 case CTRL_LISTBOX: 1100 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) 1101 hTheme = getThemeHandle( mhWnd, L"Listview"); 1102 else if( nPart == PART_BUTTON_DOWN ) 1103 hTheme = getThemeHandle( mhWnd, L"Combobox"); 1104 break; 1105 case CTRL_TAB_PANE: 1106 case CTRL_TAB_BODY: 1107 case CTRL_TAB_ITEM: 1108 case CTRL_FIXEDBORDER: 1109 hTheme = getThemeHandle( mhWnd, L"Tab"); 1110 break; 1111 case CTRL_TOOLBAR: 1112 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON ) 1113 hTheme = getThemeHandle( mhWnd, L"Toolbar"); 1114 else 1115 // use rebar for grip and background 1116 hTheme = getThemeHandle( mhWnd, L"Rebar"); 1117 break; 1118 case CTRL_MENUBAR: 1119 if( nPart == PART_ENTIRE_CONTROL ) 1120 hTheme = getThemeHandle( mhWnd, L"Rebar"); 1121 else if( GetSalData()->mbThemeMenuSupport ) 1122 { 1123 if( nPart == PART_MENU_ITEM ) 1124 hTheme = getThemeHandle( mhWnd, L"Menu" ); 1125 } 1126 break; 1127 case CTRL_PROGRESS: 1128 if( nPart == PART_ENTIRE_CONTROL ) 1129 hTheme = getThemeHandle( mhWnd, L"Progress"); 1130 break; 1131 case CTRL_LISTNODE: 1132 if( nPart == PART_ENTIRE_CONTROL ) 1133 hTheme = getThemeHandle( mhWnd, L"TreeView"); 1134 break; 1135 case CTRL_SLIDER: 1136 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) 1137 hTheme = getThemeHandle( mhWnd, L"Trackbar" ); 1138 break; 1139 case CTRL_MENU_POPUP: 1140 if( GetSalData()->mbThemeMenuSupport ) 1141 { 1142 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM || 1143 nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK || 1144 nPart == PART_MENU_SEPARATOR 1145 ) 1146 hTheme = getThemeHandle( mhWnd, L"Menu" ); 1147 } 1148 break; 1149 default: 1150 hTheme = NULL; 1151 break; 1152 } 1153 1154 if( !hTheme ) 1155 return false; 1156 1157 Rectangle buttonRect = rControlRegion; 1158 RECT rc; 1159 rc.left = buttonRect.Left(); 1160 rc.right = buttonRect.Right()+1; 1161 rc.top = buttonRect.Top(); 1162 rc.bottom = buttonRect.Bottom()+1; 1163 1164 // set default text alignment 1165 int ta = SetTextAlign( mhDC, TA_LEFT|TA_TOP|TA_NOUPDATECP ); 1166 1167 OUString aCaptionStr( aCaption.replace('~', '&') ); // translate mnemonics 1168 bOk = ImplDrawNativeControl(mhDC, hTheme, rc, 1169 nType, nPart, nState, aValue, 1170 aCaptionStr ); 1171 1172 // restore alignment 1173 SetTextAlign( mhDC, ta ); 1174 1175 1176 //GdiFlush(); 1177 1178 return bOk; 1179 } 1180 1181 1182 /* 1183 * DrawNativeControlText() 1184 * 1185 * OPTIONAL. Draws the requested text for the control described by nPart/nState. 1186 * Used if text not drawn by DrawNativeControl(). 1187 * 1188 * rControlRegion: The bounding region of the complete control in VCL frame coordinates. 1189 * aValue: An optional value (tristate/numerical/string) 1190 * aCaption: A caption or title string (like button text etc) 1191 */ 1192 sal_Bool WinSalGraphics::drawNativeControlText( ControlType, 1193 ControlPart, 1194 const Rectangle&, 1195 ControlState, 1196 const ImplControlValue&, 1197 const OUString& ) 1198 { 1199 return( false ); 1200 } 1201 1202 1203 /* 1204 * GetNativeControlRegion() 1205 * 1206 * If the return value is TRUE, rNativeBoundingRegion 1207 * contains the true bounding region covered by the control 1208 * including any adornment, while rNativeContentRegion contains the area 1209 * within the control that can be safely drawn into without drawing over 1210 * the borders of the control. 1211 * 1212 * rControlRegion: The bounding region of the control in VCL frame coordinates. 1213 * aValue: An optional value (tristate/numerical/string) 1214 * aCaption: A caption or title string (like button text etc) 1215 */ 1216 sal_Bool WinSalGraphics::getNativeControlRegion( ControlType nType, 1217 ControlPart nPart, 1218 const Rectangle& rControlRegion, 1219 ControlState nState, 1220 const ImplControlValue& rControlValue, 1221 const OUString&, 1222 Rectangle &rNativeBoundingRegion, 1223 Rectangle &rNativeContentRegion ) 1224 { 1225 sal_Bool bRet = FALSE; 1226 1227 HDC hDC = GetDC( mhWnd ); 1228 if( nType == CTRL_TOOLBAR ) 1229 { 1230 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 1231 { 1232 /* 1233 // the vertical gripper is not supported in most themes and it makes no 1234 // sense to only support horizontal gripper 1235 1236 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar"); 1237 if( hTheme ) 1238 { 1239 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER, 1240 0, rControlRegion.GetBoundRect() ) ); 1241 if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() ) 1242 { 1243 Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() ); 1244 rNativeContentRegion = aVertRect; 1245 } 1246 else 1247 rNativeContentRegion = aRect; 1248 rNativeBoundingRegion = rNativeContentRegion; 1249 if( !rNativeContentRegion.IsEmpty() ) 1250 bRet = TRUE; 1251 } 1252 */ 1253 } 1254 if( nPart == PART_BUTTON ) 1255 { 1256 HTHEME hTheme = getThemeHandle( mhWnd, L"Toolbar"); 1257 if( hTheme ) 1258 { 1259 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, TP_SPLITBUTTONDROPDOWN, 1260 TS_HOT, rControlRegion ) ); 1261 rNativeContentRegion = aRect; 1262 rNativeBoundingRegion = rNativeContentRegion; 1263 if( !rNativeContentRegion.IsEmpty() ) 1264 bRet = TRUE; 1265 } 1266 } 1267 } 1268 if( nType == CTRL_PROGRESS && nPart == PART_ENTIRE_CONTROL ) 1269 { 1270 HTHEME hTheme = getThemeHandle( mhWnd, L"Progress"); 1271 if( hTheme ) 1272 { 1273 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, PP_BAR, 1274 0, rControlRegion ) ); 1275 rNativeContentRegion = aRect; 1276 rNativeBoundingRegion = rNativeContentRegion; 1277 if( !rNativeContentRegion.IsEmpty() ) 1278 bRet = TRUE; 1279 } 1280 } 1281 if( (nType == CTRL_LISTBOX || nType == CTRL_COMBOBOX ) && nPart == PART_ENTIRE_CONTROL ) 1282 { 1283 HTHEME hTheme = getThemeHandle( mhWnd, L"Combobox"); 1284 if( hTheme ) 1285 { 1286 Rectangle aBoxRect( rControlRegion ); 1287 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, CP_DROPDOWNBUTTON, 1288 CBXS_NORMAL, aBoxRect ) ); 1289 if( aRect.GetHeight() > aBoxRect.GetHeight() ) 1290 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight(); 1291 if( aRect.GetWidth() > aBoxRect.GetWidth() ) 1292 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth(); 1293 rNativeContentRegion = aBoxRect; 1294 rNativeBoundingRegion = rNativeContentRegion; 1295 if( !aRect.IsEmpty() ) 1296 bRet = TRUE; 1297 } 1298 } 1299 1300 if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL ) 1301 { 1302 HTHEME hTheme = getThemeHandle( mhWnd, L"Edit"); 1303 if( hTheme ) 1304 { 1305 // get border size 1306 Rectangle aBoxRect( rControlRegion ); 1307 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, EP_BACKGROUNDWITHBORDER, 1308 EBWBS_HOT, aBoxRect ) ); 1309 // ad app font height 1310 NONCLIENTMETRICSW aNonClientMetrics; 1311 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); 1312 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) 1313 { 1314 long nFontHeight = aNonClientMetrics.lfMessageFont.lfHeight; 1315 if( nFontHeight < 0 ) 1316 nFontHeight = -nFontHeight; 1317 1318 if( aRect.GetHeight() && nFontHeight ) 1319 { 1320 aRect.Bottom() += aRect.GetHeight(); 1321 aRect.Bottom() += nFontHeight; 1322 if( aRect.GetHeight() > aBoxRect.GetHeight() ) 1323 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight(); 1324 if( aRect.GetWidth() > aBoxRect.GetWidth() ) 1325 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth(); 1326 rNativeContentRegion = aBoxRect; 1327 rNativeBoundingRegion = rNativeContentRegion; 1328 bRet = TRUE; 1329 } 1330 } 1331 } 1332 } 1333 1334 if( GetSalData()->mbThemeMenuSupport ) 1335 { 1336 if( nType == CTRL_MENU_POPUP ) 1337 { 1338 if( nPart == PART_MENU_ITEM_CHECK_MARK || 1339 nPart == PART_MENU_ITEM_RADIO_MARK ) 1340 { 1341 HTHEME hTheme = getThemeHandle( mhWnd, L"Menu"); 1342 Rectangle aBoxRect( rControlRegion ); 1343 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, 1344 MENU_POPUPCHECK, 1345 MC_CHECKMARKNORMAL, 1346 aBoxRect ) ); 1347 if( aBoxRect.GetWidth() && aBoxRect.GetHeight() ) 1348 { 1349 rNativeContentRegion = aRect; 1350 rNativeBoundingRegion = rNativeContentRegion; 1351 bRet = TRUE; 1352 } 1353 } 1354 } 1355 } 1356 1357 if( nType == CTRL_SLIDER && ( (nPart == PART_THUMB_HORZ) || (nPart == PART_THUMB_VERT) ) ) 1358 { 1359 HTHEME hTheme = getThemeHandle( mhWnd, L"Trackbar"); 1360 if( hTheme ) 1361 { 1362 int iPart = (nPart == PART_THUMB_HORZ) ? TKP_THUMB : TKP_THUMBVERT; 1363 int iState = (nPart == PART_THUMB_HORZ) ? TUS_NORMAL : TUVS_NORMAL; 1364 Rectangle aThumbRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() ); 1365 if( nPart == PART_THUMB_HORZ ) 1366 { 1367 long nW = aThumbRect.GetWidth(); 1368 Rectangle aRect( rControlRegion ); 1369 aRect.Right() = aRect.Left() + nW - 1; 1370 rNativeContentRegion = aRect; 1371 rNativeBoundingRegion = rNativeContentRegion; 1372 } 1373 else 1374 { 1375 long nH = aThumbRect.GetHeight(); 1376 Rectangle aRect( rControlRegion ); 1377 aRect.Bottom() = aRect.Top() + nH - 1; 1378 rNativeContentRegion = aRect; 1379 rNativeBoundingRegion = rNativeContentRegion; 1380 } 1381 bRet = TRUE; 1382 } 1383 } 1384 1385 if ( ( nType == CTRL_TAB_ITEM ) && ( nPart == PART_ENTIRE_CONTROL ) ) 1386 { 1387 Rectangle aControlRect( rControlRegion ); 1388 rNativeContentRegion = aControlRect; 1389 1390 --aControlRect.Bottom(); 1391 1392 if( rControlValue.getType() == CTRL_TAB_ITEM ) 1393 { 1394 const TabitemValue *pValue = static_cast<const TabitemValue*>(&rControlValue); 1395 if ( pValue->isBothAligned() ) 1396 --aControlRect.Right(); 1397 1398 if ( nState & CTRL_STATE_SELECTED ) 1399 { 1400 aControlRect.Left() -= 2; 1401 if ( pValue && !pValue->isBothAligned() ) 1402 { 1403 if ( pValue->isLeftAligned() || pValue->isNotAligned() ) 1404 aControlRect.Right() += 2; 1405 if ( pValue->isRightAligned() ) 1406 aControlRect.Right() += 1; 1407 } 1408 aControlRect.Top() -= 2; 1409 aControlRect.Bottom() += 2; 1410 } 1411 } 1412 rNativeBoundingRegion = aControlRect; 1413 bRet = TRUE; 1414 } 1415 1416 ReleaseDC( mhWnd, hDC ); 1417 return( bRet ); 1418 } 1419 1420