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