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