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