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/module.h"
38 #include <opengl/win/gdiimpl.hxx>
39 #include "vcl/svapp.hxx"
40 #include <vcl/settings.hxx>
42 #include "win/svsys.h"
43 #include "win/salgdi.h"
44 #include "win/saldata.hxx"
54 typedef map
< wstring
, HTHEME
> ThemeMap
;
55 static ThemeMap aThemeMap
;
57 /****************************************************
58 wrap visual styles API to avoid linking against it
59 it is not available on all Windows platforms
60 *****************************************************/
65 typedef HTHEME (WINAPI
* OpenThemeData_Proc_T
) ( HWND hwnd
, LPCWSTR pszClassList
);
66 typedef HRESULT (WINAPI
* CloseThemeData_Proc_T
) ( HTHEME hTheme
);
67 typedef HRESULT (WINAPI
* GetThemeBackgroundContentRect_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
68 typedef HRESULT (WINAPI
* DrawThemeBackground_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
69 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
);
70 typedef HRESULT (WINAPI
* GetThemePartSize_Proc_T
) ( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
71 typedef BOOL (WINAPI
* IsThemeActive_Proc_T
) ( void );
73 OpenThemeData_Proc_T lpfnOpenThemeData
;
74 CloseThemeData_Proc_T lpfnCloseThemeData
;
75 GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect
;
76 DrawThemeBackground_Proc_T lpfnDrawThemeBackground
;
77 DrawThemeText_Proc_T lpfnDrawThemeText
;
78 GetThemePartSize_Proc_T lpfnGetThemePartSize
;
79 IsThemeActive_Proc_T lpfnIsThemeActive
;
86 bool IsAvailable() { return (mhModule
!= NULL
); }
88 HTHEME
OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
);
89 HRESULT
CloseThemeData( HTHEME hTheme
);
90 HRESULT
GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
);
91 HRESULT
DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
);
92 HRESULT
DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
);
93 HRESULT
GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
);
97 static VisualStylesAPI vsAPI
;
99 VisualStylesAPI::VisualStylesAPI()
100 : lpfnOpenThemeData( NULL
),
101 lpfnCloseThemeData( NULL
),
102 lpfnGetThemeBackgroundContentRect( NULL
),
103 lpfnDrawThemeBackground( NULL
),
104 lpfnDrawThemeText( NULL
),
105 lpfnGetThemePartSize( NULL
),
106 lpfnIsThemeActive( NULL
)
108 OUString
aLibraryName( "uxtheme.dll" );
109 mhModule
= osl_loadModule( aLibraryName
.pData
, SAL_LOADMODULE_DEFAULT
);
113 lpfnOpenThemeData
= (OpenThemeData_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "OpenThemeData" );
114 lpfnCloseThemeData
= (CloseThemeData_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "CloseThemeData" );
115 lpfnGetThemeBackgroundContentRect
= (GetThemeBackgroundContentRect_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "GetThemeBackgroundContentRect" );
116 lpfnDrawThemeBackground
= (DrawThemeBackground_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeBackground" );
117 lpfnDrawThemeText
= (DrawThemeText_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "DrawThemeText" );
118 lpfnGetThemePartSize
= (GetThemePartSize_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "GetThemePartSize" );
119 lpfnIsThemeActive
= (IsThemeActive_Proc_T
)osl_getAsciiFunctionSymbol( mhModule
, "IsThemeActive" );
123 VisualStylesAPI::~VisualStylesAPI()
126 osl_unloadModule( mhModule
);
129 HTHEME
VisualStylesAPI::OpenThemeData( HWND hwnd
, LPCWSTR pszClassList
)
131 if(lpfnOpenThemeData
)
132 return (*lpfnOpenThemeData
) (hwnd
, pszClassList
);
137 HRESULT
VisualStylesAPI::CloseThemeData( HTHEME hTheme
)
139 if(lpfnCloseThemeData
)
140 return (*lpfnCloseThemeData
) (hTheme
);
145 HRESULT
VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pBoundingRect
, RECT
*pContentRect
)
147 if(lpfnGetThemeBackgroundContentRect
)
148 return (*lpfnGetThemeBackgroundContentRect
) ( hTheme
, hdc
, iPartId
, iStateId
, pBoundingRect
, pContentRect
);
153 HRESULT
VisualStylesAPI::DrawThemeBackground( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, const RECT
*pRect
, const RECT
*pClipRect
)
155 if(lpfnDrawThemeBackground
)
156 return (*lpfnDrawThemeBackground
) (hTheme
, hdc
, iPartId
, iStateId
, pRect
, pClipRect
);
161 HRESULT
VisualStylesAPI::DrawThemeText( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, LPCWSTR pszText
, int iCharCount
, DWORD dwTextFlags
, DWORD dwTextFlags2
, const RECT
*pRect
)
163 if(lpfnDrawThemeText
)
164 return (*lpfnDrawThemeText
) (hTheme
, hdc
, iPartId
, iStateId
, pszText
, iCharCount
, dwTextFlags
, dwTextFlags2
, pRect
);
169 HRESULT
VisualStylesAPI::GetThemePartSize( HTHEME hTheme
, HDC hdc
, int iPartId
, int iStateId
, RECT
*prc
, THEMESIZE eSize
, SIZE
*psz
)
171 if(lpfnGetThemePartSize
)
172 return (*lpfnGetThemePartSize
) (hTheme
, hdc
, iPartId
, iStateId
, prc
, eSize
, psz
);
177 BOOL
VisualStylesAPI::IsThemeActive()
179 if(lpfnIsThemeActive
)
180 return (*lpfnIsThemeActive
) ();
185 /*********************************************************
186 * Initialize XP theming and local stuff
187 *********************************************************/
188 void SalData::initNWF()
190 ImplSVData
* pSVData
= ImplGetSVData();
192 // the menu bar and the top docking area should have a common background (gradient)
193 pSVData
->maNWFData
.mbMenuBarDockingAreaCommonBG
= true;
196 // *********************************************************
197 // * Release theming handles
198 // ********************************************************
199 void SalData::deInitNWF()
201 ThemeMap::iterator iter
= aThemeMap
.begin();
202 while( iter
!= aThemeMap
.end() )
204 vsAPI
.CloseThemeData(iter
->second
);
209 osl_unloadModule( maDwmLib
);
212 static HTHEME
getThemeHandle( HWND hWnd
, LPCWSTR name
)
214 if( GetSalData()->mbThemeChanged
)
216 // throw away invalid theme handles
217 GetSalData()->deInitNWF();
218 GetSalData()->mbThemeChanged
= FALSE
;
221 ThemeMap::iterator iter
;
222 if( (iter
= aThemeMap
.find( name
)) != aThemeMap
.end() )
224 // theme not found -> add it to map
225 HTHEME hTheme
= vsAPI
.OpenThemeData( hWnd
, name
);
227 aThemeMap
[name
] = hTheme
;
232 * IsNativeControlSupported()
234 * Returns TRUE if the platform supports native
235 * drawing of the control defined by nPart
237 bool WinSalGraphics::IsNativeControlSupported( ControlType nType
, ControlPart nPart
)
239 HTHEME hTheme
= NULL
;
243 case CTRL_PUSHBUTTON
:
244 case CTRL_RADIOBUTTON
:
246 if( nPart
== PART_ENTIRE_CONTROL
)
247 hTheme
= getThemeHandle( mhWnd
, L
"Button");
250 if( nPart
== PART_DRAW_BACKGROUND_HORZ
|| nPart
== PART_DRAW_BACKGROUND_VERT
)
251 return FALSE
; // no background painting needed
252 if( nPart
== PART_ENTIRE_CONTROL
)
253 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
256 if( nPart
== HAS_BACKGROUND_TEXTURE
)
257 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
258 if( nPart
== PART_ENTIRE_CONTROL
)
259 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
260 else if( nPart
== PART_BUTTON_DOWN
)
261 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
264 if( nPart
== PART_ENTIRE_CONTROL
)
265 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
266 else if( nPart
== PART_ALL_BUTTONS
||
267 nPart
== PART_BUTTON_UP
|| nPart
== PART_BUTTON_DOWN
||
268 nPart
== PART_BUTTON_LEFT
|| nPart
== PART_BUTTON_RIGHT
)
269 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
271 case CTRL_SPINBUTTONS
:
272 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_ALL_BUTTONS
)
273 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
276 case CTRL_MULTILINE_EDITBOX
:
277 if( nPart
== HAS_BACKGROUND_TEXTURE
)
278 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
280 if( nPart
== PART_ENTIRE_CONTROL
)
281 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
284 if( nPart
== HAS_BACKGROUND_TEXTURE
)
285 return FALSE
; // we do not paint the inner part (ie the selection background/focus indication)
286 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_WINDOW
)
287 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
288 else if( nPart
== PART_BUTTON_DOWN
)
289 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
294 if( nPart
== PART_ENTIRE_CONTROL
)
295 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
298 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_BUTTON
)
299 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
301 // use rebar theme for grip and background
302 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
305 if( nPart
== PART_ENTIRE_CONTROL
)
306 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
307 else if( GetSalData()->mbThemeMenuSupport
)
309 if( nPart
== PART_MENU_ITEM
)
310 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
313 case CTRL_MENU_POPUP
:
314 if( GetSalData()->mbThemeMenuSupport
)
316 if( nPart
== PART_ENTIRE_CONTROL
||
317 nPart
== PART_MENU_ITEM
||
318 nPart
== PART_MENU_ITEM_CHECK_MARK
||
319 nPart
== PART_MENU_ITEM_RADIO_MARK
||
320 nPart
== PART_MENU_SEPARATOR
)
321 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
325 if( nPart
== PART_ENTIRE_CONTROL
)
326 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
329 if( nPart
== PART_TRACK_HORZ_AREA
|| nPart
== PART_TRACK_VERT_AREA
)
330 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
333 if( nPart
== PART_ENTIRE_CONTROL
)
334 hTheme
= getThemeHandle( mhWnd
, L
"TreeView" );
341 return (hTheme
!= NULL
);
345 * HitTestNativeControl()
347 * If the return value is TRUE, bIsInside contains information whether
348 * aPos was or was not inside the native widget specified by the
349 * nType/nPart combination.
351 bool WinSalGraphics::hitTestNativeControl( ControlType
,
360 bool ImplDrawTheme( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, RECT rc
, const OUString
& aStr
)
362 HRESULT hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
364 if( aStr
.getLength() )
367 hr
= vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, iPart
, iState
, &rc
, &rcContent
);
368 hr
= vsAPI
.DrawThemeText( hTheme
, hDC
, iPart
, iState
,
369 reinterpret_cast<LPCWSTR
>(aStr
.getStr()), -1,
370 DT_CENTER
| DT_VCENTER
| DT_SINGLELINE
,
376 Rectangle
ImplGetThemeRect( HTHEME hTheme
, HDC hDC
, int iPart
, int iState
, const Rectangle
& /* aRect */, THEMESIZE eTS
= TS_TRUE
)
379 HRESULT hr
= vsAPI
.GetThemePartSize( hTheme
, hDC
, iPart
, iState
, NULL
, eTS
, &aSz
); // TS_TRUE returns optimal size
381 return Rectangle( 0, 0, aSz
.cx
, aSz
.cy
);
388 void ImplConvertSpinbuttonValues( int nControlPart
, const ControlState
& rState
, const Rectangle
& rRect
,
389 int* pLunaPart
, int *pLunaState
, RECT
*pRect
)
391 if( nControlPart
== PART_BUTTON_DOWN
)
393 *pLunaPart
= SPNP_DOWN
;
394 if( rState
& ControlState::PRESSED
)
395 *pLunaState
= DNS_PRESSED
;
396 else if( !(rState
& ControlState::ENABLED
) )
397 *pLunaState
= DNS_DISABLED
;
398 else if( rState
& ControlState::ROLLOVER
)
399 *pLunaState
= DNS_HOT
;
401 *pLunaState
= DNS_NORMAL
;
403 if( nControlPart
== PART_BUTTON_UP
)
405 *pLunaPart
= SPNP_UP
;
406 if( rState
& ControlState::PRESSED
)
407 *pLunaState
= UPS_PRESSED
;
408 else if( !(rState
& ControlState::ENABLED
) )
409 *pLunaState
= UPS_DISABLED
;
410 else if( rState
& ControlState::ROLLOVER
)
411 *pLunaState
= UPS_HOT
;
413 *pLunaState
= UPS_NORMAL
;
415 if( nControlPart
== PART_BUTTON_RIGHT
)
417 *pLunaPart
= SPNP_UPHORZ
;
418 if( rState
& ControlState::PRESSED
)
419 *pLunaState
= DNHZS_PRESSED
;
420 else if( !(rState
& ControlState::ENABLED
) )
421 *pLunaState
= DNHZS_DISABLED
;
422 else if( rState
& ControlState::ROLLOVER
)
423 *pLunaState
= DNHZS_HOT
;
425 *pLunaState
= DNHZS_NORMAL
;
427 if( nControlPart
== PART_BUTTON_LEFT
)
429 *pLunaPart
= SPNP_DOWNHORZ
;
430 if( rState
& ControlState::PRESSED
)
431 *pLunaState
= UPHZS_PRESSED
;
432 else if( !(rState
& ControlState::ENABLED
) )
433 *pLunaState
= UPHZS_DISABLED
;
434 else if( rState
& ControlState::ROLLOVER
)
435 *pLunaState
= UPHZS_HOT
;
437 *pLunaState
= UPHZS_NORMAL
;
440 pRect
->left
= rRect
.Left();
441 pRect
->right
= rRect
.Right()+1;
442 pRect
->top
= rRect
.Top();
443 pRect
->bottom
= rRect
.Bottom()+1;
446 /// Draw an own toolbar style on Windows Vista or later, looks better there
447 static void impl_drawAeroToolbar( HDC hDC
, RECT rc
, bool bHorizontal
)
449 if ( rc
.top
== 0 && bHorizontal
)
451 const long GRADIENT_HEIGHT
= 32;
453 long gradient_break
= rc
.top
;
454 long gradient_bottom
= rc
.bottom
- 1;
455 GRADIENT_RECT g_rect
[1] = { { 0, 1 } };
457 // very slow gradient at the top (if we have space for that)
458 if ( gradient_bottom
- rc
.top
> GRADIENT_HEIGHT
)
460 gradient_break
= gradient_bottom
- GRADIENT_HEIGHT
;
462 TRIVERTEX vert
[2] = {
463 { rc
.left
, rc
.top
, 0xff00, 0xff00, 0xff00, 0xff00 },
464 { rc
.right
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
466 GradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
469 // gradient at the bottom
470 TRIVERTEX vert
[2] = {
471 { rc
.left
, gradient_break
, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
472 { rc
.right
, gradient_bottom
, 0xf000, 0xf000, 0xf000, 0xff00 }
474 GradientFill( hDC
, vert
, 2, g_rect
, 1, GRADIENT_FILL_RECT_V
);
476 // and a darker horizontal line under that
477 HPEN hpen
= CreatePen( PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0 ) );
478 HPEN hOrigPen
= (HPEN
) SelectObject(hDC
, hpen
);
480 MoveToEx( hDC
, rc
.left
, gradient_bottom
, NULL
);
481 LineTo( hDC
, rc
.right
, gradient_bottom
);
483 SelectObject(hDC
, hOrigPen
);
488 HBRUSH hbrush
= CreateSolidBrush( RGB( 0xf0, 0xf0, 0xf0 ) );
489 FillRect( hDC
, &rc
, hbrush
);
490 DeleteObject( hbrush
);
492 // darker line to distinguish the toolbar and viewshell
493 // it is drawn only for the horizontal toolbars; it did not look well
494 // when done for the vertical ones too
497 long from_x
, from_y
, to_x
, to_y
;
501 from_y
= to_y
= rc
.top
;
503 HPEN hpen
= CreatePen( PS_SOLID
, 1, RGB( 0xb0, 0xb0, 0xb0 ) );
504 HPEN hOrigPen
= (HPEN
) SelectObject(hDC
, hpen
);
506 MoveToEx( hDC
, from_x
, from_y
, NULL
);
507 LineTo( hDC
, to_x
, to_y
);
509 SelectObject(hDC
, hOrigPen
);
515 bool ImplDrawNativeControl( HDC hDC
, HTHEME hTheme
, RECT rc
,
519 const ImplControlValue
& aValue
,
522 // a listbox dropdown is actually a combobox dropdown
523 if( nType
== CTRL_LISTBOX
)
524 if( nPart
== PART_BUTTON_DOWN
)
525 nType
= CTRL_COMBOBOX
;
527 // draw entire combobox as a large edit box
528 if( nType
== CTRL_COMBOBOX
)
529 if( nPart
== PART_ENTIRE_CONTROL
)
530 nType
= CTRL_EDITBOX
;
532 // draw entire spinbox as a large edit box
533 if( nType
== CTRL_SPINBOX
)
534 if( nPart
== PART_ENTIRE_CONTROL
)
535 nType
= CTRL_EDITBOX
;
537 int iPart(0), iState(0);
538 if( nType
== CTRL_SCROLLBAR
)
541 if( nPart
== PART_BUTTON_UP
)
543 iPart
= SBP_ARROWBTN
;
544 if( nState
& ControlState::PRESSED
)
545 iState
= ABS_UPPRESSED
;
546 else if( !(nState
& ControlState::ENABLED
) )
547 iState
= ABS_UPDISABLED
;
548 else if( nState
& ControlState::ROLLOVER
)
551 iState
= ABS_UPNORMAL
;
552 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
555 if( nPart
== PART_BUTTON_DOWN
)
557 iPart
= SBP_ARROWBTN
;
558 if( nState
& ControlState::PRESSED
)
559 iState
= ABS_DOWNPRESSED
;
560 else if( !(nState
& ControlState::ENABLED
) )
561 iState
= ABS_DOWNDISABLED
;
562 else if( nState
& ControlState::ROLLOVER
)
563 iState
= ABS_DOWNHOT
;
565 iState
= ABS_DOWNNORMAL
;
566 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
569 if( nPart
== PART_BUTTON_LEFT
)
571 iPart
= SBP_ARROWBTN
;
572 if( nState
& ControlState::PRESSED
)
573 iState
= ABS_LEFTPRESSED
;
574 else if( !(nState
& ControlState::ENABLED
) )
575 iState
= ABS_LEFTDISABLED
;
576 else if( nState
& ControlState::ROLLOVER
)
577 iState
= ABS_LEFTHOT
;
579 iState
= ABS_LEFTNORMAL
;
580 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
583 if( nPart
== PART_BUTTON_RIGHT
)
585 iPart
= SBP_ARROWBTN
;
586 if( nState
& ControlState::PRESSED
)
587 iState
= ABS_RIGHTPRESSED
;
588 else if( !(nState
& ControlState::ENABLED
) )
589 iState
= ABS_RIGHTDISABLED
;
590 else if( nState
& ControlState::ROLLOVER
)
591 iState
= ABS_RIGHTHOT
;
593 iState
= ABS_RIGHTNORMAL
;
594 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
597 if( nPart
== PART_THUMB_HORZ
|| nPart
== PART_THUMB_VERT
)
599 iPart
= (nPart
== PART_THUMB_HORZ
) ? SBP_THUMBBTNHORZ
: SBP_THUMBBTNVERT
;
600 if( nState
& ControlState::PRESSED
)
601 iState
= SCRBS_PRESSED
;
602 else if( !(nState
& ControlState::ENABLED
) )
603 iState
= SCRBS_DISABLED
;
604 else if( nState
& ControlState::ROLLOVER
)
607 iState
= SCRBS_NORMAL
;
610 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, NULL
, TS_MIN
, &sz
);
611 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, NULL
, TS_TRUE
, &sz
);
612 vsAPI
.GetThemePartSize(hTheme
, hDC
, iPart
, iState
, NULL
, TS_DRAW
, &sz
);
614 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
615 // paint gripper on thumb if enough space
616 if( ( (nPart
== PART_THUMB_VERT
) && (rc
.bottom
-rc
.top
> 12) ) ||
617 ( (nPart
== PART_THUMB_HORZ
) && (rc
.right
-rc
.left
> 12) ) )
619 iPart
= (nPart
== PART_THUMB_HORZ
) ? SBP_GRIPPERHORZ
: SBP_GRIPPERVERT
;
621 vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
625 if( nPart
== PART_TRACK_HORZ_LEFT
|| nPart
== PART_TRACK_HORZ_RIGHT
|| nPart
== PART_TRACK_VERT_UPPER
|| nPart
== PART_TRACK_VERT_LOWER
)
629 case PART_TRACK_HORZ_LEFT
: iPart
= SBP_UPPERTRACKHORZ
; break;
630 case PART_TRACK_HORZ_RIGHT
: iPart
= SBP_LOWERTRACKHORZ
; break;
631 case PART_TRACK_VERT_UPPER
: iPart
= SBP_UPPERTRACKVERT
; break;
632 case PART_TRACK_VERT_LOWER
: iPart
= SBP_LOWERTRACKVERT
; break;
635 if( nState
& ControlState::PRESSED
)
636 iState
= SCRBS_PRESSED
;
637 else if( !(nState
& ControlState::ENABLED
) )
638 iState
= SCRBS_DISABLED
;
639 else if( nState
& ControlState::ROLLOVER
)
642 iState
= SCRBS_NORMAL
;
643 hr
= vsAPI
.DrawThemeBackground( hTheme
, hDC
, iPart
, iState
, &rc
, 0);
647 if( nType
== CTRL_SPINBUTTONS
&& nPart
== PART_ALL_BUTTONS
)
649 if( aValue
.getType() == CTRL_SPINBUTTONS
)
651 const SpinbuttonValue
* pValue
= (aValue
.getType() == CTRL_SPINBUTTONS
) ? static_cast<const SpinbuttonValue
*>(&aValue
) : NULL
;
654 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
655 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
659 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
660 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
666 if( nType
== CTRL_SPINBOX
)
668 // decrease spinbutton rects a little
671 if( nPart
== PART_ALL_BUTTONS
)
673 if( aValue
.getType() == CTRL_SPINBUTTONS
)
675 const SpinbuttonValue
*pValue
= static_cast<const SpinbuttonValue
*>(&aValue
);
678 ImplConvertSpinbuttonValues( pValue
->mnUpperPart
, pValue
->mnUpperState
, pValue
->maUpperRect
, &iPart
, &iState
, &rect
);
679 bool bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
683 ImplConvertSpinbuttonValues( pValue
->mnLowerPart
, pValue
->mnLowerState
, pValue
->maLowerRect
, &iPart
, &iState
, &rect
);
684 bOk
= ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rect
, aCaption
);
691 if( nPart
== PART_BUTTON_DOWN
)
694 if( nState
& ControlState::PRESSED
)
695 iState
= DNS_PRESSED
;
696 else if( !(nState
& ControlState::ENABLED
) )
697 iState
= DNS_DISABLED
;
698 else if( nState
& ControlState::ROLLOVER
)
703 if( nPart
== PART_BUTTON_UP
)
706 if( nState
& ControlState::PRESSED
)
707 iState
= UPS_PRESSED
;
708 else if( !(nState
& ControlState::ENABLED
) )
709 iState
= UPS_DISABLED
;
710 else if( nState
& ControlState::ROLLOVER
)
715 if( nPart
== PART_BUTTON_RIGHT
)
717 iPart
= SPNP_DOWNHORZ
;
718 if( nState
& ControlState::PRESSED
)
719 iState
= DNHZS_PRESSED
;
720 else if( !(nState
& ControlState::ENABLED
) )
721 iState
= DNHZS_DISABLED
;
722 else if( nState
& ControlState::ROLLOVER
)
725 iState
= DNHZS_NORMAL
;
727 if( nPart
== PART_BUTTON_LEFT
)
730 if( nState
& ControlState::PRESSED
)
731 iState
= UPHZS_PRESSED
;
732 else if( !(nState
& ControlState::ENABLED
) )
733 iState
= UPHZS_DISABLED
;
734 else if( nState
& ControlState::ROLLOVER
)
737 iState
= UPHZS_NORMAL
;
739 if( nPart
== PART_BUTTON_LEFT
|| nPart
== PART_BUTTON_RIGHT
|| nPart
== PART_BUTTON_UP
|| nPart
== PART_BUTTON_DOWN
)
740 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
742 if( nType
== CTRL_COMBOBOX
)
744 if( nPart
== PART_BUTTON_DOWN
)
746 iPart
= CP_DROPDOWNBUTTON
;
747 if( nState
& ControlState::PRESSED
)
748 iState
= CBXS_PRESSED
;
749 else if( !(nState
& ControlState::ENABLED
) )
750 iState
= CBXS_DISABLED
;
751 else if( nState
& ControlState::ROLLOVER
)
754 iState
= CBXS_NORMAL
;
755 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
758 if( nType
== CTRL_PUSHBUTTON
)
760 iPart
= BP_PUSHBUTTON
;
761 if( nState
& ControlState::PRESSED
)
762 iState
= PBS_PRESSED
;
763 else if( !(nState
& ControlState::ENABLED
) )
764 iState
= PBS_DISABLED
;
765 else if( nState
& ControlState::ROLLOVER
)
767 else if( nState
& ControlState::DEFAULT
)
768 iState
= PBS_DEFAULTED
;
769 //else if( nState & ControlState::FOCUSED )
770 // iState = PBS_DEFAULTED; // may need to draw focus rect
774 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
777 if( nType
== CTRL_RADIOBUTTON
)
779 iPart
= BP_RADIOBUTTON
;
780 bool bChecked
= ( aValue
.getTristateVal() == BUTTONVALUE_ON
);
782 if( nState
& ControlState::PRESSED
)
783 iState
= bChecked
? RBS_CHECKEDPRESSED
: RBS_UNCHECKEDPRESSED
;
784 else if( !(nState
& ControlState::ENABLED
) )
785 iState
= bChecked
? RBS_CHECKEDDISABLED
: RBS_UNCHECKEDDISABLED
;
786 else if( nState
& ControlState::ROLLOVER
)
787 iState
= bChecked
? RBS_CHECKEDHOT
: RBS_UNCHECKEDHOT
;
789 iState
= bChecked
? RBS_CHECKEDNORMAL
: RBS_UNCHECKEDNORMAL
;
791 //if( nState & ControlState::FOCUSED )
792 // iState |= PBS_DEFAULTED; // may need to draw focus rect
794 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
797 if( nType
== CTRL_CHECKBOX
)
800 ButtonValue v
= aValue
.getTristateVal();
802 if( nState
& ControlState::PRESSED
)
803 iState
= (v
== BUTTONVALUE_ON
) ? CBS_CHECKEDPRESSED
:
804 ( (v
== BUTTONVALUE_OFF
) ? CBS_UNCHECKEDPRESSED
: CBS_MIXEDPRESSED
);
805 else if( !(nState
& ControlState::ENABLED
) )
806 iState
= (v
== BUTTONVALUE_ON
) ? CBS_CHECKEDDISABLED
:
807 ( (v
== BUTTONVALUE_OFF
) ? CBS_UNCHECKEDDISABLED
: CBS_MIXEDDISABLED
);
808 else if( nState
& ControlState::ROLLOVER
)
809 iState
= (v
== BUTTONVALUE_ON
) ? CBS_CHECKEDHOT
:
810 ( (v
== BUTTONVALUE_OFF
) ? CBS_UNCHECKEDHOT
: CBS_MIXEDHOT
);
812 iState
= (v
== BUTTONVALUE_ON
) ? CBS_CHECKEDNORMAL
:
813 ( (v
== BUTTONVALUE_OFF
) ? CBS_UNCHECKEDNORMAL
: CBS_MIXEDNORMAL
);
815 //if( nState & ControlState::FOCUSED )
816 // iState |= PBS_DEFAULTED; // may need to draw focus rect
819 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
820 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
822 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
825 if( ( nType
== CTRL_EDITBOX
) || ( nType
== CTRL_MULTILINE_EDITBOX
) )
828 if( !(nState
& ControlState::ENABLED
) )
829 iState
= ETS_DISABLED
;
830 else if( nState
& ControlState::FOCUSED
)
831 iState
= ETS_FOCUSED
;
832 else if( nState
& ControlState::ROLLOVER
)
837 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
840 if( nType
== CTRL_LISTBOX
)
842 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_WINDOW
)
844 iPart
= LVP_EMPTYTEXT
; // ??? no idea which part to choose here
845 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
849 if( nType
== CTRL_TAB_PANE
)
852 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
855 if( nType
== CTRL_TAB_BODY
)
858 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
861 if( nType
== CTRL_TAB_ITEM
)
863 iPart
= TABP_TABITEMLEFTEDGE
;
866 OSL_ASSERT( aValue
.getType() == CTRL_TAB_ITEM
);
868 const TabitemValue
*pValue
= static_cast<const TabitemValue
*>(&aValue
);
869 if( pValue
->isBothAligned() )
871 iPart
= TABP_TABITEMLEFTEDGE
;
874 else if( pValue
->isLeftAligned() )
875 iPart
= TABP_TABITEMLEFTEDGE
;
876 else if( pValue
->isRightAligned() )
877 iPart
= TABP_TABITEMRIGHTEDGE
;
878 else iPart
= TABP_TABITEM
;
880 if( !(nState
& ControlState::ENABLED
) )
881 iState
= TILES_DISABLED
;
882 else if( nState
& ControlState::SELECTED
)
884 iState
= TILES_SELECTED
;
885 // increase the selected tab
887 if( pValue
&& !pValue
->isBothAligned() )
889 if( pValue
->isLeftAligned() || pValue
->isNotAligned() )
891 if( pValue
->isRightAligned() )
897 else if( nState
& ControlState::ROLLOVER
)
899 else if( nState
& ControlState::FOCUSED
)
900 iState
= TILES_FOCUSED
; // may need to draw focus rect
902 iState
= TILES_NORMAL
;
903 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
906 if( nType
== CTRL_TOOLBAR
)
908 if( nPart
== PART_BUTTON
)
911 bool bChecked
= ( aValue
.getTristateVal() == BUTTONVALUE_ON
);
912 if( !(nState
& ControlState::ENABLED
) )
913 //iState = TS_DISABLED;
914 // disabled buttons are typically not painted at all but we need visual
915 // feedback when travelling by keyboard over disabled entries
917 else if( nState
& ControlState::PRESSED
)
919 else if( nState
& ControlState::ROLLOVER
)
920 iState
= bChecked
? TS_HOTCHECKED
: TS_HOT
;
922 iState
= bChecked
? TS_CHECKED
: TS_NORMAL
;
923 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
925 else if( nPart
== PART_THUMB_HORZ
|| nPart
== PART_THUMB_VERT
)
927 // the vertical gripper is not supported in most themes and it makes no
928 // sense to only support horizontal gripper
929 //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER;
930 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
932 else if( nPart
== PART_DRAW_BACKGROUND_HORZ
|| nPart
== PART_DRAW_BACKGROUND_VERT
)
934 if( aValue
.getType() == CTRL_TOOLBAR
)
936 const ToolbarValue
*pValue
= static_cast<const ToolbarValue
*>(&aValue
);
937 if( pValue
->mbIsTopDockingArea
)
938 rc
.top
= 0; // extend potential gradient to cover menu bar as well
941 // make it more compatible with Aero
942 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
944 impl_drawAeroToolbar( hDC
, rc
, nPart
== PART_DRAW_BACKGROUND_HORZ
);
948 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
952 if( nType
== CTRL_MENUBAR
)
954 if( nPart
== PART_ENTIRE_CONTROL
)
956 if( aValue
.getType() == CTRL_MENUBAR
)
958 const MenubarValue
*pValue
= static_cast<const MenubarValue
*>(&aValue
);
959 rc
.bottom
+= pValue
->maTopDockingAreaHeight
; // extend potential gradient to cover docking area as well
961 // make it more compatible with Aero
962 if( ImplGetSVData()->maNWFData
.mbDockingAreaAvoidTBFrames
)
964 impl_drawAeroToolbar( hDC
, rc
, true );
968 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
970 else if( nPart
== PART_MENU_ITEM
)
972 if( nState
& ControlState::ENABLED
)
974 if( nState
& ControlState::SELECTED
)
976 else if( nState
& ControlState::ROLLOVER
)
983 if( nState
& ControlState::SELECTED
)
984 iState
= MBI_DISABLEDPUSHED
;
985 else if( nState
& ControlState::ROLLOVER
)
986 iState
= MBI_DISABLEDHOT
;
988 iState
= MBI_DISABLED
;
990 return ImplDrawTheme( hTheme
, hDC
, MENU_BARITEM
, iState
, rc
, aCaption
);
994 if( nType
== CTRL_PROGRESS
)
996 if( nPart
!= PART_ENTIRE_CONTROL
)
999 if( ! ImplDrawTheme( hTheme
, hDC
, PP_BAR
, iState
, rc
, aCaption
) )
1001 RECT aProgressRect
= rc
;
1002 if( vsAPI
.GetThemeBackgroundContentRect( hTheme
, hDC
, PP_BAR
, iState
, &rc
, &aProgressRect
) != S_OK
)
1005 long nProgressWidth
= aValue
.getNumericVal();
1006 nProgressWidth
*= (aProgressRect
.right
- aProgressRect
.left
);
1007 nProgressWidth
/= (rc
.right
- rc
.left
);
1008 if( AllSettings::GetLayoutRTL() )
1009 aProgressRect
.left
= aProgressRect
.right
- nProgressWidth
;
1011 aProgressRect
.right
= aProgressRect
.left
+ nProgressWidth
;
1013 return ImplDrawTheme( hTheme
, hDC
, PP_CHUNK
, iState
, aProgressRect
, aCaption
);
1016 if( nType
== CTRL_SLIDER
)
1018 iPart
= (nPart
== PART_TRACK_HORZ_AREA
) ? TKP_TRACK
: TKP_TRACKVERT
;
1019 iState
= (nPart
== PART_TRACK_HORZ_AREA
) ? static_cast<int>(TRS_NORMAL
) : static_cast<int>(TRVS_NORMAL
);
1021 Rectangle aTrackRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, Rectangle() );
1023 if( nPart
== PART_TRACK_HORZ_AREA
)
1025 long nH
= aTrackRect
.GetHeight();
1026 aTRect
.top
+= (rc
.bottom
- rc
.top
- nH
)/2;
1027 aTRect
.bottom
= aTRect
.top
+ nH
;
1031 long nW
= aTrackRect
.GetWidth();
1032 aTRect
.left
+= (rc
.right
- rc
.left
- nW
)/2;
1033 aTRect
.right
= aTRect
.left
+ nW
;
1035 ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aTRect
, aCaption
);
1038 OSL_ASSERT( aValue
.getType() == CTRL_SLIDER
);
1039 const SliderValue
* pVal
= static_cast<const SliderValue
*>(&aValue
);
1040 aThumbRect
.left
= pVal
->maThumbRect
.Left();
1041 aThumbRect
.top
= pVal
->maThumbRect
.Top();
1042 aThumbRect
.right
= pVal
->maThumbRect
.Right();
1043 aThumbRect
.bottom
= pVal
->maThumbRect
.Bottom();
1044 iPart
= (nPart
== PART_TRACK_HORZ_AREA
) ? TKP_THUMB
: TKP_THUMBVERT
;
1045 iState
= (nState
& ControlState::ENABLED
) ? TUS_NORMAL
: TUS_DISABLED
;
1046 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, aThumbRect
, aCaption
);
1049 if( nType
== CTRL_LISTNODE
)
1051 if( nPart
!= PART_ENTIRE_CONTROL
)
1054 ButtonValue aButtonValue
= aValue
.getTristateVal();
1056 switch( aButtonValue
)
1058 case BUTTONVALUE_ON
:
1059 iState
= GLPS_OPENED
;
1061 case BUTTONVALUE_OFF
:
1062 iState
= GLPS_CLOSED
;
1067 return ImplDrawTheme( hTheme
, hDC
, iPart
, iState
, rc
, aCaption
);
1070 if( GetSalData()->mbThemeMenuSupport
)
1072 if( nType
== CTRL_MENU_POPUP
)
1074 if( nPart
== PART_ENTIRE_CONTROL
)
1076 RECT aGutterRC
= rc
;
1077 if( AllSettings::GetLayoutRTL() )
1079 aGutterRC
.right
-= aValue
.getNumericVal()+1;
1080 aGutterRC
.left
= aGutterRC
.right
-3;
1084 aGutterRC
.left
+= aValue
.getNumericVal();
1085 aGutterRC
.right
= aGutterRC
.left
+3;
1088 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPBACKGROUND
, 0, rc
, aCaption
) &&
1089 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPGUTTER
, 0, aGutterRC
, aCaption
)
1092 else if( nPart
== PART_MENU_ITEM
)
1094 if( (nState
& ControlState::ENABLED
) )
1095 iState
= (nState
& ControlState::SELECTED
) ? MPI_HOT
: MPI_NORMAL
;
1097 iState
= (nState
& ControlState::SELECTED
) ? MPI_DISABLEDHOT
: MPI_DISABLED
;
1098 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPITEM
, iState
, rc
, aCaption
);
1100 else if( nPart
== PART_MENU_ITEM_CHECK_MARK
|| nPart
== PART_MENU_ITEM_RADIO_MARK
)
1102 if( (nState
& ControlState::PRESSED
) )
1105 if( aValue
.getType() == CTRL_MENU_POPUP
)
1107 const MenupopupValue
& rMVal( static_cast<const MenupopupValue
&>(aValue
) );
1108 aBGRect
.top
= rMVal
.maItemRect
.Top();
1109 aBGRect
.bottom
= rMVal
.maItemRect
.Bottom()+1; // see below in drawNativeControl
1110 if( AllSettings::GetLayoutRTL() )
1112 aBGRect
.right
= rMVal
.maItemRect
.Right()+1;
1113 aBGRect
.left
= aBGRect
.right
- (rMVal
.getNumericVal()-rMVal
.maItemRect
.Left());
1117 aBGRect
.right
= rMVal
.getNumericVal();
1118 aBGRect
.left
= rMVal
.maItemRect
.Left();
1122 iState
= (nState
& ControlState::ENABLED
) ? MCB_NORMAL
: MCB_DISABLED
;
1123 ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECKBACKGROUND
, iState
, aBGRect
, aCaption
);
1124 if( nPart
== PART_MENU_ITEM_CHECK_MARK
)
1125 iState
= (nState
& ControlState::ENABLED
) ? MC_CHECKMARKNORMAL
: MC_CHECKMARKDISABLED
;
1127 iState
= (nState
& ControlState::ENABLED
) ? MC_BULLETNORMAL
: MC_BULLETDISABLED
;
1128 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPCHECK
, iState
, rc
, aCaption
);
1131 return true; // unchecked: do nothing
1133 else if( nPart
== PART_MENU_SEPARATOR
)
1135 // adjust for gutter position
1136 if( AllSettings::GetLayoutRTL() )
1137 rc
.right
-= aValue
.getNumericVal()+1;
1139 rc
.left
+= aValue
.getNumericVal()+1;
1140 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1141 MENU_POPUPSEPARATOR
, 0, Rectangle( rc
.left
, rc
.top
, rc
.right
, rc
.bottom
) ) );
1142 // center the separator inside the passed rectangle
1143 long nDY
= ((rc
.bottom
- rc
.top
+ 1) - aRect
.GetHeight()) / 2;
1145 rc
.bottom
= rc
.top
+aRect
.GetHeight()-1;
1146 return ImplDrawTheme( hTheme
, hDC
, MENU_POPUPSEPARATOR
, 0, rc
, aCaption
);
1155 * DrawNativeControl()
1157 * Draws the requested control described by nPart/nState.
1159 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
1160 * aValue: An optional value (tristate/numerical/string)
1161 * aCaption: A caption or title string (like button text etc)
1163 bool WinSalGraphics::drawNativeControl( ControlType nType
,
1165 const Rectangle
& rControlRegion
,
1166 ControlState nState
,
1167 const ImplControlValue
& aValue
,
1168 const OUString
& aCaption
)
1171 HTHEME hTheme
= NULL
;
1173 Rectangle buttonRect
= rControlRegion
;
1175 WinOpenGLSalGraphicsImpl
* pImpl
= dynamic_cast<WinOpenGLSalGraphicsImpl
*>(mpImpl
.get());
1177 ControlCacheKey
aControlCacheKey(nType
, nPart
, nState
, buttonRect
.GetSize());
1178 if (pImpl
!= NULL
&& pImpl
->TryRenderCachedNativeControl(aControlCacheKey
, buttonRect
.Left(), buttonRect
.Top()))
1185 case CTRL_PUSHBUTTON
:
1186 case CTRL_RADIOBUTTON
:
1188 hTheme
= getThemeHandle( mhWnd
, L
"Button");
1190 case CTRL_SCROLLBAR
:
1191 hTheme
= getThemeHandle( mhWnd
, L
"Scrollbar");
1194 if( nPart
== PART_ENTIRE_CONTROL
)
1195 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1196 else if( nPart
== PART_BUTTON_DOWN
)
1197 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1200 if( nPart
== PART_ENTIRE_CONTROL
)
1201 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1203 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1205 case CTRL_SPINBUTTONS
:
1206 hTheme
= getThemeHandle( mhWnd
, L
"Spin");
1209 case CTRL_MULTILINE_EDITBOX
:
1210 hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1213 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_WINDOW
)
1214 hTheme
= getThemeHandle( mhWnd
, L
"Listview");
1215 else if( nPart
== PART_BUTTON_DOWN
)
1216 hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1221 hTheme
= getThemeHandle( mhWnd
, L
"Tab");
1224 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_BUTTON
)
1225 hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1227 // use rebar for grip and background
1228 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1231 if( nPart
== PART_ENTIRE_CONTROL
)
1232 hTheme
= getThemeHandle( mhWnd
, L
"Rebar");
1233 else if( GetSalData()->mbThemeMenuSupport
)
1235 if( nPart
== PART_MENU_ITEM
)
1236 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1240 if( nPart
== PART_ENTIRE_CONTROL
)
1241 hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1244 if( nPart
== PART_ENTIRE_CONTROL
)
1245 hTheme
= getThemeHandle( mhWnd
, L
"TreeView");
1248 if( nPart
== PART_TRACK_HORZ_AREA
|| nPart
== PART_TRACK_VERT_AREA
)
1249 hTheme
= getThemeHandle( mhWnd
, L
"Trackbar" );
1251 case CTRL_MENU_POPUP
:
1252 if( GetSalData()->mbThemeMenuSupport
)
1254 if( nPart
== PART_ENTIRE_CONTROL
|| nPart
== PART_MENU_ITEM
||
1255 nPart
== PART_MENU_ITEM_CHECK_MARK
|| nPart
== PART_MENU_ITEM_RADIO_MARK
||
1256 nPart
== PART_MENU_SEPARATOR
1258 hTheme
= getThemeHandle( mhWnd
, L
"Menu" );
1270 rc
.left
= buttonRect
.Left();
1271 rc
.right
= buttonRect
.Right()+1;
1272 rc
.top
= buttonRect
.Top();
1273 rc
.bottom
= buttonRect
.Bottom()+1;
1275 OUString
aCaptionStr(aCaption
.replace('~', '&')); // translate mnemonics
1279 // set default text alignment
1280 int ta
= SetTextAlign(getHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1282 bOk
= ImplDrawNativeControl(getHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
);
1284 // restore alignment
1285 SetTextAlign(getHDC(), ta
);
1290 OpenGLCompatibleDC
aBlackDC(*this, buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight());
1291 SetTextAlign(aBlackDC
.getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1292 aBlackDC
.fill(MAKE_SALCOLOR(0, 0, 0));
1294 OpenGLCompatibleDC
aWhiteDC(*this, buttonRect
.Left(), buttonRect
.Top(), buttonRect
.GetWidth(), buttonRect
.GetHeight());
1295 SetTextAlign(aWhiteDC
.getCompatibleHDC(), TA_LEFT
|TA_TOP
|TA_NOUPDATECP
);
1296 aWhiteDC
.fill(MAKE_SALCOLOR(0xff, 0xff, 0xff));
1298 if (ImplDrawNativeControl(aBlackDC
.getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
) &&
1299 ImplDrawNativeControl(aWhiteDC
.getCompatibleHDC(), hTheme
, rc
, nType
, nPart
, nState
, aValue
, aCaptionStr
))
1301 bOk
= pImpl
->RenderAndCacheNativeControl(aWhiteDC
, aBlackDC
, buttonRect
.Left(), buttonRect
.Top(), aControlCacheKey
);
1309 * GetNativeControlRegion()
1311 * If the return value is TRUE, rNativeBoundingRegion
1312 * contains the true bounding region covered by the control
1313 * including any adornment, while rNativeContentRegion contains the area
1314 * within the control that can be safely drawn into without drawing over
1315 * the borders of the control.
1317 * rControlRegion: The bounding region of the control in VCL frame coordinates.
1318 * aValue: An optional value (tristate/numerical/string)
1319 * aCaption: A caption or title string (like button text etc)
1321 bool WinSalGraphics::getNativeControlRegion( ControlType nType
,
1323 const Rectangle
& rControlRegion
,
1324 ControlState nState
,
1325 const ImplControlValue
& rControlValue
,
1327 Rectangle
&rNativeBoundingRegion
,
1328 Rectangle
&rNativeContentRegion
)
1332 HDC hDC
= GetDC( mhWnd
);
1333 if( nType
== CTRL_TOOLBAR
)
1335 if( nPart
== PART_THUMB_HORZ
|| nPart
== PART_THUMB_VERT
)
1338 // the vertical gripper is not supported in most themes and it makes no
1339 // sense to only support horizontal gripper
1341 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1344 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER,
1345 0, rControlRegion.GetBoundRect() ) );
1346 if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() )
1348 Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1349 rNativeContentRegion = aVertRect;
1352 rNativeContentRegion = aRect;
1353 rNativeBoundingRegion = rNativeContentRegion;
1354 if( !rNativeContentRegion.IsEmpty() )
1359 if( nPart
== PART_BUTTON
)
1361 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Toolbar");
1364 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, TP_SPLITBUTTONDROPDOWN
,
1365 TS_HOT
, rControlRegion
) );
1366 rNativeContentRegion
= aRect
;
1367 rNativeBoundingRegion
= rNativeContentRegion
;
1368 if( !rNativeContentRegion
.IsEmpty() )
1373 if( nType
== CTRL_PROGRESS
&& nPart
== PART_ENTIRE_CONTROL
)
1375 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Progress");
1378 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, PP_BAR
,
1379 0, rControlRegion
) );
1380 rNativeContentRegion
= aRect
;
1381 rNativeBoundingRegion
= rNativeContentRegion
;
1382 if( !rNativeContentRegion
.IsEmpty() )
1386 if( (nType
== CTRL_LISTBOX
|| nType
== CTRL_COMBOBOX
) && nPart
== PART_ENTIRE_CONTROL
)
1388 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Combobox");
1391 Rectangle
aBoxRect( rControlRegion
);
1392 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, CP_DROPDOWNBUTTON
,
1393 CBXS_NORMAL
, aBoxRect
) );
1394 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1395 aBoxRect
.Bottom() = aBoxRect
.Top() + aRect
.GetHeight();
1396 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1397 aBoxRect
.Right() = aBoxRect
.Left() + aRect
.GetWidth();
1398 rNativeContentRegion
= aBoxRect
;
1399 rNativeBoundingRegion
= rNativeContentRegion
;
1400 if( !aRect
.IsEmpty() )
1405 if( (nType
== CTRL_EDITBOX
|| nType
== CTRL_SPINBOX
) && nPart
== PART_ENTIRE_CONTROL
)
1407 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Edit");
1411 Rectangle
aBoxRect( rControlRegion
);
1412 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
, EP_BACKGROUNDWITHBORDER
,
1413 EBWBS_HOT
, aBoxRect
) );
1414 // ad app font height
1415 NONCLIENTMETRICSW aNonClientMetrics
;
1416 aNonClientMetrics
.cbSize
= sizeof( aNonClientMetrics
);
1417 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS
, sizeof( aNonClientMetrics
), &aNonClientMetrics
, 0 ) )
1419 long nFontHeight
= aNonClientMetrics
.lfMessageFont
.lfHeight
;
1420 if( nFontHeight
< 0 )
1421 nFontHeight
= -nFontHeight
;
1423 if( aRect
.GetHeight() && nFontHeight
)
1425 aRect
.Bottom() += aRect
.GetHeight();
1426 aRect
.Bottom() += nFontHeight
;
1427 if( aRect
.GetHeight() > aBoxRect
.GetHeight() )
1428 aBoxRect
.Bottom() = aBoxRect
.Top() + aRect
.GetHeight();
1429 if( aRect
.GetWidth() > aBoxRect
.GetWidth() )
1430 aBoxRect
.Right() = aBoxRect
.Left() + aRect
.GetWidth();
1431 rNativeContentRegion
= aBoxRect
;
1432 rNativeBoundingRegion
= rNativeContentRegion
;
1439 if( GetSalData()->mbThemeMenuSupport
)
1441 if( nType
== CTRL_MENU_POPUP
)
1443 if( nPart
== PART_MENU_ITEM_CHECK_MARK
||
1444 nPart
== PART_MENU_ITEM_RADIO_MARK
)
1446 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Menu");
1447 Rectangle
aBoxRect( rControlRegion
);
1448 Rectangle
aRect( ImplGetThemeRect( hTheme
, hDC
,
1452 if( aBoxRect
.GetWidth() && aBoxRect
.GetHeight() )
1454 rNativeContentRegion
= aRect
;
1455 rNativeBoundingRegion
= rNativeContentRegion
;
1462 if( nType
== CTRL_SLIDER
&& ( (nPart
== PART_THUMB_HORZ
) || (nPart
== PART_THUMB_VERT
) ) )
1464 HTHEME hTheme
= getThemeHandle( mhWnd
, L
"Trackbar");
1467 int iPart
= (nPart
== PART_THUMB_HORZ
) ? TKP_THUMB
: TKP_THUMBVERT
;
1468 int iState
= (nPart
== PART_THUMB_HORZ
) ? static_cast<int>(TUS_NORMAL
) : static_cast<int>(TUVS_NORMAL
);
1469 Rectangle aThumbRect
= ImplGetThemeRect( hTheme
, hDC
, iPart
, iState
, Rectangle() );
1470 if( nPart
== PART_THUMB_HORZ
)
1472 long nW
= aThumbRect
.GetWidth();
1473 Rectangle
aRect( rControlRegion
);
1474 aRect
.Right() = aRect
.Left() + nW
- 1;
1475 rNativeContentRegion
= aRect
;
1476 rNativeBoundingRegion
= rNativeContentRegion
;
1480 long nH
= aThumbRect
.GetHeight();
1481 Rectangle
aRect( rControlRegion
);
1482 aRect
.Bottom() = aRect
.Top() + nH
- 1;
1483 rNativeContentRegion
= aRect
;
1484 rNativeBoundingRegion
= rNativeContentRegion
;
1490 if ( ( nType
== CTRL_TAB_ITEM
) && ( nPart
== PART_ENTIRE_CONTROL
) )
1492 Rectangle
aControlRect( rControlRegion
);
1493 rNativeContentRegion
= aControlRect
;
1495 --aControlRect
.Bottom();
1497 if( rControlValue
.getType() == CTRL_TAB_ITEM
)
1499 const TabitemValue
*pValue
= static_cast<const TabitemValue
*>(&rControlValue
);
1500 if ( pValue
->isBothAligned() )
1501 --aControlRect
.Right();
1503 if ( nState
& ControlState::SELECTED
)
1505 aControlRect
.Left() -= 2;
1506 if ( pValue
&& !pValue
->isBothAligned() )
1508 if ( pValue
->isLeftAligned() || pValue
->isNotAligned() )
1509 aControlRect
.Right() += 2;
1510 if ( pValue
->isRightAligned() )
1511 aControlRect
.Right() += 1;
1513 aControlRect
.Top() -= 2;
1514 aControlRect
.Bottom() += 2;
1517 rNativeBoundingRegion
= aControlRect
;
1521 ReleaseDC( mhWnd
, hDC
);
1525 void WinSalGraphics::updateSettingsNative( AllSettings
& rSettings
)
1527 if ( !vsAPI
.IsThemeActive() )
1530 StyleSettings aStyleSettings
= rSettings
.GetStyleSettings();
1531 ImplSVData
* pSVData
= ImplGetSVData();
1533 // don't draw frame around each and every toolbar
1534 pSVData
->maNWFData
.mbDockingAreaAvoidTBFrames
= true;
1536 // check if vista or newer runs
1537 // in Aero theme (and similar ?) the menu text color does not change
1538 // for selected items; also on WinXP and earlier menus are not themed
1539 // FIXME get the color directly from the theme, not from the settings
1540 if (aSalShlData
.mbWVista
)
1542 Color aMenuBarTextColor
= aStyleSettings
.GetPersonaMenuBarTextColor().get_value_or( aStyleSettings
.GetMenuTextColor() );
1543 // in aero menuitem highlight text is drawn in the same color as normal
1544 aStyleSettings
.SetMenuHighlightTextColor( aStyleSettings
.GetMenuTextColor() );
1545 aStyleSettings
.SetMenuBarRolloverTextColor( aMenuBarTextColor
);
1546 aStyleSettings
.SetMenuBarHighlightTextColor( aMenuBarTextColor
);
1547 pSVData
->maNWFData
.mnMenuFormatBorderX
= 2;
1548 pSVData
->maNWFData
.mnMenuFormatBorderY
= 2;
1549 pSVData
->maNWFData
.maMenuBarHighlightTextColor
= aMenuBarTextColor
;
1550 GetSalData()->mbThemeMenuSupport
= TRUE
;
1553 rSettings
.SetStyleSettings( aStyleSettings
);
1556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */