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>
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 *****************************************************/
72 typedef HTHEME (WINAPI
* OpenThemeData_Proc_T
) ( HWND hwnd
, LPCWSTR pszClassList
);
73 typedef HRESULT (WINAPI
* CloseThemeData_Proc_T
) ( HTHEME hTheme
);
74 typedef HRESULT (WINAPI
* GetThemeBackgroundContentRect_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
75 typedef HRESULT (WINAPI
* DrawThemeBackground_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
76 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
);
77 typedef HRESULT (WINAPI
* GetThemePartSize_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
78 typedef BOOL (WINAPI
* IsThemeActive_Proc_T
) ( void );
80 OpenThemeData_Proc_T lpfnOpenThemeData
;
81 CloseThemeData_Proc_T lpfnCloseThemeData
;
82 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect
;
83 DrawThemeBackground_Proc_T lpfnDrawThemeBackground
;
84 DrawThemeText_Proc_T lpfnDrawThemeText
;
85 GetThemePartSize_Proc_T lpfnGetThemePartSize
;
86 IsThemeActive_Proc_T lpfnIsThemeActive
;
94 HTHEME
OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
);
95 HRESULT
CloseThemeData( HTHEME hTheme
);
96 HRESULT
GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
97 HRESULT
DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
98 HRESULT
DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
);
99 HRESULT
GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
100 bool IsThemeActive();
105 static VisualStylesAPI vsAPI
;
107 VisualStylesAPI::VisualStylesAPI()
108 : lpfnOpenThemeData( nullptr ),
109 lpfnCloseThemeData( nullptr ),
110 lpfnGetThemeBackgroundContentRect( nullptr ),
111 lpfnDrawThemeBackground( nullptr ),
112 lpfnDrawThemeText( nullptr ),
113 lpfnGetThemePartSize( nullptr ),
114 lpfnIsThemeActive( nullptr )
116 OUString
aLibraryName( "uxtheme.dll" );
117 mhModule
= osl_loadModule( aLibraryName
.pData
, SAL_LOADMODULE_DEFAULT
);
121 lpfnOpenThemeData
= reinterpret_cast<OpenThemeData_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "OpenThemeData" ));
122 lpfnCloseThemeData
= reinterpret_cast<CloseThemeData_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "CloseThemeData" ));
123 lpfnGetThemeBackgroundContentRect
= reinterpret_cast<GetThemeBackgroundContentRect_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "GetThemeBackgroundContentRect" ));
124 lpfnDrawThemeBackground
= reinterpret_cast<DrawThemeBackground_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeBackground" ));
125 lpfnDrawThemeText
= reinterpret_cast<DrawThemeText_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeText" ));
126 lpfnGetThemePartSize
= reinterpret_cast<GetThemePartSize_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "GetThemePartSize" ));
127 lpfnIsThemeActive
= reinterpret_cast<IsThemeActive_Proc_T
>(osl_getAsciiFunctionSymbol( mhModule
, "IsThemeActive" ));
131 VisualStylesAPI::~VisualStylesAPI()
134 osl_unloadModule( mhModule
);
137 HTHEME
VisualStylesAPI::OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
)
139 if(lpfnOpenThemeData
)
140 return (*lpfnOpenThemeData
) (hwnd
, pszClassList
);
145 HRESULT
VisualStylesAPI::CloseThemeData( HTHEME hTheme
)
147 if(lpfnCloseThemeData
)
148 return (*lpfnCloseThemeData
) (hTheme
);
153 HRESULT
VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
)
155 if(lpfnGetThemeBackgroundContentRect
)
156 return (*lpfnGetThemeBackgroundContentRect
) ( hTheme
, hdc
, iPartId
, iStateId
, pBoundingRect
, pContentRect
);
161 HRESULT
VisualStylesAPI::DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
)
163 if(lpfnDrawThemeBackground
)
164 return (*lpfnDrawThemeBackground
) (hTheme
, hdc
, iPartId
, iStateId
, pRect
, pClipRect
);
169 HRESULT
VisualStylesAPI::DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
)
171 if(lpfnDrawThemeText
)
172 return (*lpfnDrawThemeText
) (hTheme
, hdc
, iPartId
, iStateId
, pszText
, iCharCount
, dwTextFlags
, dwTextFlags2
, pRect
);
177 HRESULT
VisualStylesAPI::GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
)
179 if(lpfnGetThemePartSize
)
180 return (*lpfnGetThemePartSize
) (hTheme
, hdc
, iPartId
, iStateId
, prc
, eSize
, psz
);
185 bool VisualStylesAPI::IsThemeActive()
187 if(lpfnIsThemeActive
)
188 return (*lpfnIsThemeActive
) ();
193 /*********************************************************
194 * Initialize XP theming and local stuff
195 *********************************************************/
196 void SalData::initNWF()
198 ImplSVData
* pSVData
= ImplGetSVData();
200 // the menu bar and the top docking area should have a common background (gradient)
201 pSVData
->maNWFData
.mbMenuBarDockingAreaCommonBG
= true;
204 // *********************************************************
205 // * Release theming handles
206 // ********************************************************
207 void SalData::deInitNWF()
209 for( auto& rEntry
: aThemeMap
)
210 vsAPI
.CloseThemeData(rEntry
.second
);
214 static HTHEME
getThemeHandle( HWND hWnd
, LPCWSTR name
)
216 if( GetSalData()->mbThemeChanged
)
218 // throw away invalid theme handles
219 SalData::deInitNWF();
220 GetSalData()->mbThemeChanged
= false;
223 ThemeMap::iterator iter
;
224 if( (iter
= aThemeMap
.find( name
)) != aThemeMap
.end() )
226 // theme not found -> add it to map
227 HTHEME hTheme
= vsAPI
.OpenThemeData( hWnd
, name
);
228 if( hTheme
!= nullptr )
229 aThemeMap
[name
] = hTheme
;
233 bool WinSalGraphics::isNativeControlSupported( ControlType nType
, ControlPart nPart
)
235 HTHEME hTheme
= nullptr;
239 case ControlType::Pushbutton
:
240 case ControlType::Radiobutton
:
241 case ControlType::Checkbox
:
242 if( nPart
== ControlPart::Entire
)
243 hTheme
= getThemeHandle( mhWnd
, L
"Button");
245 case ControlType::Scrollbar
:
246 if( nPart
== ControlPart::DrawBackgroundHorz
|| nPart
== ControlPart::DrawBackgroundVert
)
247 return false; // no background painting needed
248 if( nPart
== ControlPart::Entire
)
249 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
251 case ControlType::Combobox
:
252 if( nPart
== ControlPart::HasBackgroundTexture
)
253 return false; // we do not paint the inner part (ie the selection background/focus indication)
254 if( nPart
== ControlPart::Entire
)
255 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
256 else if( nPart
== ControlPart::ButtonDown
)
257 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
259 case ControlType::Spinbox
:
260 if( nPart
== ControlPart::Entire
)
261 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
262 else if( nPart
== ControlPart::AllButtons
||
263 nPart
== ControlPart::ButtonUp
|| nPart
== ControlPart::ButtonDown
||
264 nPart
== ControlPart::ButtonLeft
|| nPart
== ControlPart::ButtonRight
)
265 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
267 case ControlType::SpinButtons
:
268 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::AllButtons
)
269 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
271 case ControlType::Editbox
:
272 case ControlType::MultilineEditbox
:
273 if( nPart
== ControlPart::HasBackgroundTexture
)
274 return false; // we do not paint the inner part (ie the selection background/focus indication)
276 if( nPart
== ControlPart::Entire
)
277 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
279 case ControlType::Listbox
:
280 if( nPart
== ControlPart::HasBackgroundTexture
)
281 return false; // we do not paint the inner part (ie the selection background/focus indication)
282 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
283 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
284 else if( nPart
== ControlPart::ButtonDown
)
285 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
287 case ControlType::TabPane
:
288 case ControlType::TabBody
:
289 case ControlType::TabItem
:
290 if( nPart
== ControlPart::Entire
)
291 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
293 case ControlType::Toolbar
:
294 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::Button
)
295 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
297 // use rebar theme for grip and background
298 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
300 case ControlType::Menubar
:
301 if( nPart
== ControlPart::Entire
)
302 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
303 else if( GetSalData()->mbThemeMenuSupport
)
305 if( nPart
== ControlPart::MenuItem
)
306 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
309 case ControlType::MenuPopup
:
310 if( GetSalData()->mbThemeMenuSupport
)
312 if( nPart
== ControlPart::Entire
||
313 nPart
== ControlPart::MenuItem
||
314 nPart
== ControlPart::MenuItemCheckMark
||
315 nPart
== ControlPart::MenuItemRadioMark
||
316 nPart
== ControlPart::Separator
)
317 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
320 case ControlType::Progress
:
321 if( nPart
== ControlPart::Entire
)
322 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
324 case ControlType::Slider
:
325 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
326 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
328 case ControlType::ListNode
:
329 if( nPart
== ControlPart::Entire
)
330 hTheme
= getThemeHandle( mhWnd
, L
"TreeView" );
337 return (hTheme
!= nullptr);
340 bool WinSalGraphics::hitTestNativeControl( ControlType
,
342 const tools::Rectangle
&,
349 static bool ImplDrawTheme( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, RECT rc
, const OUString
& aStr
)
351 HRESULT hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
353 if( aStr
.getLength() )
356 hr
= vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, iPart
, iState
, &rc
, &rcContent
);
357 hr
= vsAPI
.DrawThemeText( hTheme
, hDC
, iPart
, iState
,
358 o3tl::toW(aStr
.getStr()), -1,
359 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
,
365 static tools::Rectangle
ImplGetThemeRect( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, const tools::Rectangle
& /* aRect */, THEMESIZE eTS
= TS_TRUE
)
368 HRESULT hr
= vsAPI
.GetThemePartSize( hTheme
, hDC
, iPart
, iState
, nullptr, eTS
, &aSz
); // TS_TRUE returns optimal size
370 return tools::Rectangle( 0, 0, aSz
.cx
, aSz
.cy
);
372 return tools::Rectangle();
377 static void ImplConvertSpinbuttonValues( ControlPart nControlPart
, const ControlState
& rState
, const tools::Rectangle
& rRect
,
378 int* pLunaPart
, int *pLunaState
, RECT
*pRect
)
380 if( nControlPart
== ControlPart::ButtonDown
)
382 *pLunaPart
= SPNP_DOWN
;
383 if( rState
& ControlState::PRESSED
)
384 *pLunaState
= DNS_PRESSED
;
385 else if( !(rState
& ControlState::ENABLED
) )
386 *pLunaState
= DNS_DISABLED
;
387 else if( rState
& ControlState::ROLLOVER
)
388 *pLunaState
= DNS_HOT
;
390 *pLunaState
= DNS_NORMAL
;
392 if( nControlPart
== ControlPart::ButtonUp
)
394 *pLunaPart
= SPNP_UP
;
395 if( rState
& ControlState::PRESSED
)
396 *pLunaState
= UPS_PRESSED
;
397 else if( !(rState
& ControlState::ENABLED
) )
398 *pLunaState
= UPS_DISABLED
;
399 else if( rState
& ControlState::ROLLOVER
)
400 *pLunaState
= UPS_HOT
;
402 *pLunaState
= UPS_NORMAL
;
404 if( nControlPart
== ControlPart::ButtonRight
)
406 *pLunaPart
= SPNP_UPHORZ
;
407 if( rState
& ControlState::PRESSED
)
408 *pLunaState
= DNHZS_PRESSED
;
409 else if( !(rState
& ControlState::ENABLED
) )
410 *pLunaState
= DNHZS_DISABLED
;
411 else if( rState
& ControlState::ROLLOVER
)
412 *pLunaState
= DNHZS_HOT
;
414 *pLunaState
= DNHZS_NORMAL
;
416 if( nControlPart
== ControlPart::ButtonLeft
)
418 *pLunaPart
= SPNP_DOWNHORZ
;
419 if( rState
& ControlState::PRESSED
)
420 *pLunaState
= UPHZS_PRESSED
;
421 else if( !(rState
& ControlState::ENABLED
) )
422 *pLunaState
= UPHZS_DISABLED
;
423 else if( rState
& ControlState::ROLLOVER
)
424 *pLunaState
= UPHZS_HOT
;
426 *pLunaState
= UPHZS_NORMAL
;
429 pRect
->left
= rRect
.Left();
430 pRect
->right
= rRect
.Right()+1;
431 pRect
->top
= rRect
.Top();
432 pRect
->bottom
= rRect
.Bottom()+1;
435 /// Draw an own toolbar style on Windows Vista or later, looks better there
436 static void impl_drawAeroToolbar( HDC hDC
, RECT rc
, bool bHorizontal
)
438 if ( rc
.top
== 0 && bHorizontal
)
440 const long GRADIENT_HEIGHT
= 32;
442 long gradient_break
= rc
.top
;
443 long gradient_bottom
= rc
.bottom
- 1;
444 GRADIENT_RECT g_rect
[1] = { { 0, 1 } };
446 // very slow gradient at the top (if we have space for that)
447 if ( gradient_bottom
- rc
.top
> GRADIENT_HEIGHT
)
449 gradient_break
= gradient_bottom
- GRADIENT_HEIGHT
;
451 TRIVERTEX vert
[2] = {
452 { rc
.left
, rc
.top
, 0xff00, 0xff00, 0xff00, 0xff00 },
453 { rc
.right
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
455 GdiGradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
458 // gradient at the bottom
459 TRIVERTEX vert
[2] = {
460 { rc
.left
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
461 { rc
.right
, gradient_bottom
, 0xf000, 0xf000, 0xf000, 0xff00 }
463 GdiGradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
465 // and a darker horizontal line under that
466 ScopedSelectedHPEN
hPen(hDC
, CreatePen(PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0)));
468 MoveToEx( hDC
, rc
.left
, gradient_bottom
, nullptr );
469 LineTo( hDC
, rc
.right
, gradient_bottom
);
473 ScopedHBRUSH
hbrush(CreateSolidBrush(RGB(0xf0, 0xf0, 0xf0)));
474 FillRect(hDC
, &rc
, hbrush
.get());
476 // darker line to distinguish the toolbar and viewshell
477 // it is drawn only for the horizontal toolbars; it did not look well
478 // when done for the vertical ones too
481 long from_x
, from_y
, to_x
, to_y
;
485 from_y
= to_y
= rc
.top
;
487 ScopedSelectedHPEN
hPen(hDC
, CreatePen(PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0)));
489 MoveToEx( hDC
, from_x
, from_y
, nullptr );
490 LineTo( hDC
, to_x
, to_y
);
496 * Gives the actual rectangle used for rendering by ControlType::MenuPopup's
497 * ControlPart::MenuItemCheckMark or ControlPart::MenuItemRadioMark.
499 static tools::Rectangle
GetMenuPopupMarkRegion(const ImplControlValue
& rValue
)
501 tools::Rectangle aRet
;
503 auto pMVal
= dynamic_cast<const MenupopupValue
*>(&rValue
);
507 aRet
.SetTop(pMVal
->maItemRect
.Top());
508 aRet
.SetBottom(pMVal
->maItemRect
.Bottom() + 1); // see below in drawNativeControl
509 if (AllSettings::GetLayoutRTL())
511 aRet
.SetRight(pMVal
->maItemRect
.Right() + 1);
512 aRet
.SetLeft(aRet
.Right() - (pMVal
->getNumericVal() - pMVal
->maItemRect
.Left()));
516 aRet
.SetRight(pMVal
->getNumericVal());
517 aRet
.SetLeft(pMVal
->maItemRect
.Left());
523 static bool ImplDrawNativeControl( HDC hDC
, HTHEME hTheme
, RECT rc
,
527 const ImplControlValue
& aValue
,
528 OUString
const & aCaption
)
530 // a listbox dropdown is actually a combobox dropdown
531 if( nType
== ControlType::Listbox
)
532 if( nPart
== ControlPart::ButtonDown
)
533 nType
= ControlType::Combobox
;
535 // draw entire combobox as a large edit box
536 if( nType
== ControlType::Combobox
)
537 if( nPart
== ControlPart::Entire
)
538 nType
= ControlType::Editbox
;
540 // draw entire spinbox as a large edit box
541 if( nType
== ControlType::Spinbox
)
542 if( nPart
== ControlPart::Entire
)
543 nType
= ControlType::Editbox
;
545 int iPart(0), iState(0);
546 if( nType
== ControlType::Scrollbar
)
549 if( nPart
== ControlPart::ButtonUp
)
551 iPart
= SBP_ARROWBTN
;
552 if( nState
& ControlState::PRESSED
)
553 iState
= ABS_UPPRESSED
;
554 else if( !(nState
& ControlState::ENABLED
) )
555 iState
= ABS_UPDISABLED
;
556 else if( nState
& ControlState::ROLLOVER
)
559 iState
= ABS_UPNORMAL
;
560 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
563 if( nPart
== ControlPart::ButtonDown
)
565 iPart
= SBP_ARROWBTN
;
566 if( nState
& ControlState::PRESSED
)
567 iState
= ABS_DOWNPRESSED
;
568 else if( !(nState
& ControlState::ENABLED
) )
569 iState
= ABS_DOWNDISABLED
;
570 else if( nState
& ControlState::ROLLOVER
)
571 iState
= ABS_DOWNHOT
;
573 iState
= ABS_DOWNNORMAL
;
574 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
577 if( nPart
== ControlPart::ButtonLeft
)
579 iPart
= SBP_ARROWBTN
;
580 if( nState
& ControlState::PRESSED
)
581 iState
= ABS_LEFTPRESSED
;
582 else if( !(nState
& ControlState::ENABLED
) )
583 iState
= ABS_LEFTDISABLED
;
584 else if( nState
& ControlState::ROLLOVER
)
585 iState
= ABS_LEFTHOT
;
587 iState
= ABS_LEFTNORMAL
;
588 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
591 if( nPart
== ControlPart::ButtonRight
)
593 iPart
= SBP_ARROWBTN
;
594 if( nState
& ControlState::PRESSED
)
595 iState
= ABS_RIGHTPRESSED
;
596 else if( !(nState
& ControlState::ENABLED
) )
597 iState
= ABS_RIGHTDISABLED
;
598 else if( nState
& ControlState::ROLLOVER
)
599 iState
= ABS_RIGHTHOT
;
601 iState
= ABS_RIGHTNORMAL
;
602 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
605 if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
607 iPart
= (nPart
== ControlPart::ThumbHorz
) ? SBP_THUMBBTNHORZ
: SBP_THUMBBTNVERT
;
608 if( nState
& ControlState::PRESSED
)
609 iState
= SCRBS_PRESSED
;
610 else if( !(nState
& ControlState::ENABLED
) )
611 iState
= SCRBS_DISABLED
;
612 else if( nState
& ControlState::ROLLOVER
)
615 iState
= SCRBS_NORMAL
;
618 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_MIN
, &sz
);
619 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_TRUE
, &sz
);
620 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, nullptr, TS_DRAW
, &sz
);
622 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
623 // paint gripper on thumb if enough space
624 if( ( (nPart
== ControlPart::ThumbVert
) && (rc
.bottom
-rc
.top
> 12) ) ||
625 ( (nPart
== ControlPart::ThumbHorz
) && (rc
.right
-rc
.left
> 12) ) )
627 iPart
= (nPart
== ControlPart::ThumbHorz
) ? SBP_GRIPPERHORZ
: SBP_GRIPPERVERT
;
629 vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
633 if( nPart
== ControlPart::TrackHorzLeft
|| nPart
== ControlPart::TrackHorzRight
|| nPart
== ControlPart::TrackVertUpper
|| nPart
== ControlPart::TrackVertLower
)
637 case ControlPart::TrackHorzLeft
: iPart
= SBP_UPPERTRACKHORZ
; break;
638 case ControlPart::TrackHorzRight
: iPart
= SBP_LOWERTRACKHORZ
; break;
639 case ControlPart::TrackVertUpper
: iPart
= SBP_UPPERTRACKVERT
; break;
640 case ControlPart::TrackVertLower
: iPart
= SBP_LOWERTRACKVERT
; break;
644 if( nState
& ControlState::PRESSED
)
645 iState
= SCRBS_PRESSED
;
646 else if( !(nState
& ControlState::ENABLED
) )
647 iState
= SCRBS_DISABLED
;
648 else if( nState
& ControlState::ROLLOVER
)
651 iState
= SCRBS_NORMAL
;
652 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, nullptr);
656 if( nType
== ControlType::SpinButtons
&& nPart
== ControlPart::AllButtons
)
658 if( aValue
.getType() == ControlType::SpinButtons
)
660 const SpinbuttonValue
* pValue
= (aValue
.getType() == ControlType::SpinButtons
) ? static_cast<const SpinbuttonValue
*>(&aValue
) : nullptr;
663 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
664 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
668 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
669 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
675 if( nType
== ControlType::Spinbox
)
677 if( nPart
== ControlPart::AllButtons
)
679 if( aValue
.getType() == ControlType::SpinButtons
)
681 const SpinbuttonValue
*pValue
= static_cast<const SpinbuttonValue
*>(&aValue
);
684 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
685 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
689 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
690 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
697 if( nPart
== ControlPart::ButtonDown
)
700 if( nState
& ControlState::PRESSED
)
701 iState
= DNS_PRESSED
;
702 else if( !(nState
& ControlState::ENABLED
) )
703 iState
= DNS_DISABLED
;
704 else if( nState
& ControlState::ROLLOVER
)
709 if( nPart
== ControlPart::ButtonUp
)
712 if( nState
& ControlState::PRESSED
)
713 iState
= UPS_PRESSED
;
714 else if( !(nState
& ControlState::ENABLED
) )
715 iState
= UPS_DISABLED
;
716 else if( nState
& ControlState::ROLLOVER
)
721 if( nPart
== ControlPart::ButtonRight
)
723 iPart
= SPNP_DOWNHORZ
;
724 if( nState
& ControlState::PRESSED
)
725 iState
= DNHZS_PRESSED
;
726 else if( !(nState
& ControlState::ENABLED
) )
727 iState
= DNHZS_DISABLED
;
728 else if( nState
& ControlState::ROLLOVER
)
731 iState
= DNHZS_NORMAL
;
733 if( nPart
== ControlPart::ButtonLeft
)
736 if( nState
& ControlState::PRESSED
)
737 iState
= UPHZS_PRESSED
;
738 else if( !(nState
& ControlState::ENABLED
) )
739 iState
= UPHZS_DISABLED
;
740 else if( nState
& ControlState::ROLLOVER
)
743 iState
= UPHZS_NORMAL
;
745 if( nPart
== ControlPart::ButtonLeft
|| nPart
== ControlPart::ButtonRight
|| nPart
== ControlPart::ButtonUp
|| nPart
== ControlPart::ButtonDown
)
746 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
748 if( nType
== ControlType::Combobox
)
750 if( nPart
== ControlPart::ButtonDown
)
752 iPart
= CP_DROPDOWNBUTTON
;
753 if( nState
& ControlState::PRESSED
)
754 iState
= CBXS_PRESSED
;
755 else if( !(nState
& ControlState::ENABLED
) )
756 iState
= CBXS_DISABLED
;
757 else if( nState
& ControlState::ROLLOVER
)
760 iState
= CBXS_NORMAL
;
761 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
764 if( nType
== ControlType::Pushbutton
)
766 iPart
= BP_PUSHBUTTON
;
767 if( nState
& ControlState::PRESSED
)
768 iState
= PBS_PRESSED
;
769 else if( !(nState
& ControlState::ENABLED
) )
770 iState
= PBS_DISABLED
;
771 else if( nState
& ControlState::ROLLOVER
)
773 else if( nState
& ControlState::DEFAULT
)
774 iState
= PBS_DEFAULTED
;
775 //else if( nState & ControlState::FOCUSED )
776 // iState = PBS_DEFAULTED; // may need to draw focus rect
780 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
783 if( nType
== ControlType::Radiobutton
)
785 iPart
= BP_RADIOBUTTON
;
786 bool bChecked
= ( aValue
.getTristateVal() == ButtonValue::On
);
788 if( nState
& ControlState::PRESSED
)
789 iState
= bChecked
? RBS_CHECKEDPRESSED
: RBS_UNCHECKEDPRESSED
;
790 else if( !(nState
& ControlState::ENABLED
) )
791 iState
= bChecked
? RBS_CHECKEDDISABLED
: RBS_UNCHECKEDDISABLED
;
792 else if( nState
& ControlState::ROLLOVER
)
793 iState
= bChecked
? RBS_CHECKEDHOT
: RBS_UNCHECKEDHOT
;
795 iState
= bChecked
? RBS_CHECKEDNORMAL
: RBS_UNCHECKEDNORMAL
;
797 //if( nState & ControlState::FOCUSED )
798 // iState |= PBS_DEFAULTED; // may need to draw focus rect
800 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
803 if( nType
== ControlType::Checkbox
)
806 ButtonValue v
= aValue
.getTristateVal();
808 if( nState
& ControlState::PRESSED
)
809 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDPRESSED
:
810 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDPRESSED
: CBS_MIXEDPRESSED
);
811 else if( !(nState
& ControlState::ENABLED
) )
812 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDDISABLED
:
813 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDDISABLED
: CBS_MIXEDDISABLED
);
814 else if( nState
& ControlState::ROLLOVER
)
815 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDHOT
:
816 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDHOT
: CBS_MIXEDHOT
);
818 iState
= (v
== ButtonValue::On
) ? CBS_CHECKEDNORMAL
:
819 ( (v
== ButtonValue::Off
) ? CBS_UNCHECKEDNORMAL
: CBS_MIXEDNORMAL
);
821 //if( nState & ControlState::FOCUSED )
822 // iState |= PBS_DEFAULTED; // may need to draw focus rect
825 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
826 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
828 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
831 if( ( nType
== ControlType::Editbox
) || ( nType
== ControlType::MultilineEditbox
) )
834 if( !(nState
& ControlState::ENABLED
) )
835 iState
= ETS_DISABLED
;
836 else if( nState
& ControlState::FOCUSED
)
837 iState
= ETS_FOCUSED
;
838 else if( nState
& ControlState::ROLLOVER
)
843 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
846 if( nType
== ControlType::Listbox
)
848 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
850 iPart
= LVP_EMPTYTEXT
; // ??? no idea which part to choose here
851 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
855 if( nType
== ControlType::TabPane
)
858 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
861 if( nType
== ControlType::TabBody
)
864 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
867 if( nType
== ControlType::TabItem
)
869 iPart
= TABP_TABITEMLEFTEDGE
;
872 OSL_ASSERT( aValue
.getType() == ControlType::TabItem
);
874 const TabitemValue
& rValue
= static_cast<const TabitemValue
&>(aValue
);
875 if (rValue
.isBothAligned())
877 iPart
= TABP_TABITEMLEFTEDGE
;
880 else if (rValue
.isLeftAligned())
881 iPart
= TABP_TABITEMLEFTEDGE
;
882 else if (rValue
.isRightAligned())
883 iPart
= TABP_TABITEMRIGHTEDGE
;
884 else iPart
= TABP_TABITEM
;
886 if( !(nState
& ControlState::ENABLED
) )
887 iState
= TILES_DISABLED
;
888 else if( nState
& ControlState::SELECTED
)
890 iState
= TILES_SELECTED
;
891 // increase the selected tab
893 if (rValue
.isBothAligned())
895 if (rValue
.isLeftAligned() || rValue
.isNotAligned())
897 if (rValue
.isRightAligned())
903 else if( nState
& ControlState::ROLLOVER
)
905 else if( nState
& ControlState::FOCUSED
)
906 iState
= TILES_FOCUSED
; // may need to draw focus rect
908 iState
= TILES_NORMAL
;
909 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
912 if( nType
== ControlType::Toolbar
)
914 if( nPart
== ControlPart::Button
)
917 bool bChecked
= ( aValue
.getTristateVal() == ButtonValue::On
);
918 if( !(nState
& ControlState::ENABLED
) )
919 //iState = TS_DISABLED;
920 // disabled buttons are typically not painted at all but we need visual
921 // feedback when travelling by keyboard over disabled entries
923 else if( nState
& ControlState::PRESSED
)
925 else if( nState
& ControlState::ROLLOVER
)
926 iState
= bChecked
? TS_HOTCHECKED
: TS_HOT
;
928 iState
= bChecked
? TS_CHECKED
: TS_NORMAL
;
929 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
931 else if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
933 // the vertical gripper is not supported in most themes and it makes no
934 // sense to only support horizontal gripper
935 //iPart = (nPart == ControlPart::ThumbHorz) ? RP_GRIPPERVERT : RP_GRIPPER;
936 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
938 else if( nPart
== ControlPart::DrawBackgroundHorz
|| nPart
== ControlPart::DrawBackgroundVert
)
940 if( aValue
.getType() == ControlType::Toolbar
)
942 const ToolbarValue
*pValue
= static_cast<const ToolbarValue
*>(&aValue
);
943 if( pValue
->mbIsTopDockingArea
)
944 rc
.top
= 0; // extend potential gradient to cover menu bar as well
947 // make it more compatible with Aero
948 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
950 impl_drawAeroToolbar( hDC
, rc
, nPart
== ControlPart::DrawBackgroundHorz
);
954 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
958 if( nType
== ControlType::Menubar
)
960 if( nPart
== ControlPart::Entire
)
962 if( aValue
.getType() == ControlType::Menubar
)
964 const MenubarValue
*pValue
= static_cast<const MenubarValue
*>(&aValue
);
965 rc
.bottom
+= pValue
->maTopDockingAreaHeight
; // extend potential gradient to cover docking area as well
967 // make it more compatible with Aero
968 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
970 impl_drawAeroToolbar( hDC
, rc
, true );
974 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
976 else if( nPart
== ControlPart::MenuItem
)
978 if( nState
& ControlState::ENABLED
)
980 if( nState
& ControlState::SELECTED
)
982 else if( nState
& ControlState::ROLLOVER
)
989 if( nState
& ControlState::SELECTED
)
990 iState
= MBI_DISABLEDPUSHED
;
991 else if( nState
& ControlState::ROLLOVER
)
992 iState
= MBI_DISABLEDHOT
;
994 iState
= MBI_DISABLED
;
996 return ImplDrawTheme( hTheme
, hDC
, MENU_BARITEM
, iState
, rc
, aCaption
);
1000 if( nType
== ControlType::Progress
)
1002 if( nPart
!= ControlPart::Entire
)
1005 if( ! ImplDrawTheme( hTheme
, hDC
, PP_BAR
, iState
, rc
, aCaption
) )
1007 RECT aProgressRect
= rc
;
1008 if( vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, PP_BAR
, iState
, &rc
, &aProgressRect
) != S_OK
)
1011 long nProgressWidth
= aValue
.getNumericVal();
1012 nProgressWidth
*= (aProgressRect
.right
- aProgressRect
.left
);
1013 nProgressWidth
/= (rc
.right
- rc
.left
);
1014 if( AllSettings::GetLayoutRTL() )
1015 aProgressRect
.left
= aProgressRect
.right
- nProgressWidth
;
1017 aProgressRect
.right
= aProgressRect
.left
+ nProgressWidth
;
1019 return ImplDrawTheme( hTheme
, hDC
, PP_CHUNK
, iState
, aProgressRect
, aCaption
);
1022 if( nType
== ControlType::Slider
)
1024 iPart
= (nPart
== ControlPart::TrackHorzArea
) ? TKP_TRACK
: TKP_TRACKVERT
;
1025 iState
= (nPart
== ControlPart::TrackHorzArea
) ? static_cast<int>(TRS_NORMAL
) : static_cast<int>(TRVS_NORMAL
);
1027 tools::Rectangle aTrackRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, tools::Rectangle() );
1029 if( nPart
== ControlPart::TrackHorzArea
)
1031 long nH
= aTrackRect
.GetHeight();
1032 aTRect
.top
+= (rc
.bottom
- rc
.top
- nH
)/2;
1033 aTRect
.bottom
= aTRect
.top
+ nH
;
1037 long nW
= aTrackRect
.GetWidth();
1038 aTRect
.left
+= (rc
.right
- rc
.left
- nW
)/2;
1039 aTRect
.right
= aTRect
.left
+ nW
;
1041 ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aTRect
, aCaption
);
1044 OSL_ASSERT( aValue
.getType() == ControlType::Slider
);
1045 const SliderValue
* pVal
= static_cast<const SliderValue
*>(&aValue
);
1046 aThumbRect
.left
= pVal
->maThumbRect
.Left();
1047 aThumbRect
.top
= pVal
->maThumbRect
.Top();
1048 aThumbRect
.right
= pVal
->maThumbRect
.Right();
1049 aThumbRect
.bottom
= pVal
->maThumbRect
.Bottom();
1050 iPart
= (nPart
== ControlPart::TrackHorzArea
) ? TKP_THUMB
: TKP_THUMBVERT
;
1051 iState
= (nState
& ControlState::ENABLED
) ? TUS_NORMAL
: TUS_DISABLED
;
1052 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aThumbRect
, aCaption
);
1055 if( nType
== ControlType::ListNode
)
1057 if( nPart
!= ControlPart::Entire
)
1060 ButtonValue aButtonValue
= aValue
.getTristateVal();
1062 switch( aButtonValue
)
1064 case ButtonValue::On
:
1065 iState
= GLPS_OPENED
;
1067 case ButtonValue::Off
:
1068 iState
= GLPS_CLOSED
;
1073 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
1076 if( GetSalData()->mbThemeMenuSupport
)
1078 if( nType
== ControlType::MenuPopup
)
1080 if( nPart
== ControlPart::Entire
)
1082 RECT aGutterRC
= rc
;
1083 if( AllSettings::GetLayoutRTL() )
1085 aGutterRC
.right
-= aValue
.getNumericVal()+1;
1086 aGutterRC
.left
= aGutterRC
.right
-3;
1090 aGutterRC
.left
+= aValue
.getNumericVal();
1091 aGutterRC
.right
= aGutterRC
.left
+3;
1094 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPBACKGROUND
, 0, rc
, aCaption
) &&
1095 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPGUTTER
, 0, aGutterRC
, aCaption
)
1098 else if( nPart
== ControlPart::MenuItem
)
1100 if( nState
& ControlState::ENABLED
)
1101 iState
= (nState
& ControlState::SELECTED
) ? MPI_HOT
: MPI_NORMAL
;
1103 iState
= (nState
& ControlState::SELECTED
) ? MPI_DISABLEDHOT
: MPI_DISABLED
;
1104 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPITEM
, iState
, rc
, aCaption
);
1106 else if( nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
)
1108 if( nState
& ControlState::PRESSED
)
1111 if( aValue
.getType() == ControlType::MenuPopup
)
1113 tools::Rectangle aRectangle
= GetMenuPopupMarkRegion(aValue
);
1114 aBGRect
.top
= aRectangle
.Top();
1115 aBGRect
.left
= aRectangle
.Left();
1116 aBGRect
.bottom
= aRectangle
.Bottom();
1117 aBGRect
.right
= aRectangle
.Right();
1120 iState
= (nState
& ControlState::ENABLED
) ? MCB_NORMAL
: MCB_DISABLED
;
1121 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECKBACKGROUND
, iState
, aBGRect
, aCaption
);
1122 if( nPart
== ControlPart::MenuItemCheckMark
)
1123 iState
= (nState
& ControlState::ENABLED
) ? MC_CHECKMARKNORMAL
: MC_CHECKMARKDISABLED
;
1125 iState
= (nState
& ControlState::ENABLED
) ? MC_BULLETNORMAL
: MC_BULLETDISABLED
;
1126 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECK
, iState
, rc
, aCaption
);
1129 return true; // unchecked: do nothing
1131 else if( nPart
== ControlPart::Separator
)
1133 // adjust for gutter position
1134 if( AllSettings::GetLayoutRTL() )
1135 rc
.right
-= aValue
.getNumericVal()+1;
1137 rc
.left
+= aValue
.getNumericVal()+1;
1138 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1139 MENU_POPUPSEPARATOR
, 0, tools::Rectangle( rc
.left
, rc
.top
, rc
.right
, rc
.bottom
) ) );
1140 // center the separator inside the passed rectangle
1141 long nDY
= ((rc
.bottom
- rc
.top
+ 1) - aRect
.GetHeight()) / 2;
1143 rc
.bottom
= rc
.top
+aRect
.GetHeight()-1;
1144 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPSEPARATOR
, 0, rc
, aCaption
);
1152 bool WinSalGraphics::drawNativeControl( ControlType nType
,
1154 const tools::Rectangle
& rControlRegion
,
1155 ControlState nState
,
1156 const ImplControlValue
& aValue
,
1157 const OUString
& aCaption
,
1158 const Color
& /*rBackgroundColor*/ )
1161 HTHEME hTheme
= nullptr;
1163 tools::Rectangle buttonRect
= rControlRegion
;
1164 tools::Rectangle cacheRect
= rControlRegion
;
1165 Size keySize
= cacheRect
.GetSize();
1167 WinSalGraphicsImplBase
* pImpl
= dynamic_cast<WinSalGraphicsImplBase
*>(mpImpl
.get());
1168 if( !pImpl
->UseRenderNativeControl())
1171 // tdf#95618 - A few controls render outside the region they're given.
1172 if (pImpl
&& nType
== ControlType::TabItem
)
1174 tools::Rectangle rNativeBoundingRegion
;
1175 tools::Rectangle rNativeContentRegion
;
1176 if (getNativeControlRegion(nType
, nPart
, rControlRegion
, nState
, aValue
, aCaption
,
1177 rNativeBoundingRegion
, rNativeContentRegion
))
1179 cacheRect
= rNativeBoundingRegion
;
1180 keySize
= rNativeBoundingRegion
.GetSize();
1184 if (pImpl
&& nType
== ControlType::MenuPopup
&& (nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
))
1186 tools::Rectangle aRectangle
= GetMenuPopupMarkRegion(aValue
);
1187 if (!aRectangle
.IsEmpty())
1189 cacheRect
= GetMenuPopupMarkRegion(aValue
);
1190 buttonRect
= cacheRect
;
1191 keySize
= cacheRect
.GetSize();
1196 ControlCacheKey
aControlCacheKey(nType
, nPart
, nState
, keySize
);
1197 if (pImpl
!= nullptr && pImpl
->TryRenderCachedNativeControl(aControlCacheKey
, buttonRect
.Left(), buttonRect
.Top()))
1204 case ControlType::Pushbutton
:
1205 case ControlType::Radiobutton
:
1206 case ControlType::Checkbox
:
1207 hTheme
= getThemeHandle( mhWnd
, L
"Button");
1209 case ControlType::Scrollbar
:
1210 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
1212 case ControlType::Combobox
:
1213 if( nPart
== ControlPart::Entire
)
1214 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1215 else if( nPart
== ControlPart::ButtonDown
)
1216 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1218 case ControlType::Spinbox
:
1219 if( nPart
== ControlPart::Entire
)
1220 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1222 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1224 case ControlType::SpinButtons
:
1225 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1227 case ControlType::Editbox
:
1228 case ControlType::MultilineEditbox
:
1229 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1231 case ControlType::Listbox
:
1232 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::ListboxWindow
)
1233 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
1234 else if( nPart
== ControlPart::ButtonDown
)
1235 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1237 case ControlType::TabPane
:
1238 case ControlType::TabBody
:
1239 case ControlType::TabItem
:
1240 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
1242 case ControlType::Toolbar
:
1243 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::Button
)
1244 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1246 // use rebar for grip and background
1247 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1249 case ControlType::Menubar
:
1250 if( nPart
== ControlPart::Entire
)
1251 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1252 else if( GetSalData()->mbThemeMenuSupport
)
1254 if( nPart
== ControlPart::MenuItem
)
1255 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1258 case ControlType::Progress
:
1259 if( nPart
== ControlPart::Entire
)
1260 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1262 case ControlType::ListNode
:
1263 if( nPart
== ControlPart::Entire
)
1264 hTheme
= getThemeHandle( mhWnd
, L
"TreeView");
1266 case ControlType::Slider
:
1267 if( nPart
== ControlPart::TrackHorzArea
|| nPart
== ControlPart::TrackVertArea
)
1268 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
1270 case ControlType::MenuPopup
:
1271 if( GetSalData()->mbThemeMenuSupport
)
1273 if( nPart
== ControlPart::Entire
|| nPart
== ControlPart::MenuItem
||
1274 nPart
== ControlPart::MenuItemCheckMark
|| nPart
== ControlPart::MenuItemRadioMark
||
1275 nPart
== ControlPart::Separator
1277 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1289 rc
.left
= buttonRect
.Left();
1290 rc
.right
= buttonRect
.Right()+1;
1291 rc
.top
= buttonRect
.Top();
1292 rc
.bottom
= buttonRect
.Bottom()+1;
1294 OUString
aCaptionStr(aCaption
.replace('~', '&')); // translate mnemonics
1296 if (pImpl
== nullptr)
1298 // set default text alignment
1299 int ta
= SetTextAlign(getHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1301 bOk
= ImplDrawNativeControl(getHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
);
1303 // restore alignment
1304 SetTextAlign(getHDC(), ta
);
1308 // We can do OpenGL/Skia
1309 std::unique_ptr
<CompatibleDC
> aBlackDC(CompatibleDC::create(*this, cacheRect
.Left(), cacheRect
.Top(), cacheRect
.GetWidth()+1, cacheRect
.GetHeight()+1));
1310 SetTextAlign(aBlackDC
->getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1311 aBlackDC
->fill(RGB(0, 0, 0));
1313 std::unique_ptr
<CompatibleDC
> aWhiteDC(CompatibleDC::create(*this, cacheRect
.Left(), cacheRect
.Top(), cacheRect
.GetWidth()+1, cacheRect
.GetHeight()+1));
1314 SetTextAlign(aWhiteDC
->getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1315 aWhiteDC
->fill(RGB(0xff, 0xff, 0xff));
1317 if (ImplDrawNativeControl(aBlackDC
->getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
) &&
1318 ImplDrawNativeControl(aWhiteDC
->getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
))
1320 bOk
= pImpl
->RenderAndCacheNativeControl(*aWhiteDC
, *aBlackDC
, cacheRect
.Left(), cacheRect
.Top(), aControlCacheKey
);
1327 bool WinSalGraphics::getNativeControlRegion( ControlType nType
,
1329 const tools::Rectangle
& rControlRegion
,
1330 ControlState nState
,
1331 const ImplControlValue
& rControlValue
,
1333 tools::Rectangle
&rNativeBoundingRegion
,
1334 tools::Rectangle
&rNativeContentRegion
)
1338 // FIXME: rNativeBoundingRegion has a different origin
1339 // depending on which part is used; horrors.
1341 HDC hDC
= GetDC( mhWnd
);
1342 if( nType
== ControlType::Toolbar
)
1344 if( nPart
== ControlPart::ThumbHorz
|| nPart
== ControlPart::ThumbVert
)
1347 // the vertical gripper is not supported in most themes and it makes no
1348 // sense to only support horizontal gripper
1350 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1353 tools::Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == ControlPart::ThumbHorz ? RP_GRIPPERVERT : RP_GRIPPER,
1354 0, rControlRegion.GetBoundRect() ) );
1355 if( nPart == ControlPart::ThumbHorz && !aRect.IsEmpty() )
1357 tools::Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1358 rNativeContentRegion = aVertRect;
1361 rNativeContentRegion = aRect;
1362 rNativeBoundingRegion = rNativeContentRegion;
1363 if( !rNativeContentRegion.IsEmpty() )
1368 if( nPart
== ControlPart::Button
)
1370 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1373 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, TP_SPLITBUTTONDROPDOWN
,
1374 TS_HOT
, rControlRegion
) );
1375 rNativeContentRegion
= aRect
;
1376 rNativeBoundingRegion
= rNativeContentRegion
;
1377 if( !rNativeContentRegion
.IsEmpty() )
1382 if( nType
== ControlType::Progress
&& nPart
== ControlPart::Entire
)
1384 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1387 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, PP_BAR
,
1388 0, rControlRegion
) );
1389 rNativeContentRegion
= aRect
;
1390 rNativeBoundingRegion
= rNativeContentRegion
;
1391 if( !rNativeContentRegion
.IsEmpty() )
1395 if( (nType
== ControlType::Listbox
|| nType
== ControlType::Combobox
) && nPart
== ControlPart::Entire
)
1397 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1400 tools::Rectangle
aBoxRect( rControlRegion
);
1401 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, CP_DROPDOWNBUTTON
,
1402 CBXS_NORMAL
, aBoxRect
) );
1403 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1404 aBoxRect
.SetBottom( aBoxRect
.Top() + aRect
.GetHeight() );
1405 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1406 aBoxRect
.SetRight( aBoxRect
.Left() + aRect
.GetWidth() );
1407 rNativeContentRegion
= aBoxRect
;
1408 rNativeBoundingRegion
= rNativeContentRegion
;
1409 if( !aRect
.IsEmpty() )
1414 if( (nType
== ControlType::Editbox
|| nType
== ControlType::Spinbox
) && nPart
== ControlPart::Entire
)
1416 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1420 tools::Rectangle
aBoxRect( rControlRegion
);
1421 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, EP_BACKGROUNDWITHBORDER
,
1422 EBWBS_HOT
, aBoxRect
) );
1423 // ad app font height
1424 NONCLIENTMETRICSW aNonClientMetrics
;
1425 aNonClientMetrics
.cbSize
= sizeof( aNonClientMetrics
);
1426 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS
, sizeof( aNonClientMetrics
), &aNonClientMetrics
, 0 ) )
1428 long nFontHeight
= aNonClientMetrics
.lfMessageFont
.lfHeight
;
1429 if( nFontHeight
< 0 )
1430 nFontHeight
= -nFontHeight
;
1432 if( aRect
.GetHeight() && nFontHeight
)
1434 aRect
.AdjustBottom(aRect
.GetHeight());
1435 aRect
.AdjustBottom(nFontHeight
);
1436 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1437 aBoxRect
.SetBottom( aBoxRect
.Top() + aRect
.GetHeight() );
1438 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1439 aBoxRect
.SetRight( aBoxRect
.Left() + aRect
.GetWidth() );
1440 rNativeContentRegion
= aBoxRect
;
1441 rNativeBoundingRegion
= rNativeContentRegion
;
1448 if( GetSalData()->mbThemeMenuSupport
)
1450 if( nType
== ControlType::MenuPopup
)
1452 if( nPart
== ControlPart::MenuItemCheckMark
||
1453 nPart
== ControlPart::MenuItemRadioMark
)
1455 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Menu");
1456 tools::Rectangle
aBoxRect( rControlRegion
);
1457 tools::Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1461 if( aBoxRect
.GetWidth() && aBoxRect
.GetHeight() )
1463 rNativeContentRegion
= aRect
;
1464 rNativeBoundingRegion
= rNativeContentRegion
;
1471 if( nType
== ControlType::Slider
&& ( (nPart
== ControlPart::ThumbHorz
) || (nPart
== ControlPart::ThumbVert
) ) )
1473 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Trackbar");
1476 int iPart
= (nPart
== ControlPart::ThumbHorz
) ? TKP_THUMB
: TKP_THUMBVERT
;
1477 int iState
= (nPart
== ControlPart::ThumbHorz
) ? static_cast<int>(TUS_NORMAL
) : static_cast<int>(TUVS_NORMAL
);
1478 tools::Rectangle aThumbRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, tools::Rectangle() );
1479 if( nPart
== ControlPart::ThumbHorz
)
1481 long nW
= aThumbRect
.GetWidth();
1482 tools::Rectangle
aRect( rControlRegion
);
1483 aRect
.SetRight( aRect
.Left() + nW
- 1 );
1484 rNativeContentRegion
= aRect
;
1485 rNativeBoundingRegion
= rNativeContentRegion
;
1489 long nH
= aThumbRect
.GetHeight();
1490 tools::Rectangle
aRect( rControlRegion
);
1491 aRect
.SetBottom( aRect
.Top() + nH
- 1 );
1492 rNativeContentRegion
= aRect
;
1493 rNativeBoundingRegion
= rNativeContentRegion
;
1499 if ( ( nType
== ControlType::TabItem
) && ( nPart
== ControlPart::Entire
) )
1501 tools::Rectangle
aControlRect( rControlRegion
);
1502 rNativeContentRegion
= aControlRect
;
1504 aControlRect
.AdjustBottom(-1);
1506 if( rControlValue
.getType() == ControlType::TabItem
)
1508 const TabitemValue
& rValue
= static_cast<const TabitemValue
&>(rControlValue
);
1509 if (rValue
.isBothAligned())
1510 aControlRect
.AdjustRight(-1);
1512 if ( nState
& ControlState::SELECTED
)
1514 aControlRect
.AdjustLeft(-2);
1515 if (!rValue
.isBothAligned())
1517 if (rValue
.isLeftAligned() || rValue
.isNotAligned())
1518 aControlRect
.AdjustRight(2);
1519 if (rValue
.isRightAligned())
1520 aControlRect
.AdjustRight(1);
1522 aControlRect
.AdjustTop(-2);
1523 aControlRect
.AdjustBottom(2);
1526 rNativeBoundingRegion
= aControlRect
;
1530 ReleaseDC( mhWnd
, hDC
);
1534 void WinSalGraphics::updateSettingsNative( AllSettings
& rSettings
)
1536 if ( !vsAPI
.IsThemeActive() )
1539 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1540 ImplSVData
* pSVData
= ImplGetSVData();
1542 // don't draw frame around each and every toolbar
1543 pSVData
->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1545 // FIXME get the color directly from the theme, not from the settings
1546 Color aMenuBarTextColor
= aStyleSettings
.GetPersonaMenuBarTextColor().value_or( aStyleSettings
.GetMenuTextColor() );
1547 // in aero menuitem highlight text is drawn in the same color as normal
1548 aStyleSettings
.SetMenuHighlightTextColor( aStyleSettings
.GetMenuTextColor() );
1549 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuBarTextColor
);
1550 aStyleSettings
.SetMenuBarHighlightTextColor( aMenuBarTextColor
);
1551 pSVData
->maNWFData
.mnMenuFormatBorderX
= 2;
1552 pSVData
->maNWFData
.mnMenuFormatBorderY
= 2;
1553 pSVData
->maNWFData
.maMenuBarHighlightTextColor
= aMenuBarTextColor
;
1554 GetSalData()->mbThemeMenuSupport
= true;
1556 rSettings
.SetStyleSettings( aStyleSettings
);
1559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */