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