1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 // http://msdn.microsoft.com/en-us/library/windows/desktop/hh270423%28v=vs.85%29.aspx
22 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773178%28v=vs.85%29.aspx
24 // Useful tool to explore the themes & their rendering:
25 // http://privat.rejbrand.se/UxExplore.exe
26 // (found at http://stackoverflow.com/questions/4009701/windows-visual-themes-gallery-of-parts-and-states/4009712#4009712)
29 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773218%28v=vs.85%29.aspx
31 // Drawing in non-client area (general DWM-related info):
32 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb688195%28v=vs.85%29.aspx
34 #include <rtl/ustring.h>
36 #include <osl/diagnose.h>
37 #include <osl/module.h>
38 #include <o3tl/char16_t2wchar_t.hxx>
40 #include <opengl/win/gdiimpl.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/settings.hxx>
44 #include <win/svsys.h>
45 #include <win/salgdi.h>
46 #include <win/saldata.hxx>
47 #include <win/scoped_gdi.hxx>
54 #include <boost/optional.hpp>
55 #include <ControlCacheKey.hxx>
59 typedef map
< wstring
, HTHEME
> ThemeMap
;
60 static ThemeMap aThemeMap
;
62 /****************************************************
63 wrap visual styles API to avoid linking against it
64 it is not available on all Windows platforms
65 *****************************************************/
70 typedef HTHEME (WINAPI
* OpenThemeData_Proc_T
) ( HWND hwnd
, LPCWSTR pszClassList
);
71 typedef HRESULT (WINAPI
* CloseThemeData_Proc_T
) ( HTHEME hTheme
);
72 typedef HRESULT (WINAPI
* GetThemeBackgroundContentRect_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
73 typedef HRESULT (WINAPI
* DrawThemeBackground_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
74 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
);
75 typedef HRESULT (WINAPI
* GetThemePartSize_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
76 typedef BOOL (WINAPI
* IsThemeActive_Proc_T
) ( void );
78 OpenThemeData_Proc_T lpfnOpenThemeData
;
79 CloseThemeData_Proc_T lpfnCloseThemeData
;
80 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect
;
81 DrawThemeBackground_Proc_T lpfnDrawThemeBackground
;
82 DrawThemeText_Proc_T lpfnDrawThemeText
;
83 GetThemePartSize_Proc_T lpfnGetThemePartSize
;
84 IsThemeActive_Proc_T lpfnIsThemeActive
;
92 HTHEME
OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
);
93 HRESULT
CloseThemeData( HTHEME hTheme
);
94 HRESULT
GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
95 HRESULT
DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
96 HRESULT
DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
);
97 HRESULT
GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
101 static VisualStylesAPI vsAPI
;
103 VisualStylesAPI::VisualStylesAPI()
104 : lpfnOpenThemeData( nullptr ),
105 lpfnCloseThemeData( nullptr ),
106 lpfnGetThemeBackgroundContentRect( nullptr ),
107 lpfnDrawThemeBackground( nullptr ),
108 lpfnDrawThemeText( nullptr ),
109 lpfnGetThemePartSize( nullptr ),
110 lpfnIsThemeActive( nullptr )
112 OUString
aLibraryName( "uxtheme.dll" );
113 mhModule
= osl_loadModule( aLibraryName
.pData
, SAL_LOADMODULE_DEFAULT
);
117 lpfnOpenThemeData
= reinterpret_cast<OpenThemeData_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "OpenThemeData" ));
118 lpfnCloseThemeData
= reinterpret_cast<CloseThemeData_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "CloseThemeData" ));
119 lpfnGetThemeBackgroundContentRect
= reinterpret_cast<GetThemeBackgroundContentRect_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "GetThemeBackgroundContentRect" ));
120 lpfnDrawThemeBackground
= reinterpret_cast<DrawThemeBackground_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeBackground" ));
121 lpfnDrawThemeText
= reinterpret_cast<DrawThemeText_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeText" ));
122 lpfnGetThemePartSize
= reinterpret_cast<GetThemePartSize_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "GetThemePartSize" ));
123 lpfnIsThemeActive
= reinterpret_cast<IsThemeActive_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "IsThemeActive" ));
127 VisualStylesAPI::~VisualStylesAPI()
130 osl_unloadModule( mhModule
);
133 HTHEME
VisualStylesAPI::OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
)
135 if(lpfnOpenThemeData
)
136 return (*lpfnOpenThemeData
) (hwnd
, pszClassList
);
141 HRESULT
VisualStylesAPI::CloseThemeData( HTHEME hTheme
)
143 if(lpfnCloseThemeData
)
144 return (*lpfnCloseThemeData
) (hTheme
);
149 HRESULT
VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
)
151 if(lpfnGetThemeBackgroundContentRect
)
152 return (*lpfnGetThemeBackgroundContentRect
) ( hTheme
, hdc
, iPartId
, iStateId
, pBoundingRect
, pContentRect
);
157 HRESULT
VisualStylesAPI::DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
)
159 if(lpfnDrawThemeBackground
)
160 return (*lpfnDrawThemeBackground
) (hTheme
, hdc
, iPartId
, iStateId
, pRect
, pClipRect
);
165 HRESULT
VisualStylesAPI::DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
)
167 if(lpfnDrawThemeText
)
168 return (*lpfnDrawThemeText
) (hTheme
, hdc
, iPartId
, iStateId
, pszText
, iCharCount
, dwTextFlags
, dwTextFlags2
, pRect
);
173 HRESULT
VisualStylesAPI::GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
)
175 if(lpfnGetThemePartSize
)
176 return (*lpfnGetThemePartSize
) (hTheme
, hdc
, iPartId
, iStateId
, prc
, eSize
, psz
);
181 BOOL
VisualStylesAPI::IsThemeActive()
183 if(lpfnIsThemeActive
)
184 return (*lpfnIsThemeActive
) ();
189 /*********************************************************
190 * Initialize XP theming and local stuff
191 *********************************************************/
192 void SalData::initNWF()
194 ImplSVData
* pSVData
= ImplGetSVData();
196 // the menu bar and the top docking area should have a common background (gradient)
197 pSVData
->maNWFData
.mbMenuBarDockingAreaCommonBG
= true;
200 // *********************************************************
201 // * Release theming handles
202 // ********************************************************
203 void SalData::deInitNWF()
205 for( auto& rEntry
: aThemeMap
)
206 vsAPI
.CloseThemeData(rEntry
.second
);
210 static HTHEME
getThemeHandle( HWND hWnd
, LPCWSTR name
)
212 if( GetSalData()->mbThemeChanged
)
214 // throw away invalid theme handles
215 SalData::deInitNWF();
216 GetSalData()->mbThemeChanged
= false;
219 ThemeMap::iterator iter
;
220 if( (iter
= aThemeMap
.find( name
)) != aThemeMap
.end() )
222 // theme not found -> add it to map
223 HTHEME hTheme
= vsAPI
.OpenThemeData( hWnd
, name
);
224 if( hTheme
!= nullptr )
225 aThemeMap
[name
] = hTheme
;
229 bool WinSalGraphics::isNativeControlSupported( ControlType nType
, ControlPart nPart
)
231 HTHEME hTheme
= nullptr;
235 case ControlType::Pushbutton
:
236 case ControlType::Radiobutton
:
237 case ControlType::Checkbox
:
238 if( nPart
== ControlPart::Entire
)
239 hTheme
= getThemeHandle( mhWnd
, L
"Button");
241 case ControlType::Scrollbar
:
242 if( nPart
== ControlPart::DrawBackgroundHorz
|| nPart
== ControlPart::DrawBackgroundVert
)
243 return FALSE
; // no background painting needed
244 if( nPart
== ControlPart::Entire
)
245 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
247 case ControlType::Combobox
:
248 if( nPart
== ControlPart::HasBackgroundTexture
)
249 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
250 if( nPart
== ControlPart::Entire
)
251 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
252 else if( nPart
== ControlPart::ButtonDown
)
253 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
255 case ControlType::Spinbox
:
256 if( nPart
== ControlPart::Entire
)
257 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
258 else if( nPart
== ControlPart::AllButtons
||
259 nPart
== ControlPart::ButtonUp
|| nPart
== ControlPart::ButtonDown
||
260 nPart
== ControlPart::ButtonLeft
|| nPart
== ControlPart::ButtonRight
)
261 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
263 case ControlType::SpinButtons
:
264 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::AllButtons
)
265 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
267 case ControlType::Editbox
:
268 case ControlType::MultilineEditbox
:
269 if( nPart
== ControlPart::HasBackgroundTexture
)
270 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
272 if( nPart
== ControlPart::Entire
)
273 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
275 case ControlType::Listbox
:
276 if( nPart
== ControlPart::HasBackgroundTexture
)
277 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
278 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
279 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
280 else if( nPart
== ControlPart::ButtonDown
)
281 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
283 case ControlType::TabPane
:
284 case ControlType::TabBody
:
285 case ControlType::TabItem
:
286 if( nPart
== ControlPart::Entire
)
287 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
289 case ControlType::Toolbar
:
290 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::Button
)
291 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
293 // use rebar theme for grip and background
294 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
296 case ControlType::Menubar
:
297 if( nPart
== ControlPart::Entire
)
298 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
299 else if( GetSalData()->mbThemeMenuSupport
)
301 if( nPart
== ControlPart::MenuItem
)
302 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
305 case ControlType::MenuPopup
:
306 if( GetSalData()->mbThemeMenuSupport
)
308 if( nPart
== ControlPart::Entire
||
309 nPart
== ControlPart::MenuItem
||
310 nPart
== ControlPart::MenuItemCheckMark
||
311 nPart
== ControlPart::MenuItemRadioMark
||
312 nPart
== ControlPart::Separator
)
313 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
316 case ControlType::Progress
:
317 if( nPart
== ControlPart::Entire
)
318 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
320 case ControlType::Slider
:
321 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
322 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
324 case ControlType::ListNode
:
325 if( nPart
== ControlPart::Entire
)
326 hTheme
= getThemeHandle( mhWnd
, L
"TreeView" );
333 return (hTheme
!= nullptr);
336 bool WinSalGraphics::hitTestNativeControl( ControlType
,
338 const tools::Rectangle
&,
345 static bool ImplDrawTheme( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, RECT rc
, const OUString
& aStr
)
347 HRESULT hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
349 if( aStr
.getLength() )
352 hr
= vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, iPart
, iState
, &rc
, &rcContent
);
353 hr
= vsAPI
.DrawThemeText( hTheme
, hDC
, iPart
, iState
,
354 o3tl::toW(aStr
.getStr()), -1,
355 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
,
361 static tools::Rectangle
ImplGetThemeRect( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, const tools::Rectangle
& /* aRect */, THEMESIZE eTS
= TS_TRUE
)
364 HRESULT hr
= vsAPI
.GetThemePartSize( hTheme
, hDC
, iPart
, iState
, nullptr, eTS
, &aSz
); // TS_TRUE returns optimal size
366 return tools::Rectangle( 0, 0, aSz
.cx
, aSz
.cy
);
368 return tools::Rectangle();
373 static void ImplConvertSpinbuttonValues( ControlPart nControlPart
, const ControlState
& rState
, const tools::Rectangle
& rRect
,
374 int* pLunaPart
, int *pLunaState
, RECT
*pRect
)
376 if( nControlPart
== ControlPart::ButtonDown
)
378 *pLunaPart
= SPNP_DOWN
;
379 if( rState
& ControlState::PRESSED
)
380 *pLunaState
= DNS_PRESSED
;
381 else if( !(rState
& ControlState::ENABLED
) )
382 *pLunaState
= DNS_DISABLED
;
383 else if( rState
& ControlState::ROLLOVER
)
384 *pLunaState
= DNS_HOT
;
386 *pLunaState
= DNS_NORMAL
;
388 if( nControlPart
== ControlPart::ButtonUp
)
390 *pLunaPart
= SPNP_UP
;
391 if( rState
& ControlState::PRESSED
)
392 *pLunaState
= UPS_PRESSED
;
393 else if( !(rState
& ControlState::ENABLED
) )
394 *pLunaState
= UPS_DISABLED
;
395 else if( rState
& ControlState::ROLLOVER
)
396 *pLunaState
= UPS_HOT
;
398 *pLunaState
= UPS_NORMAL
;
400 if( nControlPart
== ControlPart::ButtonRight
)
402 *pLunaPart
= SPNP_UPHORZ
;
403 if( rState
& ControlState::PRESSED
)
404 *pLunaState
= DNHZS_PRESSED
;
405 else if( !(rState
& ControlState::ENABLED
) )
406 *pLunaState
= DNHZS_DISABLED
;
407 else if( rState
& ControlState::ROLLOVER
)
408 *pLunaState
= DNHZS_HOT
;
410 *pLunaState
= DNHZS_NORMAL
;
412 if( nControlPart
== ControlPart::ButtonLeft
)
414 *pLunaPart
= SPNP_DOWNHORZ
;
415 if( rState
& ControlState::PRESSED
)
416 *pLunaState
= UPHZS_PRESSED
;
417 else if( !(rState
& ControlState::ENABLED
) )
418 *pLunaState
= UPHZS_DISABLED
;
419 else if( rState
& ControlState::ROLLOVER
)
420 *pLunaState
= UPHZS_HOT
;
422 *pLunaState
= UPHZS_NORMAL
;
425 pRect
->left
= rRect
.Left();
426 pRect
->right
= rRect
.Right()+1;
427 pRect
->top
= rRect
.Top();
428 pRect
->bottom
= rRect
.Bottom()+1;
431 /// Draw an own toolbar style on Windows Vista or later, looks better there
432 static void impl_drawAeroToolbar( HDC hDC
, RECT rc
, bool bHorizontal
)
434 if ( rc
.top
== 0 && bHorizontal
)
436 const long GRADIENT_HEIGHT
= 32;
438 long gradient_break
= rc
.top
;
439 long gradient_bottom
= rc
.bottom
- 1;
440 GRADIENT_RECT g_rect
[1] = { { 0, 1 } };
442 // very slow gradient at the top (if we have space for that)
443 if ( gradient_bottom
- rc
.top
> GRADIENT_HEIGHT
)
445 gradient_break
= gradient_bottom
- GRADIENT_HEIGHT
;
447 TRIVERTEX vert
[2] = {
448 { rc
.left
, rc
.top
, 0xff00, 0xff00, 0xff00, 0xff00 },
449 { rc
.right
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
451 GdiGradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
454 // gradient at the bottom
455 TRIVERTEX vert
[2] = {
456 { rc
.left
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
457 { rc
.right
, gradient_bottom
, 0xf000, 0xf000, 0xf000, 0xff00 }
459 GdiGradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
461 // and a darker horizontal line under that
462 ScopedSelectedHPEN
hPen(hDC
, CreatePen(PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0)));
464 MoveToEx( hDC
, rc
.left
, gradient_bottom
, nullptr );
465 LineTo( hDC
, rc
.right
, gradient_bottom
);
469 ScopedHBRUSH
hbrush(CreateSolidBrush(RGB(0xf0, 0xf0, 0xf0)));
470 FillRect(hDC
, &rc
, hbrush
.get());
472 // darker line to distinguish the toolbar and viewshell
473 // it is drawn only for the horizontal toolbars; it did not look well
474 // when done for the vertical ones too
477 long from_x
, from_y
, to_x
, to_y
;
481 from_y
= to_y
= rc
.top
;
483 ScopedSelectedHPEN
hPen(hDC
, CreatePen(PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0)));
485 MoveToEx( hDC
, from_x
, from_y
, nullptr );
486 LineTo( hDC
, to_x
, to_y
);
492 * Gives the actual rectangle used for rendering by ControlType::MenuPopup's
493 * ControlPart::MenuItemCheckMark or ControlPart::MenuItemRadioMark.
495 static tools::Rectangle
GetMenuPopupMarkRegion(const ImplControlValue
& rValue
)
497 tools::Rectangle aRet
;
499 auto pMVal
= dynamic_cast<const MenupopupValue
*>(&rValue
);
503 aRet
.SetTop(pMVal
->maItemRect
.Top());
504 aRet
.SetBottom(pMVal
->maItemRect
.Bottom() + 1); // see below in drawNativeControl
505 if (AllSettings::GetLayoutRTL())
507 aRet
.SetRight(pMVal
->maItemRect
.Right() + 1);
508 aRet
.SetLeft(aRet
.Right() - (pMVal
->getNumericVal() - pMVal
->maItemRect
.Left()));
512 aRet
.SetRight(pMVal
->getNumericVal());
513 aRet
.SetLeft(pMVal
->maItemRect
.Left());
519 static bool ImplDrawNativeControl( HDC hDC
, HTHEME hTheme
, RECT rc
,
523 const ImplControlValue
& aValue
,
524 OUString
const & aCaption
)
526 // a listbox dropdown is actually a combobox dropdown
527 if( nType
== ControlType::Listbox
)
528 if( nPart
== ControlPart::ButtonDown
)
529 nType
= ControlType::Combobox
;
531 // draw entire combobox as a large edit box
532 if( nType
== ControlType::Combobox
)
533 if( nPart
== ControlPart::Entire
)
534 nType
= ControlType::Editbox
;
536 // draw entire spinbox as a large edit box
537 if( nType
== ControlType::Spinbox
)
538 if( nPart
== ControlPart::Entire
)
539 nType
= ControlType::Editbox
;
541 int iPart(0), iState(0);
542 if( nType
== ControlType::Scrollbar
)
545 if( nPart
== ControlPart::ButtonUp
)
547 iPart
= SBP_ARROWBTN
;
548 if( nState
& ControlState::PRESSED
)
549 iState
= ABS_UPPRESSED
;
550 else if( !(nState
& ControlState::ENABLED
) )
551 iState
= ABS_UPDISABLED
;
552 else if( nState
& ControlState::ROLLOVER
)
555 iState
= ABS_UPNORMAL
;
556 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
559 if( nPart
== ControlPart::ButtonDown
)
561 iPart
= SBP_ARROWBTN
;
562 if( nState
& ControlState::PRESSED
)
563 iState
= ABS_DOWNPRESSED
;
564 else if( !(nState
& ControlState::ENABLED
) )
565 iState
= ABS_DOWNDISABLED
;
566 else if( nState
& ControlState::ROLLOVER
)
567 iState
= ABS_DOWNHOT
;
569 iState
= ABS_DOWNNORMAL
;
570 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
573 if( nPart
== ControlPart::ButtonLeft
)
575 iPart
= SBP_ARROWBTN
;
576 if( nState
& ControlState::PRESSED
)
577 iState
= ABS_LEFTPRESSED
;
578 else if( !(nState
& ControlState::ENABLED
) )
579 iState
= ABS_LEFTDISABLED
;
580 else if( nState
& ControlState::ROLLOVER
)
581 iState
= ABS_LEFTHOT
;
583 iState
= ABS_LEFTNORMAL
;
584 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
587 if( nPart
== ControlPart::ButtonRight
)
589 iPart
= SBP_ARROWBTN
;
590 if( nState
& ControlState::PRESSED
)
591 iState
= ABS_RIGHTPRESSED
;
592 else if( !(nState
& ControlState::ENABLED
) )
593 iState
= ABS_RIGHTDISABLED
;
594 else if( nState
& ControlState::ROLLOVER
)
595 iState
= ABS_RIGHTHOT
;
597 iState
= ABS_RIGHTNORMAL
;
598 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
601 if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
603 iPart
= (nPart
== ControlPart::ThumbHorz
) ? SBP_THUMBBTNHORZ
: SBP_THUMBBTNVERT
;
604 if( nState
& ControlState::PRESSED
)
605 iState
= SCRBS_PRESSED
;
606 else if( !(nState
& ControlState::ENABLED
) )
607 iState
= SCRBS_DISABLED
;
608 else if( nState
& ControlState::ROLLOVER
)
611 iState
= SCRBS_NORMAL
;
614 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_MIN
, &sz
);
615 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_TRUE
, &sz
);
616 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_DRAW
, &sz
);
618 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
619 // paint gripper on thumb if enough space
620 if( ( (nPart
== ControlPart::ThumbVert
) && (rc
.bottom
-rc
.top
> 12) ) ||
621 ( (nPart
== ControlPart::ThumbHorz
) && (rc
.right
-rc
.left
> 12) ) )
623 iPart
= (nPart
== ControlPart::ThumbHorz
) ? SBP_GRIPPERHORZ
: SBP_GRIPPERVERT
;
625 vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
629 if( nPart
== ControlPart::TrackHorzLeft
|| nPart
== ControlPart::TrackHorzRight
|| nPart
== ControlPart::TrackVertUpper
|| nPart
== ControlPart::TrackVertLower
)
633 case ControlPart::TrackHorzLeft
: iPart
= SBP_UPPERTRACKHORZ
; break;
634 case ControlPart::TrackHorzRight
: iPart
= SBP_LOWERTRACKHORZ
; break;
635 case ControlPart::TrackVertUpper
: iPart
= SBP_UPPERTRACKVERT
; break;
636 case ControlPart::TrackVertLower
: iPart
= SBP_LOWERTRACKVERT
; break;
640 if( nState
& ControlState::PRESSED
)
641 iState
= SCRBS_PRESSED
;
642 else if( !(nState
& ControlState::ENABLED
) )
643 iState
= SCRBS_DISABLED
;
644 else if( nState
& ControlState::ROLLOVER
)
647 iState
= SCRBS_NORMAL
;
648 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
652 if( nType
== ControlType::SpinButtons
&& nPart
== ControlPart::AllButtons
)
654 if( aValue
.getType() == ControlType::SpinButtons
)
656 const SpinbuttonValue
* pValue
= (aValue
.getType() == ControlType::SpinButtons
) ? static_cast<const SpinbuttonValue
*>(&aValue
) : nullptr;
659 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
660 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
664 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
665 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
671 if( nType
== ControlType::Spinbox
)
673 if( nPart
== ControlPart::AllButtons
)
675 if( aValue
.getType() == ControlType::SpinButtons
)
677 const SpinbuttonValue
*pValue
= static_cast<const SpinbuttonValue
*>(&aValue
);
680 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
681 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
685 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
686 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
693 if( nPart
== ControlPart::ButtonDown
)
696 if( nState
& ControlState::PRESSED
)
697 iState
= DNS_PRESSED
;
698 else if( !(nState
& ControlState::ENABLED
) )
699 iState
= DNS_DISABLED
;
700 else if( nState
& ControlState::ROLLOVER
)
705 if( nPart
== ControlPart::ButtonUp
)
708 if( nState
& ControlState::PRESSED
)
709 iState
= UPS_PRESSED
;
710 else if( !(nState
& ControlState::ENABLED
) )
711 iState
= UPS_DISABLED
;
712 else if( nState
& ControlState::ROLLOVER
)
717 if( nPart
== ControlPart::ButtonRight
)
719 iPart
= SPNP_DOWNHORZ
;
720 if( nState
& ControlState::PRESSED
)
721 iState
= DNHZS_PRESSED
;
722 else if( !(nState
& ControlState::ENABLED
) )
723 iState
= DNHZS_DISABLED
;
724 else if( nState
& ControlState::ROLLOVER
)
727 iState
= DNHZS_NORMAL
;
729 if( nPart
== ControlPart::ButtonLeft
)
732 if( nState
& ControlState::PRESSED
)
733 iState
= UPHZS_PRESSED
;
734 else if( !(nState
& ControlState::ENABLED
) )
735 iState
= UPHZS_DISABLED
;
736 else if( nState
& ControlState::ROLLOVER
)
739 iState
= UPHZS_NORMAL
;
741 if( nPart
== ControlPart::ButtonLeft
|| nPart
== ControlPart::ButtonRight
|| nPart
== ControlPart::ButtonUp
|| nPart
== ControlPart::ButtonDown
)
742 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
744 if( nType
== ControlType::Combobox
)
746 if( nPart
== ControlPart::ButtonDown
)
748 iPart
= CP_DROPDOWNBUTTON
;
749 if( nState
& ControlState::PRESSED
)
750 iState
= CBXS_PRESSED
;
751 else if( !(nState
& ControlState::ENABLED
) )
752 iState
= CBXS_DISABLED
;
753 else if( nState
& ControlState::ROLLOVER
)
756 iState
= CBXS_NORMAL
;
757 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
760 if( nType
== ControlType::Pushbutton
)
762 iPart
= BP_PUSHBUTTON
;
763 if( nState
& ControlState::PRESSED
)
764 iState
= PBS_PRESSED
;
765 else if( !(nState
& ControlState::ENABLED
) )
766 iState
= PBS_DISABLED
;
767 else if( nState
& ControlState::ROLLOVER
)
769 else if( nState
& ControlState::DEFAULT
)
770 iState
= PBS_DEFAULTED
;
771 //else if( nState & ControlState::FOCUSED )
772 // iState = PBS_DEFAULTED; // may need to draw focus rect
776 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
779 if( nType
== ControlType::Radiobutton
)
781 iPart
= BP_RADIOBUTTON
;
782 bool bChecked
= ( aValue
.getTristateVal() == ButtonValue::On
);
784 if( nState
& ControlState::PRESSED
)
785 iState
= bChecked
? RBS_CHECKEDPRESSED
: RBS_UNCHECKEDPRESSED
;
786 else if( !(nState
& ControlState::ENABLED
) )
787 iState
= bChecked
? RBS_CHECKEDDISABLED
: RBS_UNCHECKEDDISABLED
;
788 else if( nState
& ControlState::ROLLOVER
)
789 iState
= bChecked
? RBS_CHECKEDHOT
: RBS_UNCHECKEDHOT
;
791 iState
= bChecked
? RBS_CHECKEDNORMAL
: RBS_UNCHECKEDNORMAL
;
793 //if( nState & ControlState::FOCUSED )
794 // iState |= PBS_DEFAULTED; // may need to draw focus rect
796 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
799 if( nType
== ControlType::Checkbox
)
802 ButtonValue v
= aValue
.getTristateVal();
804 if( nState
& ControlState::PRESSED
)
805 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDPRESSED
:
806 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDPRESSED
: CBS_MIXEDPRESSED
);
807 else if( !(nState
& ControlState::ENABLED
) )
808 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDDISABLED
:
809 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDDISABLED
: CBS_MIXEDDISABLED
);
810 else if( nState
& ControlState::ROLLOVER
)
811 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDHOT
:
812 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDHOT
: CBS_MIXEDHOT
);
814 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDNORMAL
:
815 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDNORMAL
: CBS_MIXEDNORMAL
);
817 //if( nState & ControlState::FOCUSED )
818 // iState |= PBS_DEFAULTED; // may need to draw focus rect
821 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
822 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
824 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
827 if( ( nType
== ControlType::Editbox
) || ( nType
== ControlType::MultilineEditbox
) )
830 if( !(nState
& ControlState::ENABLED
) )
831 iState
= ETS_DISABLED
;
832 else if( nState
& ControlState::FOCUSED
)
833 iState
= ETS_FOCUSED
;
834 else if( nState
& ControlState::ROLLOVER
)
839 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
842 if( nType
== ControlType::Listbox
)
844 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
846 iPart
= LVP_EMPTYTEXT
; // ??? no idea which part to choose here
847 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
851 if( nType
== ControlType::TabPane
)
854 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
857 if( nType
== ControlType::TabBody
)
860 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
863 if( nType
== ControlType::TabItem
)
865 iPart
= TABP_TABITEMLEFTEDGE
;
868 OSL_ASSERT( aValue
.getType() == ControlType::TabItem
);
870 const TabitemValue
& rValue
= static_cast<const TabitemValue
&>(aValue
);
871 if (rValue
.isBothAligned())
873 iPart
= TABP_TABITEMLEFTEDGE
;
876 else if (rValue
.isLeftAligned())
877 iPart
= TABP_TABITEMLEFTEDGE
;
878 else if (rValue
.isRightAligned())
879 iPart
= TABP_TABITEMRIGHTEDGE
;
880 else iPart
= TABP_TABITEM
;
882 if( !(nState
& ControlState::ENABLED
) )
883 iState
= TILES_DISABLED
;
884 else if( nState
& ControlState::SELECTED
)
886 iState
= TILES_SELECTED
;
887 // increase the selected tab
889 if (rValue
.isBothAligned())
891 if (rValue
.isLeftAligned() || rValue
.isNotAligned())
893 if (rValue
.isRightAligned())
899 else if( nState
& ControlState::ROLLOVER
)
901 else if( nState
& ControlState::FOCUSED
)
902 iState
= TILES_FOCUSED
; // may need to draw focus rect
904 iState
= TILES_NORMAL
;
905 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
908 if( nType
== ControlType::Toolbar
)
910 if( nPart
== ControlPart::Button
)
913 bool bChecked
= ( aValue
.getTristateVal() == ButtonValue::On
);
914 if( !(nState
& ControlState::ENABLED
) )
915 //iState = TS_DISABLED;
916 // disabled buttons are typically not painted at all but we need visual
917 // feedback when travelling by keyboard over disabled entries
919 else if( nState
& ControlState::PRESSED
)
921 else if( nState
& ControlState::ROLLOVER
)
922 iState
= bChecked
? TS_HOTCHECKED
: TS_HOT
;
924 iState
= bChecked
? TS_CHECKED
: TS_NORMAL
;
925 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
927 else if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
929 // the vertical gripper is not supported in most themes and it makes no
930 // sense to only support horizontal gripper
931 //iPart = (nPart == ControlPart::ThumbHorz) ? RP_GRIPPERVERT : RP_GRIPPER;
932 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
934 else if( nPart
== ControlPart::DrawBackgroundHorz
|| nPart
== ControlPart::DrawBackgroundVert
)
936 if( aValue
.getType() == ControlType::Toolbar
)
938 const ToolbarValue
*pValue
= static_cast<const ToolbarValue
*>(&aValue
);
939 if( pValue
->mbIsTopDockingArea
)
940 rc
.top
= 0; // extend potential gradient to cover menu bar as well
943 // make it more compatible with Aero
944 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
946 impl_drawAeroToolbar( hDC
, rc
, nPart
== ControlPart::DrawBackgroundHorz
);
950 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
954 if( nType
== ControlType::Menubar
)
956 if( nPart
== ControlPart::Entire
)
958 if( aValue
.getType() == ControlType::Menubar
)
960 const MenubarValue
*pValue
= static_cast<const MenubarValue
*>(&aValue
);
961 rc
.bottom
+= pValue
->maTopDockingAreaHeight
; // extend potential gradient to cover docking area as well
963 // make it more compatible with Aero
964 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
966 impl_drawAeroToolbar( hDC
, rc
, true );
970 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
972 else if( nPart
== ControlPart::MenuItem
)
974 if( nState
& ControlState::ENABLED
)
976 if( nState
& ControlState::SELECTED
)
978 else if( nState
& ControlState::ROLLOVER
)
985 if( nState
& ControlState::SELECTED
)
986 iState
= MBI_DISABLEDPUSHED
;
987 else if( nState
& ControlState::ROLLOVER
)
988 iState
= MBI_DISABLEDHOT
;
990 iState
= MBI_DISABLED
;
992 return ImplDrawTheme( hTheme
, hDC
, MENU_BARITEM
, iState
, rc
, aCaption
);
996 if( nType
== ControlType::Progress
)
998 if( nPart
!= ControlPart::Entire
)
1001 if( ! ImplDrawTheme( hTheme
, hDC
, PP_BAR
, iState
, rc
, aCaption
) )
1003 RECT aProgressRect
= rc
;
1004 if( vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, PP_BAR
, iState
, &rc
, &aProgressRect
) != S_OK
)
1007 long nProgressWidth
= aValue
.getNumericVal();
1008 nProgressWidth
*= (aProgressRect
.right
- aProgressRect
.left
);
1009 nProgressWidth
/= (rc
.right
- rc
.left
);
1010 if( AllSettings::GetLayoutRTL() )
1011 aProgressRect
.left
= aProgressRect
.right
- nProgressWidth
;
1013 aProgressRect
.right
= aProgressRect
.left
+ nProgressWidth
;
1015 return ImplDrawTheme( hTheme
, hDC
, PP_CHUNK
, iState
, aProgressRect
, aCaption
);
1018 if( nType
== ControlType::Slider
)
1020 iPart
= (nPart
== ControlPart::TrackHorzArea
) ? TKP_TRACK
: TKP_TRACKVERT
;
1021 iState
= (nPart
== ControlPart::TrackHorzArea
) ? static_cast<int>(TRS_NORMAL
) : static_cast<int>(TRVS_NORMAL
);
1023 tools::Rectangle aTrackRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, tools::Rectangle() );
1025 if( nPart
== ControlPart::TrackHorzArea
)
1027 long nH
= aTrackRect
.GetHeight();
1028 aTRect
.top
+= (rc
.bottom
- rc
.top
- nH
)/2;
1029 aTRect
.bottom
= aTRect
.top
+ nH
;
1033 long nW
= aTrackRect
.GetWidth();
1034 aTRect
.left
+= (rc
.right
- rc
.left
- nW
)/2;
1035 aTRect
.right
= aTRect
.left
+ nW
;
1037 ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aTRect
, aCaption
);
1040 OSL_ASSERT( aValue
.getType() == ControlType::Slider
);
1041 const SliderValue
* pVal
= static_cast<const SliderValue
*>(&aValue
);
1042 aThumbRect
.left
= pVal
->maThumbRect
.Left();
1043 aThumbRect
.top
= pVal
->maThumbRect
.Top();
1044 aThumbRect
.right
= pVal
->maThumbRect
.Right();
1045 aThumbRect
.bottom
= pVal
->maThumbRect
.Bottom();
1046 iPart
= (nPart
== ControlPart::TrackHorzArea
) ? TKP_THUMB
: TKP_THUMBVERT
;
1047 iState
= (nState
& ControlState::ENABLED
) ? TUS_NORMAL
: TUS_DISABLED
;
1048 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aThumbRect
, aCaption
);
1051 if( nType
== ControlType::ListNode
)
1053 if( nPart
!= ControlPart::Entire
)
1056 ButtonValue aButtonValue
= aValue
.getTristateVal();
1058 switch( aButtonValue
)
1060 case ButtonValue::On
:
1061 iState
= GLPS_OPENED
;
1063 case ButtonValue::Off
:
1064 iState
= GLPS_CLOSED
;
1069 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
1072 if( GetSalData()->mbThemeMenuSupport
)
1074 if( nType
== ControlType::MenuPopup
)
1076 if( nPart
== ControlPart::Entire
)
1078 RECT aGutterRC
= rc
;
1079 if( AllSettings::GetLayoutRTL() )
1081 aGutterRC
.right
-= aValue
.getNumericVal()+1;
1082 aGutterRC
.left
= aGutterRC
.right
-3;
1086 aGutterRC
.left
+= aValue
.getNumericVal();
1087 aGutterRC
.right
= aGutterRC
.left
+3;
1090 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPBACKGROUND
, 0, rc
, aCaption
) &&
1091 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPGUTTER
, 0, aGutterRC
, aCaption
)
1094 else if( nPart
== ControlPart::MenuItem
)
1096 if( nState
& ControlState::ENABLED
)
1097 iState
= (nState
& ControlState::SELECTED
) ? MPI_HOT
: MPI_NORMAL
;
1099 iState
= (nState
& ControlState::SELECTED
) ? MPI_DISABLEDHOT
: MPI_DISABLED
;
1100 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPITEM
, iState
, rc
, aCaption
);
1102 else if( nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
1104 if( nState
& ControlState::PRESSED
)
1107 if( aValue
.getType() == ControlType::MenuPopup
)
1109 tools::Rectangle aRectangle
= GetMenuPopupMarkRegion(aValue
);
1110 aBGRect
.top
= aRectangle
.Top();
1111 aBGRect
.left
= aRectangle
.Left();
1112 aBGRect
.bottom
= aRectangle
.Bottom();
1113 aBGRect
.right
= aRectangle
.Right();
1116 iState
= (nState
& ControlState::ENABLED
) ? MCB_NORMAL
: MCB_DISABLED
;
1117 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECKBACKGROUND
, iState
, aBGRect
, aCaption
);
1118 if( nPart
== ControlPart::MenuItemCheckMark
)
1119 iState
= (nState
& ControlState::ENABLED
) ? MC_CHECKMARKNORMAL
: MC_CHECKMARKDISABLED
;
1121 iState
= (nState
& ControlState::ENABLED
) ? MC_BULLETNORMAL
: MC_BULLETDISABLED
;
1122 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECK
, iState
, rc
, aCaption
);
1125 return true; // unchecked: do nothing
1127 else if( nPart
== ControlPart::Separator
)
1129 // adjust for gutter position
1130 if( AllSettings::GetLayoutRTL() )
1131 rc
.right
-= aValue
.getNumericVal()+1;
1133 rc
.left
+= aValue
.getNumericVal()+1;
1134 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1135 MENU_POPUPSEPARATOR
, 0, tools::Rectangle( rc
.left
, rc
.top
, rc
.right
, rc
.bottom
) ) );
1136 // center the separator inside the passed rectangle
1137 long nDY
= ((rc
.bottom
- rc
.top
+ 1) - aRect
.GetHeight()) / 2;
1139 rc
.bottom
= rc
.top
+aRect
.GetHeight()-1;
1140 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPSEPARATOR
, 0, rc
, aCaption
);
1148 bool WinSalGraphics::drawNativeControl( ControlType nType
,
1150 const tools::Rectangle
& rControlRegion
,
1151 ControlState nState
,
1152 const ImplControlValue
& aValue
,
1153 const OUString
& aCaption
)
1156 HTHEME hTheme
= nullptr;
1158 tools::Rectangle buttonRect
= rControlRegion
;
1159 tools::Rectangle cacheRect
= rControlRegion
;
1160 Size keySize
= cacheRect
.GetSize();
1162 WinOpenGLSalGraphicsImpl
* pImpl
= dynamic_cast<WinOpenGLSalGraphicsImpl
*>(mpImpl
.get());
1164 // tdf#95618 - A few controls render outside the region they're given.
1165 if (pImpl
&& nType
== ControlType::TabItem
)
1167 tools::Rectangle rNativeBoundingRegion
;
1168 tools::Rectangle rNativeContentRegion
;
1169 if (getNativeControlRegion(nType
, nPart
, rControlRegion
, nState
, aValue
, aCaption
,
1170 rNativeBoundingRegion
, rNativeContentRegion
))
1172 cacheRect
= rNativeBoundingRegion
;
1173 keySize
= rNativeBoundingRegion
.GetSize();
1177 if (pImpl
&& nType
== ControlType::MenuPopup
&& (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
))
1179 tools::Rectangle aRectangle
= GetMenuPopupMarkRegion(aValue
);
1180 if (!aRectangle
.IsEmpty())
1182 cacheRect
= GetMenuPopupMarkRegion(aValue
);
1183 buttonRect
= cacheRect
;
1184 keySize
= cacheRect
.GetSize();
1189 ControlCacheKey
aControlCacheKey(nType
, nPart
, nState
, keySize
);
1190 if (pImpl
!= nullptr && pImpl
->TryRenderCachedNativeControl(aControlCacheKey
, buttonRect
.Left(), buttonRect
.Top()))
1197 case ControlType::Pushbutton
:
1198 case ControlType::Radiobutton
:
1199 case ControlType::Checkbox
:
1200 hTheme
= getThemeHandle( mhWnd
, L
"Button");
1202 case ControlType::Scrollbar
:
1203 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
1205 case ControlType::Combobox
:
1206 if( nPart
== ControlPart::Entire
)
1207 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1208 else if( nPart
== ControlPart::ButtonDown
)
1209 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1211 case ControlType::Spinbox
:
1212 if( nPart
== ControlPart::Entire
)
1213 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1215 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1217 case ControlType::SpinButtons
:
1218 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1220 case ControlType::Editbox
:
1221 case ControlType::MultilineEditbox
:
1222 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1224 case ControlType::Listbox
:
1225 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
1226 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
1227 else if( nPart
== ControlPart::ButtonDown
)
1228 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1230 case ControlType::TabPane
:
1231 case ControlType::TabBody
:
1232 case ControlType::TabItem
:
1233 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
1235 case ControlType::Toolbar
:
1236 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::Button
)
1237 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1239 // use rebar for grip and background
1240 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1242 case ControlType::Menubar
:
1243 if( nPart
== ControlPart::Entire
)
1244 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1245 else if( GetSalData()->mbThemeMenuSupport
)
1247 if( nPart
== ControlPart::MenuItem
)
1248 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1251 case ControlType::Progress
:
1252 if( nPart
== ControlPart::Entire
)
1253 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1255 case ControlType::ListNode
:
1256 if( nPart
== ControlPart::Entire
)
1257 hTheme
= getThemeHandle( mhWnd
, L
"TreeView");
1259 case ControlType::Slider
:
1260 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
1261 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
1263 case ControlType::MenuPopup
:
1264 if( GetSalData()->mbThemeMenuSupport
)
1266 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::MenuItem
||
1267 nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
||
1268 nPart
== ControlPart::Separator
1270 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1282 rc
.left
= buttonRect
.Left();
1283 rc
.right
= buttonRect
.Right()+1;
1284 rc
.top
= buttonRect
.Top();
1285 rc
.bottom
= buttonRect
.Bottom()+1;
1287 OUString
aCaptionStr(aCaption
.replace('~', '&')); // translate mnemonics
1289 if (pImpl
== nullptr)
1291 // set default text alignment
1292 int ta
= SetTextAlign(getHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1294 bOk
= ImplDrawNativeControl(getHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
);
1296 // restore alignment
1297 SetTextAlign(getHDC(), ta
);
1302 OpenGLCompatibleDC
aBlackDC(*this, cacheRect
.Left(), cacheRect
.Top(), cacheRect
.GetWidth()+1, cacheRect
.GetHeight()+1);
1303 SetTextAlign(aBlackDC
.getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1304 aBlackDC
.fill(RGB(0, 0, 0));
1306 OpenGLCompatibleDC
aWhiteDC(*this, cacheRect
.Left(), cacheRect
.Top(), cacheRect
.GetWidth()+1, cacheRect
.GetHeight()+1);
1307 SetTextAlign(aWhiteDC
.getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1308 aWhiteDC
.fill(RGB(0xff, 0xff, 0xff));
1310 if (ImplDrawNativeControl(aBlackDC
.getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
) &&
1311 ImplDrawNativeControl(aWhiteDC
.getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
))
1313 bOk
= pImpl
->RenderAndCacheNativeControl(aWhiteDC
, aBlackDC
, cacheRect
.Left(), cacheRect
.Top(), aControlCacheKey
);
1320 bool WinSalGraphics::getNativeControlRegion( ControlType nType
,
1322 const tools::Rectangle
& rControlRegion
,
1323 ControlState nState
,
1324 const ImplControlValue
& rControlValue
,
1326 tools::Rectangle
&rNativeBoundingRegion
,
1327 tools::Rectangle
&rNativeContentRegion
)
1331 // FIXME: rNativeBoundingRegion has a different origin
1332 // depending on which part is used; horrors.
1334 HDC hDC
= GetDC( mhWnd
);
1335 if( nType
== ControlType::Toolbar
)
1337 if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
1340 // the vertical gripper is not supported in most themes and it makes no
1341 // sense to only support horizontal gripper
1343 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1346 tools::Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == ControlPart::ThumbHorz ? RP_GRIPPERVERT : RP_GRIPPER,
1347 0, rControlRegion.GetBoundRect() ) );
1348 if( nPart == ControlPart::ThumbHorz && !aRect.IsEmpty() )
1350 tools::Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1351 rNativeContentRegion = aVertRect;
1354 rNativeContentRegion = aRect;
1355 rNativeBoundingRegion = rNativeContentRegion;
1356 if( !rNativeContentRegion.IsEmpty() )
1361 if( nPart
== ControlPart::Button
)
1363 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1366 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, TP_SPLITBUTTONDROPDOWN
,
1367 TS_HOT
, rControlRegion
) );
1368 rNativeContentRegion
= aRect
;
1369 rNativeBoundingRegion
= rNativeContentRegion
;
1370 if( !rNativeContentRegion
.IsEmpty() )
1375 if( nType
== ControlType::Progress
&& nPart
== ControlPart::Entire
)
1377 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1380 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, PP_BAR
,
1381 0, rControlRegion
) );
1382 rNativeContentRegion
= aRect
;
1383 rNativeBoundingRegion
= rNativeContentRegion
;
1384 if( !rNativeContentRegion
.IsEmpty() )
1388 if( (nType
== ControlType::Listbox
|| nType
== ControlType::Combobox
) && nPart
== ControlPart::Entire
)
1390 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1393 tools::Rectangle
aBoxRect( rControlRegion
);
1394 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, CP_DROPDOWNBUTTON
,
1395 CBXS_NORMAL
, aBoxRect
) );
1396 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1397 aBoxRect
.SetBottom( aBoxRect
.Top() + aRect
.GetHeight() );
1398 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1399 aBoxRect
.SetRight( aBoxRect
.Left() + aRect
.GetWidth() );
1400 rNativeContentRegion
= aBoxRect
;
1401 rNativeBoundingRegion
= rNativeContentRegion
;
1402 if( !aRect
.IsEmpty() )
1407 if( (nType
== ControlType::Editbox
|| nType
== ControlType::Spinbox
) && nPart
== ControlPart::Entire
)
1409 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1413 tools::Rectangle
aBoxRect( rControlRegion
);
1414 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, EP_BACKGROUNDWITHBORDER
,
1415 EBWBS_HOT
, aBoxRect
) );
1416 // ad app font height
1417 NONCLIENTMETRICSW aNonClientMetrics
;
1418 aNonClientMetrics
.cbSize
= sizeof( aNonClientMetrics
);
1419 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS
, sizeof( aNonClientMetrics
), &aNonClientMetrics
, 0 ) )
1421 long nFontHeight
= aNonClientMetrics
.lfMessageFont
.lfHeight
;
1422 if( nFontHeight
< 0 )
1423 nFontHeight
= -nFontHeight
;
1425 if( aRect
.GetHeight() && nFontHeight
)
1427 aRect
.AdjustBottom(aRect
.GetHeight());
1428 aRect
.AdjustBottom(nFontHeight
);
1429 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1430 aBoxRect
.SetBottom( aBoxRect
.Top() + aRect
.GetHeight() );
1431 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1432 aBoxRect
.SetRight( aBoxRect
.Left() + aRect
.GetWidth() );
1433 rNativeContentRegion
= aBoxRect
;
1434 rNativeBoundingRegion
= rNativeContentRegion
;
1441 if( GetSalData()->mbThemeMenuSupport
)
1443 if( nType
== ControlType::MenuPopup
)
1445 if( nPart
== ControlPart::MenuItemCheckMark
||
1446 nPart
== ControlPart::MenuItemRadioMark
)
1448 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Menu");
1449 tools::Rectangle
aBoxRect( rControlRegion
);
1450 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1454 if( aBoxRect
.GetWidth() && aBoxRect
.GetHeight() )
1456 rNativeContentRegion
= aRect
;
1457 rNativeBoundingRegion
= rNativeContentRegion
;
1464 if( nType
== ControlType::Slider
&& ( (nPart
== ControlPart::ThumbHorz
) || (nPart
== ControlPart::ThumbVert
) ) )
1466 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Trackbar");
1469 int iPart
= (nPart
== ControlPart::ThumbHorz
) ? TKP_THUMB
: TKP_THUMBVERT
;
1470 int iState
= (nPart
== ControlPart::ThumbHorz
) ? static_cast<int>(TUS_NORMAL
) : static_cast<int>(TUVS_NORMAL
);
1471 tools::Rectangle aThumbRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, tools::Rectangle() );
1472 if( nPart
== ControlPart::ThumbHorz
)
1474 long nW
= aThumbRect
.GetWidth();
1475 tools::Rectangle
aRect( rControlRegion
);
1476 aRect
.SetRight( aRect
.Left() + nW
- 1 );
1477 rNativeContentRegion
= aRect
;
1478 rNativeBoundingRegion
= rNativeContentRegion
;
1482 long nH
= aThumbRect
.GetHeight();
1483 tools::Rectangle
aRect( rControlRegion
);
1484 aRect
.SetBottom( aRect
.Top() + nH
- 1 );
1485 rNativeContentRegion
= aRect
;
1486 rNativeBoundingRegion
= rNativeContentRegion
;
1492 if ( ( nType
== ControlType::TabItem
) && ( nPart
== ControlPart::Entire
) )
1494 tools::Rectangle
aControlRect( rControlRegion
);
1495 rNativeContentRegion
= aControlRect
;
1497 aControlRect
.AdjustBottom(-1);
1499 if( rControlValue
.getType() == ControlType::TabItem
)
1501 const TabitemValue
& rValue
= static_cast<const TabitemValue
&>(rControlValue
);
1502 if (rValue
.isBothAligned())
1503 aControlRect
.AdjustRight(-1);
1505 if ( nState
& ControlState::SELECTED
)
1507 aControlRect
.AdjustLeft(-2);
1508 if (!rValue
.isBothAligned())
1510 if (rValue
.isLeftAligned() || rValue
.isNotAligned())
1511 aControlRect
.AdjustRight(2);
1512 if (rValue
.isRightAligned())
1513 aControlRect
.AdjustRight(1);
1515 aControlRect
.AdjustTop(-2);
1516 aControlRect
.AdjustBottom(2);
1519 rNativeBoundingRegion
= aControlRect
;
1523 ReleaseDC( mhWnd
, hDC
);
1527 void WinSalGraphics::updateSettingsNative( AllSettings
& rSettings
)
1529 if ( !vsAPI
.IsThemeActive() )
1532 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1533 ImplSVData
* pSVData
= ImplGetSVData();
1535 // don't draw frame around each and every toolbar
1536 pSVData
->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1538 // FIXME get the color directly from the theme, not from the settings
1539 Color aMenuBarTextColor
= aStyleSettings
.GetPersonaMenuBarTextColor().get_value_or( aStyleSettings
.GetMenuTextColor() );
1540 // in aero menuitem highlight text is drawn in the same color as normal
1541 aStyleSettings
.SetMenuHighlightTextColor( aStyleSettings
.GetMenuTextColor() );
1542 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuBarTextColor
);
1543 aStyleSettings
.SetMenuBarHighlightTextColor( aMenuBarTextColor
);
1544 pSVData
->maNWFData
.mnMenuFormatBorderX
= 2;
1545 pSVData
->maNWFData
.mnMenuFormatBorderY
= 2;
1546 pSVData
->maNWFData
.maMenuBarHighlightTextColor
= aMenuBarTextColor
;
1547 GetSalData()->mbThemeMenuSupport
= true;
1549 rSettings
.SetStyleSettings( aStyleSettings
);
1552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */