Bump version to 4.1-6
[LibreOffice.git] / vcl / win / source / gdi / salnativewidgets-luna.cxx
blob796cbb33bb5767da6ed22735d29086707ad4c15d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 // General info:
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)
28 // Theme subclasses:
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 "vcl/svapp.hxx"
40 #include "win/svsys.h"
41 #include "win/salgdi.h"
42 #include "win/saldata.hxx"
44 #include "uxtheme.h"
45 #include "vssym32.h"
47 #include <map>
48 #include <string>
50 using namespace std;
53 typedef map< wstring, HTHEME > ThemeMap;
54 static ThemeMap aThemeMap;
57 /****************************************************
58 wrap visual styles API to avoid linking against it
59 it is not available on all Windows platforms
60 *****************************************************/
62 class VisualStylesAPI
64 private:
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;
81 oslModule mhModule;
83 public:
84 VisualStylesAPI();
85 ~VisualStylesAPI();
86 sal_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 );
94 BOOL IsThemeActive( void );
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 );
111 if ( mhModule )
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()
125 if( mhModule )
126 osl_unloadModule( mhModule );
129 HTHEME VisualStylesAPI::OpenThemeData( HWND hwnd, LPCWSTR pszClassList )
131 if(lpfnOpenThemeData)
132 return (*lpfnOpenThemeData) (hwnd, pszClassList);
133 else
134 return NULL;
137 HRESULT VisualStylesAPI::CloseThemeData( HTHEME hTheme )
139 if(lpfnCloseThemeData)
140 return (*lpfnCloseThemeData) (hTheme);
141 else
142 return S_FALSE;
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 );
149 else
150 return S_FALSE;
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);
157 else
158 return S_FALSE;
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);
165 else
166 return S_FALSE;
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);
173 else
174 return S_FALSE;
177 BOOL VisualStylesAPI::IsThemeActive( void )
179 if(lpfnIsThemeActive)
180 return (*lpfnIsThemeActive) ();
181 else
182 return FALSE;
185 /*********************************************************
186 * Initialize XP theming and local stuff
187 *********************************************************/
188 void SalData::initNWF( void )
190 ImplSVData* pSVData = ImplGetSVData();
192 // the menu bar and the top docking area should have a common background (gradient)
193 pSVData->maNWFData.mbMenuBarDockingAreaCommonBG = true;
197 // *********************************************************
198 // * Release theming handles
199 // ********************************************************
200 void SalData::deInitNWF( void )
202 ThemeMap::iterator iter = aThemeMap.begin();
203 while( iter != aThemeMap.end() )
205 vsAPI.CloseThemeData(iter->second);
206 ++iter;
208 aThemeMap.clear();
209 if( maDwmLib )
210 osl_unloadModule( maDwmLib );
213 static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name )
215 if( GetSalData()->mbThemeChanged )
217 // throw away invalid theme handles
218 GetSalData()->deInitNWF();
219 GetSalData()->mbThemeChanged = FALSE;
222 ThemeMap::iterator iter;
223 if( (iter = aThemeMap.find( name )) != aThemeMap.end() )
224 return iter->second;
225 // theme not found -> add it to map
226 HTHEME hTheme = vsAPI.OpenThemeData( hWnd, name );
227 if( hTheme != NULL )
228 aThemeMap[name] = hTheme;
229 return hTheme;
233 * IsNativeControlSupported()
235 * Returns TRUE if the platform supports native
236 * drawing of the control defined by nPart
238 sal_Bool WinSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
240 HTHEME hTheme = NULL;
242 switch( nType )
244 case CTRL_PUSHBUTTON:
245 case CTRL_RADIOBUTTON:
246 case CTRL_CHECKBOX:
247 if( nPart == PART_ENTIRE_CONTROL )
248 hTheme = getThemeHandle( mhWnd, L"Button");
249 break;
250 case CTRL_SCROLLBAR:
251 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
252 return FALSE; // no background painting needed
253 if( nPart == PART_ENTIRE_CONTROL )
254 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
255 break;
256 case CTRL_COMBOBOX:
257 if( nPart == HAS_BACKGROUND_TEXTURE )
258 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
259 if( nPart == PART_ENTIRE_CONTROL )
260 hTheme = getThemeHandle( mhWnd, L"Edit");
261 else if( nPart == PART_BUTTON_DOWN )
262 hTheme = getThemeHandle( mhWnd, L"Combobox");
263 break;
264 case CTRL_SPINBOX:
265 if( nPart == PART_ENTIRE_CONTROL )
266 hTheme = getThemeHandle( mhWnd, L"Edit");
267 else if( nPart == PART_ALL_BUTTONS ||
268 nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN ||
269 nPart == PART_BUTTON_LEFT|| nPart == PART_BUTTON_RIGHT )
270 hTheme = getThemeHandle( mhWnd, L"Spin");
271 break;
272 case CTRL_SPINBUTTONS:
273 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_ALL_BUTTONS )
274 hTheme = getThemeHandle( mhWnd, L"Spin");
275 break;
276 case CTRL_EDITBOX:
277 case CTRL_MULTILINE_EDITBOX:
278 if( nPart == HAS_BACKGROUND_TEXTURE )
279 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
280 //return TRUE;
281 if( nPart == PART_ENTIRE_CONTROL )
282 hTheme = getThemeHandle( mhWnd, L"Edit");
283 break;
284 case CTRL_LISTBOX:
285 if( nPart == HAS_BACKGROUND_TEXTURE )
286 return FALSE; // we do not paint the inner part (ie the selection background/focus indication)
287 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
288 hTheme = getThemeHandle( mhWnd, L"Listview");
289 else if( nPart == PART_BUTTON_DOWN )
290 hTheme = getThemeHandle( mhWnd, L"Combobox");
291 break;
292 case CTRL_TAB_PANE:
293 case CTRL_TAB_BODY:
294 case CTRL_TAB_ITEM:
295 if( nPart == PART_ENTIRE_CONTROL )
296 hTheme = getThemeHandle( mhWnd, L"Tab");
297 break;
298 case CTRL_TOOLBAR:
299 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
300 hTheme = getThemeHandle( mhWnd, L"Toolbar");
301 else
302 // use rebar theme for grip and background
303 hTheme = getThemeHandle( mhWnd, L"Rebar");
304 break;
305 case CTRL_MENUBAR:
306 if( nPart == PART_ENTIRE_CONTROL )
307 hTheme = getThemeHandle( mhWnd, L"Rebar");
308 else if( GetSalData()->mbThemeMenuSupport )
310 if( nPart == PART_MENU_ITEM )
311 hTheme = getThemeHandle( mhWnd, L"Menu" );
313 break;
314 case CTRL_MENU_POPUP:
315 if( GetSalData()->mbThemeMenuSupport )
317 if( nPart == PART_ENTIRE_CONTROL ||
318 nPart == PART_MENU_ITEM ||
319 nPart == PART_MENU_ITEM_CHECK_MARK ||
320 nPart == PART_MENU_ITEM_RADIO_MARK ||
321 nPart == PART_MENU_SEPARATOR )
322 hTheme = getThemeHandle( mhWnd, L"Menu" );
324 break;
325 case CTRL_PROGRESS:
326 if( nPart == PART_ENTIRE_CONTROL )
327 hTheme = getThemeHandle( mhWnd, L"Progress");
328 break;
329 case CTRL_SLIDER:
330 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA )
331 hTheme = getThemeHandle( mhWnd, L"Trackbar" );
332 break;
333 case CTRL_LISTNODE:
334 if( nPart == PART_ENTIRE_CONTROL )
335 hTheme = getThemeHandle( mhWnd, L"TreeView" );
336 break;
337 default:
338 hTheme = NULL;
339 break;
342 return (hTheme != NULL);
347 * HitTestNativeControl()
349 * If the return value is TRUE, bIsInside contains information whether
350 * aPos was or was not inside the native widget specified by the
351 * nType/nPart combination.
353 sal_Bool WinSalGraphics::hitTestNativeControl( ControlType,
354 ControlPart,
355 const Rectangle&,
356 const Point&,
357 sal_Bool& )
359 return FALSE;
362 sal_Bool ImplDrawTheme( HTHEME hTheme, HDC hDC, int iPart, int iState, RECT rc, const OUString& aStr)
364 HRESULT hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
366 if( aStr.getLength() )
368 RECT rcContent;
369 hr = vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, iPart, iState, &rc, &rcContent);
370 hr = vsAPI.DrawThemeText( hTheme, hDC, iPart, iState,
371 reinterpret_cast<LPCWSTR>(aStr.getStr()), -1,
372 DT_CENTER | DT_VCENTER | DT_SINGLELINE,
373 0, &rcContent);
375 return (hr == S_OK);
379 Rectangle ImplGetThemeRect( HTHEME hTheme, HDC hDC, int iPart, int iState, const Rectangle& /* aRect */, THEMESIZE eTS = TS_TRUE )
381 SIZE aSz;
382 HRESULT hr = vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, NULL, eTS, &aSz ); // TS_TRUE returns optimal size
383 if( hr == S_OK )
384 return Rectangle( 0, 0, aSz.cx, aSz.cy );
385 else
386 return Rectangle();
389 // Helper functions
390 // ----
392 void ImplConvertSpinbuttonValues( int nControlPart, const ControlState& rState, const Rectangle& rRect,
393 int* pLunaPart, int *pLunaState, RECT *pRect )
395 if( nControlPart == PART_BUTTON_DOWN )
397 *pLunaPart = SPNP_DOWN;
398 if( rState & CTRL_STATE_PRESSED )
399 *pLunaState = DNS_PRESSED;
400 else if( !(rState & CTRL_STATE_ENABLED) )
401 *pLunaState = DNS_DISABLED;
402 else if( rState & CTRL_STATE_ROLLOVER )
403 *pLunaState = DNS_HOT;
404 else
405 *pLunaState = DNS_NORMAL;
407 if( nControlPart == PART_BUTTON_UP )
409 *pLunaPart = SPNP_UP;
410 if( rState & CTRL_STATE_PRESSED )
411 *pLunaState = UPS_PRESSED;
412 else if( !(rState & CTRL_STATE_ENABLED) )
413 *pLunaState = UPS_DISABLED;
414 else if( rState & CTRL_STATE_ROLLOVER )
415 *pLunaState = UPS_HOT;
416 else
417 *pLunaState = UPS_NORMAL;
419 if( nControlPart == PART_BUTTON_RIGHT )
421 *pLunaPart = SPNP_UPHORZ;
422 if( rState & CTRL_STATE_PRESSED )
423 *pLunaState = DNHZS_PRESSED;
424 else if( !(rState & CTRL_STATE_ENABLED) )
425 *pLunaState = DNHZS_DISABLED;
426 else if( rState & CTRL_STATE_ROLLOVER )
427 *pLunaState = DNHZS_HOT;
428 else
429 *pLunaState = DNHZS_NORMAL;
431 if( nControlPart == PART_BUTTON_LEFT )
433 *pLunaPart = SPNP_DOWNHORZ;
434 if( rState & CTRL_STATE_PRESSED )
435 *pLunaState = UPHZS_PRESSED;
436 else if( !(rState & CTRL_STATE_ENABLED) )
437 *pLunaState = UPHZS_DISABLED;
438 else if( rState & CTRL_STATE_ROLLOVER )
439 *pLunaState = UPHZS_HOT;
440 else
441 *pLunaState = UPHZS_NORMAL;
444 pRect->left = rRect.Left();
445 pRect->right = rRect.Right()+1;
446 pRect->top = rRect.Top();
447 pRect->bottom = rRect.Bottom()+1;
450 /// Draw an own toolbar style on Windows Vista or later, looks better there
451 static void impl_drawAeroToolbar( HDC hDC, RECT rc, bool bHorizontal )
453 if ( rc.top == 0 && bHorizontal )
455 const long GRADIENT_HEIGHT = 32;
457 long gradient_break = rc.top;
458 long gradient_bottom = rc.bottom - 1;
459 GRADIENT_RECT g_rect[1] = { { 0, 1 } };
461 // very slow gradient at the top (if we have space for that)
462 if ( gradient_bottom - rc.top > GRADIENT_HEIGHT )
464 gradient_break = gradient_bottom - GRADIENT_HEIGHT;
466 TRIVERTEX vert[2] = {
467 { rc.left, rc.top, 0xff00, 0xff00, 0xff00, 0xff00 },
468 { rc.right, gradient_break, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
470 GradientFill( hDC, vert, 2, g_rect, 1, GRADIENT_FILL_RECT_V );
473 // gradient at the bottom
474 TRIVERTEX vert[2] = {
475 { rc.left, gradient_break, 0xfa00, 0xfa00, 0xfa00, 0xff00 },
476 { rc.right, gradient_bottom, 0xf000, 0xf000, 0xf000, 0xff00 }
478 GradientFill( hDC, vert, 2, g_rect, 1, GRADIENT_FILL_RECT_V );
480 // and a darker horizontal line under that
481 HPEN hpen = CreatePen( PS_SOLID, 1, RGB( 0xa0, 0xa0, 0xa0 ) );
482 SelectObject( hDC, hpen );
484 MoveToEx( hDC, rc.left, gradient_bottom, NULL );
485 LineTo( hDC, rc.right, gradient_bottom );
487 DeleteObject( hpen );
489 else
491 HBRUSH hbrush = CreateSolidBrush( RGB( 0xf0, 0xf0, 0xf0 ) );
492 FillRect( hDC, &rc, hbrush );
493 DeleteObject( hbrush );
495 // darker line to distinguish the toolbar and viewshell
496 // it is drawn only for the horizontal toolbars; it did not look well
497 // when done for the vertical ones too
498 if ( bHorizontal )
500 long from_x, from_y, to_x, to_y;
502 from_x = rc.left;
503 to_x = rc.right;
504 from_y = to_y = rc.top;
506 HPEN hpen = CreatePen( PS_SOLID, 1, RGB( 0xa0, 0xa0, 0xa0 ) );
507 SelectObject( hDC, hpen );
509 MoveToEx( hDC, from_x, from_y, NULL );
510 LineTo( hDC, to_x, to_y );
512 DeleteObject( hpen );
517 sal_Bool ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc,
518 ControlType nType,
519 ControlPart nPart,
520 ControlState nState,
521 const ImplControlValue& aValue,
522 OUString aCaption )
524 // a listbox dropdown is actually a combobox dropdown
525 if( nType == CTRL_LISTBOX )
526 if( nPart == PART_BUTTON_DOWN )
527 nType = CTRL_COMBOBOX;
529 // draw entire combobox as a large edit box
530 if( nType == CTRL_COMBOBOX )
531 if( nPart == PART_ENTIRE_CONTROL )
532 nType = CTRL_EDITBOX;
534 // draw entire spinbox as a large edit box
535 if( nType == CTRL_SPINBOX )
536 if( nPart == PART_ENTIRE_CONTROL )
537 nType = CTRL_EDITBOX;
539 int iPart(0), iState(0);
540 if( nType == CTRL_SCROLLBAR )
542 HRESULT hr;
543 if( nPart == PART_BUTTON_UP )
545 iPart = SBP_ARROWBTN;
546 if( nState & CTRL_STATE_PRESSED )
547 iState = ABS_UPPRESSED;
548 else if( !(nState & CTRL_STATE_ENABLED) )
549 iState = ABS_UPDISABLED;
550 else if( nState & CTRL_STATE_ROLLOVER )
551 iState = ABS_UPHOT;
552 else
553 iState = ABS_UPNORMAL;
554 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
555 return (hr == S_OK);
557 if( nPart == PART_BUTTON_DOWN )
559 iPart = SBP_ARROWBTN;
560 if( nState & CTRL_STATE_PRESSED )
561 iState = ABS_DOWNPRESSED;
562 else if( !(nState & CTRL_STATE_ENABLED) )
563 iState = ABS_DOWNDISABLED;
564 else if( nState & CTRL_STATE_ROLLOVER )
565 iState = ABS_DOWNHOT;
566 else
567 iState = ABS_DOWNNORMAL;
568 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
569 return (hr == S_OK);
571 if( nPart == PART_BUTTON_LEFT )
573 iPart = SBP_ARROWBTN;
574 if( nState & CTRL_STATE_PRESSED )
575 iState = ABS_LEFTPRESSED;
576 else if( !(nState & CTRL_STATE_ENABLED) )
577 iState = ABS_LEFTDISABLED;
578 else if( nState & CTRL_STATE_ROLLOVER )
579 iState = ABS_LEFTHOT;
580 else
581 iState = ABS_LEFTNORMAL;
582 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
583 return (hr == S_OK);
585 if( nPart == PART_BUTTON_RIGHT )
587 iPart = SBP_ARROWBTN;
588 if( nState & CTRL_STATE_PRESSED )
589 iState = ABS_RIGHTPRESSED;
590 else if( !(nState & CTRL_STATE_ENABLED) )
591 iState = ABS_RIGHTDISABLED;
592 else if( nState & CTRL_STATE_ROLLOVER )
593 iState = ABS_RIGHTHOT;
594 else
595 iState = ABS_RIGHTNORMAL;
596 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
597 return (hr == S_OK);
599 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
601 iPart = (nPart == PART_THUMB_HORZ) ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
602 if( nState & CTRL_STATE_PRESSED )
603 iState = SCRBS_PRESSED;
604 else if( !(nState & CTRL_STATE_ENABLED) )
605 iState = SCRBS_DISABLED;
606 else if( nState & CTRL_STATE_ROLLOVER )
607 iState = SCRBS_HOT;
608 else
609 iState = SCRBS_NORMAL;
611 SIZE sz;
612 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_MIN, &sz);
613 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_TRUE, &sz);
614 vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_DRAW, &sz);
616 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
617 // paint gripper on thumb if enough space
618 if( ( (nPart == PART_THUMB_VERT) && (rc.bottom-rc.top > 12) ) ||
619 ( (nPart == PART_THUMB_HORZ) && (rc.right-rc.left > 12) ) )
621 iPart = (nPart == PART_THUMB_HORZ) ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
622 iState = 0;
623 vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
625 return (hr == S_OK);
627 if( nPart == PART_TRACK_HORZ_LEFT || nPart == PART_TRACK_HORZ_RIGHT || nPart == PART_TRACK_VERT_UPPER || nPart == PART_TRACK_VERT_LOWER )
629 switch( nPart )
631 case PART_TRACK_HORZ_LEFT: iPart = SBP_UPPERTRACKHORZ; break;
632 case PART_TRACK_HORZ_RIGHT: iPart = SBP_LOWERTRACKHORZ; break;
633 case PART_TRACK_VERT_UPPER: iPart = SBP_UPPERTRACKVERT; break;
634 case PART_TRACK_VERT_LOWER: iPart = SBP_LOWERTRACKVERT; break;
637 if( nState & CTRL_STATE_PRESSED )
638 iState = SCRBS_PRESSED;
639 else if( !(nState & CTRL_STATE_ENABLED) )
640 iState = SCRBS_DISABLED;
641 else if( nState & CTRL_STATE_ROLLOVER )
642 iState = SCRBS_HOT;
643 else
644 iState = SCRBS_NORMAL;
645 hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0);
646 return (hr == S_OK);
649 if( nType == CTRL_SPINBUTTONS && nPart == PART_ALL_BUTTONS )
651 if( aValue.getType() == CTRL_SPINBUTTONS )
653 const SpinbuttonValue* pValue = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue*>(&aValue) : NULL;
654 sal_Bool bOk = sal_False;
656 RECT rect;
657 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
658 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
660 if( bOk )
662 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
663 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
666 return bOk;
669 if( nType == CTRL_SPINBOX )
671 // decrease spinbutton rects a little
672 //rc.right--;
673 //rc.bottom--;
674 if( nPart == PART_ALL_BUTTONS )
676 if( aValue.getType() == CTRL_SPINBUTTONS )
678 const SpinbuttonValue *pValue = static_cast<const SpinbuttonValue*>(&aValue);
679 sal_Bool bOk = sal_False;
681 RECT rect;
682 ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect );
683 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
685 if( bOk )
687 ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect );
688 bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption);
691 return bOk;
695 if( nPart == PART_BUTTON_DOWN )
697 iPart = SPNP_DOWN;
698 if( nState & CTRL_STATE_PRESSED )
699 iState = DNS_PRESSED;
700 else if( !(nState & CTRL_STATE_ENABLED) )
701 iState = DNS_DISABLED;
702 else if( nState & CTRL_STATE_ROLLOVER )
703 iState = DNS_HOT;
704 else
705 iState = DNS_NORMAL;
707 if( nPart == PART_BUTTON_UP )
709 iPart = SPNP_UP;
710 if( nState & CTRL_STATE_PRESSED )
711 iState = UPS_PRESSED;
712 else if( !(nState & CTRL_STATE_ENABLED) )
713 iState = UPS_DISABLED;
714 else if( nState & CTRL_STATE_ROLLOVER )
715 iState = UPS_HOT;
716 else
717 iState = UPS_NORMAL;
719 if( nPart == PART_BUTTON_RIGHT )
721 iPart = SPNP_DOWNHORZ;
722 if( nState & CTRL_STATE_PRESSED )
723 iState = DNHZS_PRESSED;
724 else if( !(nState & CTRL_STATE_ENABLED) )
725 iState = DNHZS_DISABLED;
726 else if( nState & CTRL_STATE_ROLLOVER )
727 iState = DNHZS_HOT;
728 else
729 iState = DNHZS_NORMAL;
731 if( nPart == PART_BUTTON_LEFT )
733 iPart = SPNP_UPHORZ;
734 if( nState & CTRL_STATE_PRESSED )
735 iState = UPHZS_PRESSED;
736 else if( !(nState & CTRL_STATE_ENABLED) )
737 iState = UPHZS_DISABLED;
738 else if( nState & CTRL_STATE_ROLLOVER )
739 iState = UPHZS_HOT;
740 else
741 iState = UPHZS_NORMAL;
743 if( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN )
744 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
746 if( nType == CTRL_COMBOBOX )
748 if( nPart == PART_BUTTON_DOWN )
750 iPart = CP_DROPDOWNBUTTON;
751 if( nState & CTRL_STATE_PRESSED )
752 iState = CBXS_PRESSED;
753 else if( !(nState & CTRL_STATE_ENABLED) )
754 iState = CBXS_DISABLED;
755 else if( nState & CTRL_STATE_ROLLOVER )
756 iState = CBXS_HOT;
757 else
758 iState = CBXS_NORMAL;
759 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
762 if( nType == CTRL_PUSHBUTTON )
764 iPart = BP_PUSHBUTTON;
765 if( nState & CTRL_STATE_PRESSED )
766 iState = PBS_PRESSED;
767 else if( !(nState & CTRL_STATE_ENABLED) )
768 iState = PBS_DISABLED;
769 else if( nState & CTRL_STATE_ROLLOVER )
770 iState = PBS_HOT;
771 else if( nState & CTRL_STATE_DEFAULT )
772 iState = PBS_DEFAULTED;
773 //else if( nState & CTRL_STATE_FOCUSED )
774 // iState = PBS_DEFAULTED; // may need to draw focus rect
775 else
776 iState = PBS_NORMAL;
778 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
781 if( nType == CTRL_RADIOBUTTON )
783 iPart = BP_RADIOBUTTON;
784 sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
786 if( nState & CTRL_STATE_PRESSED )
787 iState = bChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
788 else if( !(nState & CTRL_STATE_ENABLED) )
789 iState = bChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
790 else if( nState & CTRL_STATE_ROLLOVER )
791 iState = bChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
792 else
793 iState = bChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
795 //if( nState & CTRL_STATE_FOCUSED )
796 // iState |= PBS_DEFAULTED; // may need to draw focus rect
798 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
801 if( nType == CTRL_CHECKBOX )
803 iPart = BP_CHECKBOX;
804 ButtonValue v = aValue.getTristateVal();
806 if( nState & CTRL_STATE_PRESSED )
807 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDPRESSED :
808 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED );
809 else if( !(nState & CTRL_STATE_ENABLED) )
810 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDDISABLED :
811 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED );
812 else if( nState & CTRL_STATE_ROLLOVER )
813 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDHOT :
814 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT );
815 else
816 iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDNORMAL :
817 ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL );
819 //if( nState & CTRL_STATE_FOCUSED )
820 // iState |= PBS_DEFAULTED; // may need to draw focus rect
822 //SIZE sz;
823 //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW
824 //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz);
826 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
829 if( ( nType == CTRL_EDITBOX ) || ( nType == CTRL_MULTILINE_EDITBOX ) )
831 iPart = EP_EDITTEXT;
832 if( !(nState & CTRL_STATE_ENABLED) )
833 iState = ETS_DISABLED;
834 else if( nState & CTRL_STATE_FOCUSED )
835 iState = ETS_FOCUSED;
836 else if( nState & CTRL_STATE_ROLLOVER )
837 iState = ETS_HOT;
838 else
839 iState = ETS_NORMAL;
841 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
844 if( nType == CTRL_LISTBOX )
846 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
848 iPart = LVP_EMPTYTEXT; // ??? no idea which part to choose here
849 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
853 if( nType == CTRL_TAB_PANE )
855 iPart = TABP_PANE;
856 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
859 if( nType == CTRL_TAB_BODY )
861 iPart = TABP_BODY;
862 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
865 if( nType == CTRL_TAB_ITEM )
867 iPart = TABP_TABITEMLEFTEDGE;
868 rc.bottom--;
870 OSL_ASSERT( aValue.getType() == CTRL_TAB_ITEM );
872 const TabitemValue *pValue = static_cast<const TabitemValue*>(&aValue);
873 if( pValue->isBothAligned() )
875 iPart = TABP_TABITEMLEFTEDGE;
876 rc.right--;
878 else if( pValue->isLeftAligned() )
879 iPart = TABP_TABITEMLEFTEDGE;
880 else if( pValue->isRightAligned() )
881 iPart = TABP_TABITEMRIGHTEDGE;
882 else iPart = TABP_TABITEM;
884 if( !(nState & CTRL_STATE_ENABLED) )
885 iState = TILES_DISABLED;
886 else if( nState & CTRL_STATE_SELECTED )
888 iState = TILES_SELECTED;
889 // increase the selected tab
890 rc.left-=2;
891 if( pValue && !pValue->isBothAligned() )
893 if( pValue->isLeftAligned() || pValue->isNotAligned() )
894 rc.right+=2;
895 if( pValue->isRightAligned() )
896 rc.right+=1;
898 rc.top-=2;
899 rc.bottom+=2;
901 else if( nState & CTRL_STATE_ROLLOVER )
902 iState = TILES_HOT;
903 else if( nState & CTRL_STATE_FOCUSED )
904 iState = TILES_FOCUSED; // may need to draw focus rect
905 else
906 iState = TILES_NORMAL;
907 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
910 if( nType == CTRL_TOOLBAR )
912 if( nPart == PART_BUTTON )
914 iPart = TP_BUTTON;
915 sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON );
916 if( !(nState & CTRL_STATE_ENABLED) )
917 //iState = TS_DISABLED;
918 // disabled buttons are typically not painted at all but we need visual
919 // feedback when travelling by keyboard over disabled entries
920 iState = TS_HOT;
921 else if( nState & CTRL_STATE_PRESSED )
922 iState = TS_PRESSED;
923 else if( nState & CTRL_STATE_ROLLOVER )
924 iState = bChecked ? TS_HOTCHECKED : TS_HOT;
925 else
926 iState = bChecked ? TS_CHECKED : TS_NORMAL;
927 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
929 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
931 // the vertical gripper is not supported in most themes and it makes no
932 // sense to only support horizontal gripper
933 //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER;
934 //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
936 else if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
938 if( aValue.getType() == CTRL_TOOLBAR )
940 const ToolbarValue *pValue = static_cast<const ToolbarValue*>(&aValue);
941 if( pValue->mbIsTopDockingArea )
942 rc.top = 0; // extend potential gradient to cover menu bar as well
945 // make it more compatible with Aero
946 if( ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
948 impl_drawAeroToolbar( hDC, rc, nPart == PART_DRAW_BACKGROUND_HORZ );
949 return sal_True;
952 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
956 if( nType == CTRL_MENUBAR )
958 if( nPart == PART_ENTIRE_CONTROL )
960 if( aValue.getType() == CTRL_MENUBAR )
962 const MenubarValue *pValue = static_cast<const MenubarValue*>(&aValue);
963 rc.bottom += pValue->maTopDockingAreaHeight; // extend potential gradient to cover docking area as well
965 // make it more compatible with Aero
966 if( ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
968 impl_drawAeroToolbar( hDC, rc, true );
969 return sal_True;
972 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
974 else if( nPart == PART_MENU_ITEM )
976 if( nState & CTRL_STATE_ENABLED )
978 if( nState & CTRL_STATE_SELECTED )
979 iState = MBI_PUSHED;
980 else if( nState & CTRL_STATE_ROLLOVER )
981 iState = MBI_HOT;
982 else
983 iState = MBI_NORMAL;
985 else
987 if( nState & CTRL_STATE_SELECTED )
988 iState = MBI_DISABLEDPUSHED;
989 else if( nState & CTRL_STATE_ROLLOVER )
990 iState = MBI_DISABLEDHOT;
991 else
992 iState = MBI_DISABLED;
994 return ImplDrawTheme( hTheme, hDC, MENU_BARITEM, iState, rc, aCaption );
998 if( nType == CTRL_PROGRESS )
1000 if( nPart != PART_ENTIRE_CONTROL )
1001 return FALSE;
1003 if( ! ImplDrawTheme( hTheme, hDC, PP_BAR, iState, rc, aCaption) )
1004 return false;
1005 RECT aProgressRect = rc;
1006 if( vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, PP_BAR, iState, &rc, &aProgressRect) != S_OK )
1007 return false;
1009 long nProgressWidth = aValue.getNumericVal();
1010 nProgressWidth *= (aProgressRect.right - aProgressRect.left);
1011 nProgressWidth /= (rc.right - rc.left);
1012 if( Application::GetSettings().GetLayoutRTL() )
1013 aProgressRect.left = aProgressRect.right - nProgressWidth;
1014 else
1015 aProgressRect.right = aProgressRect.left + nProgressWidth;
1017 return ImplDrawTheme( hTheme, hDC, PP_CHUNK, iState, aProgressRect, aCaption );
1020 if( nType == CTRL_SLIDER )
1022 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_TRACK : TKP_TRACKVERT;
1023 iState = (nPart == PART_TRACK_HORZ_AREA) ? static_cast<int>(TRS_NORMAL) : static_cast<int>(TRVS_NORMAL);
1025 Rectangle aTrackRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() );
1026 RECT aTRect = rc;
1027 if( nPart == PART_TRACK_HORZ_AREA )
1029 long nH = aTrackRect.GetHeight();
1030 aTRect.top += (rc.bottom - rc.top - nH)/2;
1031 aTRect.bottom = aTRect.top + nH;
1033 else
1035 long nW = aTrackRect.GetWidth();
1036 aTRect.left += (rc.right - rc.left - nW)/2;
1037 aTRect.right = aTRect.left + nW;
1039 ImplDrawTheme( hTheme, hDC, iPart, iState, aTRect, aCaption );
1041 RECT aThumbRect;
1042 OSL_ASSERT( aValue.getType() == CTRL_SLIDER );
1043 const SliderValue* pVal = static_cast<const SliderValue*>(&aValue);
1044 aThumbRect.left = pVal->maThumbRect.Left();
1045 aThumbRect.top = pVal->maThumbRect.Top();
1046 aThumbRect.right = pVal->maThumbRect.Right();
1047 aThumbRect.bottom = pVal->maThumbRect.Bottom();
1048 iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_THUMB : TKP_THUMBVERT;
1049 iState = (nState & CTRL_STATE_ENABLED) ? TUS_NORMAL : TUS_DISABLED;
1050 return ImplDrawTheme( hTheme, hDC, iPart, iState, aThumbRect, aCaption );
1053 if( nType == CTRL_LISTNODE )
1055 if( nPart != PART_ENTIRE_CONTROL )
1056 return FALSE;
1058 ButtonValue aButtonValue = aValue.getTristateVal();
1059 iPart = TVP_GLYPH;
1060 switch( aButtonValue )
1062 case BUTTONVALUE_ON:
1063 iState = GLPS_OPENED;
1064 break;
1065 case BUTTONVALUE_OFF:
1066 iState = GLPS_CLOSED;
1067 break;
1068 default:
1069 return FALSE;
1071 return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption );
1074 if( GetSalData()->mbThemeMenuSupport )
1076 if( nType == CTRL_MENU_POPUP )
1078 if( nPart == PART_ENTIRE_CONTROL )
1080 RECT aGutterRC = rc;
1081 if( Application::GetSettings().GetLayoutRTL() )
1083 aGutterRC.right -= aValue.getNumericVal()+1;
1084 aGutterRC.left = aGutterRC.right-3;
1086 else
1088 aGutterRC.left += aValue.getNumericVal();
1089 aGutterRC.right = aGutterRC.left+3;
1091 return
1092 ImplDrawTheme( hTheme, hDC, MENU_POPUPBACKGROUND, 0, rc, aCaption ) &&
1093 ImplDrawTheme( hTheme, hDC, MENU_POPUPGUTTER, 0, aGutterRC, aCaption )
1096 else if( nPart == PART_MENU_ITEM )
1098 if( (nState & CTRL_STATE_ENABLED) )
1099 iState = (nState & CTRL_STATE_SELECTED) ? MPI_HOT : MPI_NORMAL;
1100 else
1101 iState = (nState & CTRL_STATE_SELECTED) ? MPI_DISABLEDHOT : MPI_DISABLED;
1102 return ImplDrawTheme( hTheme, hDC, MENU_POPUPITEM, iState, rc, aCaption );
1104 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK )
1106 if( (nState & CTRL_STATE_PRESSED) )
1108 RECT aBGRect = rc;
1109 if( aValue.getType() == CTRL_MENU_POPUP )
1111 const MenupopupValue& rMVal( static_cast<const MenupopupValue&>(aValue) );
1112 aBGRect.top = rMVal.maItemRect.Top();
1113 aBGRect.bottom = rMVal.maItemRect.Bottom()+1; // see below in drawNativeControl
1114 if( Application::GetSettings().GetLayoutRTL() )
1116 aBGRect.right = rMVal.maItemRect.Right()+1;
1117 aBGRect.left = aBGRect.right - (rMVal.getNumericVal()-rMVal.maItemRect.Left());
1119 else
1121 aBGRect.right = rMVal.getNumericVal();
1122 aBGRect.left = rMVal.maItemRect.Left();
1124 rc = aBGRect;
1126 iState = (nState & CTRL_STATE_ENABLED) ? MCB_NORMAL : MCB_DISABLED;
1127 ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECKBACKGROUND, iState, aBGRect, aCaption );
1128 if( nPart == PART_MENU_ITEM_CHECK_MARK )
1129 iState = (nState & CTRL_STATE_ENABLED) ? MC_CHECKMARKNORMAL : MC_CHECKMARKDISABLED;
1130 else
1131 iState = (nState & CTRL_STATE_ENABLED) ? MC_BULLETNORMAL : MC_BULLETDISABLED;
1132 return ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECK, iState, rc, aCaption );
1134 else
1135 return true; // unchecked: do nothing
1137 else if( nPart == PART_MENU_SEPARATOR )
1139 // adjust for gutter position
1140 if( Application::GetSettings().GetLayoutRTL() )
1141 rc.right -= aValue.getNumericVal()+1;
1142 else
1143 rc.left += aValue.getNumericVal()+1;
1144 Rectangle aRect( ImplGetThemeRect( hTheme, hDC,
1145 MENU_POPUPSEPARATOR, 0, Rectangle( rc.left, rc.top, rc.right, rc.bottom ) ) );
1146 // center the separator inside the passed rectangle
1147 long nDY = ((rc.bottom - rc.top + 1) - aRect.GetHeight()) / 2;
1148 rc.top += nDY;
1149 rc.bottom = rc.top+aRect.GetHeight()-1;
1150 return ImplDrawTheme( hTheme, hDC, MENU_POPUPSEPARATOR, 0, rc, aCaption );
1155 return false;
1159 * DrawNativeControl()
1161 * Draws the requested control described by nPart/nState.
1163 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
1164 * aValue: An optional value (tristate/numerical/string)
1165 * aCaption: A caption or title string (like button text etc)
1167 sal_Bool WinSalGraphics::drawNativeControl( ControlType nType,
1168 ControlPart nPart,
1169 const Rectangle& rControlRegion,
1170 ControlState nState,
1171 const ImplControlValue& aValue,
1172 const OUString& aCaption )
1174 sal_Bool bOk = false;
1175 HTHEME hTheme = NULL;
1177 switch( nType )
1179 case CTRL_PUSHBUTTON:
1180 case CTRL_RADIOBUTTON:
1181 case CTRL_CHECKBOX:
1182 hTheme = getThemeHandle( mhWnd, L"Button");
1183 break;
1184 case CTRL_SCROLLBAR:
1185 hTheme = getThemeHandle( mhWnd, L"Scrollbar");
1186 break;
1187 case CTRL_COMBOBOX:
1188 if( nPart == PART_ENTIRE_CONTROL )
1189 hTheme = getThemeHandle( mhWnd, L"Edit");
1190 else if( nPart == PART_BUTTON_DOWN )
1191 hTheme = getThemeHandle( mhWnd, L"Combobox");
1192 break;
1193 case CTRL_SPINBOX:
1194 if( nPart == PART_ENTIRE_CONTROL )
1195 hTheme = getThemeHandle( mhWnd, L"Edit");
1196 else
1197 hTheme = getThemeHandle( mhWnd, L"Spin");
1198 break;
1199 case CTRL_SPINBUTTONS:
1200 hTheme = getThemeHandle( mhWnd, L"Spin");
1201 break;
1202 case CTRL_EDITBOX:
1203 case CTRL_MULTILINE_EDITBOX:
1204 hTheme = getThemeHandle( mhWnd, L"Edit");
1205 break;
1206 case CTRL_LISTBOX:
1207 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW )
1208 hTheme = getThemeHandle( mhWnd, L"Listview");
1209 else if( nPart == PART_BUTTON_DOWN )
1210 hTheme = getThemeHandle( mhWnd, L"Combobox");
1211 break;
1212 case CTRL_TAB_PANE:
1213 case CTRL_TAB_BODY:
1214 case CTRL_TAB_ITEM:
1215 hTheme = getThemeHandle( mhWnd, L"Tab");
1216 break;
1217 case CTRL_TOOLBAR:
1218 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON )
1219 hTheme = getThemeHandle( mhWnd, L"Toolbar");
1220 else
1221 // use rebar for grip and background
1222 hTheme = getThemeHandle( mhWnd, L"Rebar");
1223 break;
1224 case CTRL_MENUBAR:
1225 if( nPart == PART_ENTIRE_CONTROL )
1226 hTheme = getThemeHandle( mhWnd, L"Rebar");
1227 else if( GetSalData()->mbThemeMenuSupport )
1229 if( nPart == PART_MENU_ITEM )
1230 hTheme = getThemeHandle( mhWnd, L"Menu" );
1232 break;
1233 case CTRL_PROGRESS:
1234 if( nPart == PART_ENTIRE_CONTROL )
1235 hTheme = getThemeHandle( mhWnd, L"Progress");
1236 break;
1237 case CTRL_LISTNODE:
1238 if( nPart == PART_ENTIRE_CONTROL )
1239 hTheme = getThemeHandle( mhWnd, L"TreeView");
1240 break;
1241 case CTRL_SLIDER:
1242 if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA )
1243 hTheme = getThemeHandle( mhWnd, L"Trackbar" );
1244 break;
1245 case CTRL_MENU_POPUP:
1246 if( GetSalData()->mbThemeMenuSupport )
1248 if( nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM ||
1249 nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ||
1250 nPart == PART_MENU_SEPARATOR
1252 hTheme = getThemeHandle( mhWnd, L"Menu" );
1254 break;
1255 default:
1256 hTheme = NULL;
1257 break;
1260 if( !hTheme )
1261 return false;
1263 Rectangle buttonRect = rControlRegion;
1264 RECT rc;
1265 rc.left = buttonRect.Left();
1266 rc.right = buttonRect.Right()+1;
1267 rc.top = buttonRect.Top();
1268 rc.bottom = buttonRect.Bottom()+1;
1270 // set default text alignment
1271 int ta = SetTextAlign( mhDC, TA_LEFT|TA_TOP|TA_NOUPDATECP );
1273 OUString aCaptionStr( aCaption.replace('~', '&') ); // translate mnemonics
1274 bOk = ImplDrawNativeControl(mhDC, hTheme, rc,
1275 nType, nPart, nState, aValue,
1276 aCaptionStr );
1278 // restore alignment
1279 SetTextAlign( mhDC, ta );
1282 //GdiFlush();
1284 return bOk;
1288 * GetNativeControlRegion()
1290 * If the return value is TRUE, rNativeBoundingRegion
1291 * contains the true bounding region covered by the control
1292 * including any adornment, while rNativeContentRegion contains the area
1293 * within the control that can be safely drawn into without drawing over
1294 * the borders of the control.
1296 * rControlRegion: The bounding region of the control in VCL frame coordinates.
1297 * aValue: An optional value (tristate/numerical/string)
1298 * aCaption: A caption or title string (like button text etc)
1300 sal_Bool WinSalGraphics::getNativeControlRegion( ControlType nType,
1301 ControlPart nPart,
1302 const Rectangle& rControlRegion,
1303 ControlState nState,
1304 const ImplControlValue& rControlValue,
1305 const OUString&,
1306 Rectangle &rNativeBoundingRegion,
1307 Rectangle &rNativeContentRegion )
1309 sal_Bool bRet = FALSE;
1311 HDC hDC = GetDC( mhWnd );
1312 if( nType == CTRL_TOOLBAR )
1314 if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
1317 // the vertical gripper is not supported in most themes and it makes no
1318 // sense to only support horizontal gripper
1320 HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar");
1321 if( hTheme )
1323 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER,
1324 0, rControlRegion.GetBoundRect() ) );
1325 if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() )
1327 Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() );
1328 rNativeContentRegion = aVertRect;
1330 else
1331 rNativeContentRegion = aRect;
1332 rNativeBoundingRegion = rNativeContentRegion;
1333 if( !rNativeContentRegion.IsEmpty() )
1334 bRet = TRUE;
1338 if( nPart == PART_BUTTON )
1340 HTHEME hTheme = getThemeHandle( mhWnd, L"Toolbar");
1341 if( hTheme )
1343 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, TP_SPLITBUTTONDROPDOWN,
1344 TS_HOT, rControlRegion ) );
1345 rNativeContentRegion = aRect;
1346 rNativeBoundingRegion = rNativeContentRegion;
1347 if( !rNativeContentRegion.IsEmpty() )
1348 bRet = TRUE;
1352 if( nType == CTRL_PROGRESS && nPart == PART_ENTIRE_CONTROL )
1354 HTHEME hTheme = getThemeHandle( mhWnd, L"Progress");
1355 if( hTheme )
1357 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, PP_BAR,
1358 0, rControlRegion ) );
1359 rNativeContentRegion = aRect;
1360 rNativeBoundingRegion = rNativeContentRegion;
1361 if( !rNativeContentRegion.IsEmpty() )
1362 bRet = TRUE;
1365 if( (nType == CTRL_LISTBOX || nType == CTRL_COMBOBOX ) && nPart == PART_ENTIRE_CONTROL )
1367 HTHEME hTheme = getThemeHandle( mhWnd, L"Combobox");
1368 if( hTheme )
1370 Rectangle aBoxRect( rControlRegion );
1371 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, CP_DROPDOWNBUTTON,
1372 CBXS_NORMAL, aBoxRect ) );
1373 if( aRect.GetHeight() > aBoxRect.GetHeight() )
1374 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight();
1375 if( aRect.GetWidth() > aBoxRect.GetWidth() )
1376 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth();
1377 rNativeContentRegion = aBoxRect;
1378 rNativeBoundingRegion = rNativeContentRegion;
1379 if( !aRect.IsEmpty() )
1380 bRet = TRUE;
1384 if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL )
1386 HTHEME hTheme = getThemeHandle( mhWnd, L"Edit");
1387 if( hTheme )
1389 // get border size
1390 Rectangle aBoxRect( rControlRegion );
1391 Rectangle aRect( ImplGetThemeRect( hTheme, hDC, EP_BACKGROUNDWITHBORDER,
1392 EBWBS_HOT, aBoxRect ) );
1393 // ad app font height
1394 NONCLIENTMETRICSW aNonClientMetrics;
1395 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
1396 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
1398 long nFontHeight = aNonClientMetrics.lfMessageFont.lfHeight;
1399 if( nFontHeight < 0 )
1400 nFontHeight = -nFontHeight;
1402 if( aRect.GetHeight() && nFontHeight )
1404 aRect.Bottom() += aRect.GetHeight();
1405 aRect.Bottom() += nFontHeight;
1406 if( aRect.GetHeight() > aBoxRect.GetHeight() )
1407 aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight();
1408 if( aRect.GetWidth() > aBoxRect.GetWidth() )
1409 aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth();
1410 rNativeContentRegion = aBoxRect;
1411 rNativeBoundingRegion = rNativeContentRegion;
1412 bRet = TRUE;
1418 if( GetSalData()->mbThemeMenuSupport )
1420 if( nType == CTRL_MENU_POPUP )
1422 if( nPart == PART_MENU_ITEM_CHECK_MARK ||
1423 nPart == PART_MENU_ITEM_RADIO_MARK )
1425 HTHEME hTheme = getThemeHandle( mhWnd, L"Menu");
1426 Rectangle aBoxRect( rControlRegion );
1427 Rectangle aRect( ImplGetThemeRect( hTheme, hDC,
1428 MENU_POPUPCHECK,
1429 MC_CHECKMARKNORMAL,
1430 aBoxRect ) );
1431 if( aBoxRect.GetWidth() && aBoxRect.GetHeight() )
1433 rNativeContentRegion = aRect;
1434 rNativeBoundingRegion = rNativeContentRegion;
1435 bRet = TRUE;
1441 if( nType == CTRL_SLIDER && ( (nPart == PART_THUMB_HORZ) || (nPart == PART_THUMB_VERT) ) )
1443 HTHEME hTheme = getThemeHandle( mhWnd, L"Trackbar");
1444 if( hTheme )
1446 int iPart = (nPart == PART_THUMB_HORZ) ? TKP_THUMB : TKP_THUMBVERT;
1447 int iState = (nPart == PART_THUMB_HORZ) ? static_cast<int>(TUS_NORMAL) : static_cast<int>(TUVS_NORMAL);
1448 Rectangle aThumbRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() );
1449 if( nPart == PART_THUMB_HORZ )
1451 long nW = aThumbRect.GetWidth();
1452 Rectangle aRect( rControlRegion );
1453 aRect.Right() = aRect.Left() + nW - 1;
1454 rNativeContentRegion = aRect;
1455 rNativeBoundingRegion = rNativeContentRegion;
1457 else
1459 long nH = aThumbRect.GetHeight();
1460 Rectangle aRect( rControlRegion );
1461 aRect.Bottom() = aRect.Top() + nH - 1;
1462 rNativeContentRegion = aRect;
1463 rNativeBoundingRegion = rNativeContentRegion;
1465 bRet = TRUE;
1469 if ( ( nType == CTRL_TAB_ITEM ) && ( nPart == PART_ENTIRE_CONTROL ) )
1471 Rectangle aControlRect( rControlRegion );
1472 rNativeContentRegion = aControlRect;
1474 --aControlRect.Bottom();
1476 if( rControlValue.getType() == CTRL_TAB_ITEM )
1478 const TabitemValue *pValue = static_cast<const TabitemValue*>(&rControlValue);
1479 if ( pValue->isBothAligned() )
1480 --aControlRect.Right();
1482 if ( nState & CTRL_STATE_SELECTED )
1484 aControlRect.Left() -= 2;
1485 if ( pValue && !pValue->isBothAligned() )
1487 if ( pValue->isLeftAligned() || pValue->isNotAligned() )
1488 aControlRect.Right() += 2;
1489 if ( pValue->isRightAligned() )
1490 aControlRect.Right() += 1;
1492 aControlRect.Top() -= 2;
1493 aControlRect.Bottom() += 2;
1496 rNativeBoundingRegion = aControlRect;
1497 bRet = TRUE;
1500 ReleaseDC( mhWnd, hDC );
1501 return( bRet );
1504 void WinSalGraphics::updateSettingsNative( AllSettings& rSettings )
1506 if ( !vsAPI.IsThemeActive() )
1507 return;
1509 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1510 ImplSVData* pSVData = ImplGetSVData();
1512 // don't draw frame around each and every toolbar
1513 pSVData->maNWFData.mbDockingAreaAvoidTBFrames = true;
1515 // check if vista or newer runs
1516 // in Aero theme (and similar ?) the menu text color does not change
1517 // for selected items; also on WinXP and earlier menus are not themed
1518 // FIXME get the color directly from the theme, not from the settings
1519 if( aSalShlData.maVersionInfo.dwMajorVersion >= 6 )
1521 // in aero menuitem highlight text is drawn in the same color as normal
1522 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() );
1523 aStyleSettings.SetMenuBarRolloverTextColor( aStyleSettings.GetMenuTextColor() );
1524 pSVData->maNWFData.mnMenuFormatBorderX = 2;
1525 pSVData->maNWFData.mnMenuFormatBorderY = 2;
1526 pSVData->maNWFData.maMenuBarHighlightTextColor = aStyleSettings.GetMenuTextColor();
1527 GetSalData()->mbThemeMenuSupport = TRUE;
1530 rSettings.SetStyleSettings( aStyleSettings );
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */