| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #define _SV_SALNATIVEWIDGETS_CXX |
| |
| #include "rtl/ustring.h" |
| |
| #include "osl/module.h" |
| |
| #include "vcl/svapp.hxx" |
| |
| #include "win/svsys.h" |
| #include "win/salgdi.h" |
| #include "win/saldata.hxx" |
| |
| #include "uxtheme.h" |
| #include "vssym32.h" |
| |
| #include <map> |
| #include <string> |
| |
| using namespace rtl; |
| using namespace std; |
| |
| typedef map< wstring, HTHEME > ThemeMap; |
| static ThemeMap aThemeMap; |
| |
| |
| /**************************************************** |
| wrap visual styles API to avoid linking against it |
| it is not available on all Windows platforms |
| *****************************************************/ |
| |
| class VisualStylesAPI |
| { |
| private: |
| typedef HTHEME (WINAPI * OpenThemeData_Proc_T) ( HWND hwnd, LPCWSTR pszClassList ); |
| typedef HRESULT (WINAPI * CloseThemeData_Proc_T) ( HTHEME hTheme ); |
| typedef HRESULT (WINAPI * GetThemeBackgroundContentRect_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ); |
| typedef HRESULT (WINAPI * DrawThemeBackground_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ); |
| 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 ); |
| typedef HRESULT (WINAPI * GetThemePartSize_Proc_T) ( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ); |
| |
| OpenThemeData_Proc_T lpfnOpenThemeData; |
| CloseThemeData_Proc_T lpfnCloseThemeData; |
| GetThemeBackgroundContentRect_Proc_T lpfnGetThemeBackgroundContentRect; |
| DrawThemeBackground_Proc_T lpfnDrawThemeBackground; |
| DrawThemeText_Proc_T lpfnDrawThemeText; |
| GetThemePartSize_Proc_T lpfnGetThemePartSize; |
| |
| oslModule mhModule; |
| |
| public: |
| VisualStylesAPI(); |
| ~VisualStylesAPI(); |
| sal_Bool IsAvailable() { return (mhModule != NULL); } |
| |
| HTHEME OpenThemeData( HWND hwnd, LPCWSTR pszClassList ); |
| HRESULT CloseThemeData( HTHEME hTheme ); |
| HRESULT GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ); |
| HRESULT DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ); |
| HRESULT DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect ); |
| HRESULT GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ); |
| }; |
| |
| static VisualStylesAPI vsAPI; |
| |
| VisualStylesAPI::VisualStylesAPI() |
| { |
| mhModule = osl_loadAsciiModule( "uxtheme.dll", SAL_LOADMODULE_DEFAULT ); |
| |
| if ( mhModule ) |
| { |
| lpfnOpenThemeData = (OpenThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "OpenThemeData" ); |
| lpfnCloseThemeData = (CloseThemeData_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "CloseThemeData" ); |
| lpfnGetThemeBackgroundContentRect = (GetThemeBackgroundContentRect_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemeBackgroundContentRect" ); |
| lpfnDrawThemeBackground = (DrawThemeBackground_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeBackground" ); |
| lpfnDrawThemeText = (DrawThemeText_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "DrawThemeText" ); |
| lpfnGetThemePartSize = (GetThemePartSize_Proc_T)osl_getAsciiFunctionSymbol( mhModule, "GetThemePartSize" ); |
| } |
| else |
| { |
| lpfnOpenThemeData = NULL; |
| lpfnCloseThemeData = NULL; |
| lpfnGetThemeBackgroundContentRect = NULL; |
| lpfnDrawThemeBackground = NULL; |
| lpfnDrawThemeText = NULL; |
| lpfnGetThemePartSize = NULL; |
| } |
| } |
| VisualStylesAPI::~VisualStylesAPI() |
| { |
| if( mhModule ) |
| osl_unloadModule( mhModule ); |
| } |
| HTHEME VisualStylesAPI::OpenThemeData( HWND hwnd, LPCWSTR pszClassList ) |
| { |
| if(lpfnOpenThemeData) |
| return (*lpfnOpenThemeData) (hwnd, pszClassList); |
| else |
| return NULL; |
| } |
| |
| HRESULT VisualStylesAPI::CloseThemeData( HTHEME hTheme ) |
| { |
| if(lpfnCloseThemeData) |
| return (*lpfnCloseThemeData) (hTheme); |
| else |
| return S_FALSE; |
| } |
| HRESULT VisualStylesAPI::GetThemeBackgroundContentRect( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect ) |
| { |
| if(lpfnGetThemeBackgroundContentRect) |
| return (*lpfnGetThemeBackgroundContentRect) ( hTheme, hdc, iPartId, iStateId, pBoundingRect, pContentRect ); |
| else |
| return S_FALSE; |
| } |
| HRESULT VisualStylesAPI::DrawThemeBackground( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect ) |
| { |
| if(lpfnDrawThemeBackground) |
| return (*lpfnDrawThemeBackground) (hTheme, hdc, iPartId, iStateId, pRect, pClipRect); |
| else |
| return S_FALSE; |
| } |
| HRESULT VisualStylesAPI::DrawThemeText( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect ) |
| { |
| if(lpfnDrawThemeText) |
| return (*lpfnDrawThemeText) (hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect); |
| else |
| return S_FALSE; |
| } |
| HRESULT VisualStylesAPI::GetThemePartSize( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, THEMESIZE eSize, SIZE *psz ) |
| { |
| if(lpfnGetThemePartSize) |
| return (*lpfnGetThemePartSize) (hTheme, hdc, iPartId, iStateId, prc, eSize, psz); |
| else |
| return S_FALSE; |
| } |
| |
| |
| /********************************************************* |
| * Initialize XP theming and local stuff |
| *********************************************************/ |
| void SalData::initNWF( void ) |
| { |
| ImplSVData* pSVData = ImplGetSVData(); |
| |
| // the menu bar and the top docking area should have a common background (gradient) |
| pSVData->maNWFData.mbMenuBarDockingAreaCommonBG = true; |
| } |
| |
| |
| // ********************************************************* |
| // * Release theming handles |
| // ******************************************************** |
| void SalData::deInitNWF( void ) |
| { |
| ThemeMap::iterator iter = aThemeMap.begin(); |
| while( iter != aThemeMap.end() ) |
| { |
| vsAPI.CloseThemeData(iter->second); |
| iter++; |
| } |
| aThemeMap.clear(); |
| if( maDwmLib ) |
| osl_unloadModule( maDwmLib ); |
| } |
| |
| static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name ) |
| { |
| if( GetSalData()->mbThemeChanged ) |
| { |
| // throw away invalid theme handles |
| GetSalData()->deInitNWF(); |
| GetSalData()->mbThemeChanged = FALSE; |
| } |
| |
| ThemeMap::iterator iter; |
| if( (iter = aThemeMap.find( name )) != aThemeMap.end() ) |
| return iter->second; |
| // theme not found -> add it to map |
| HTHEME hTheme = vsAPI.OpenThemeData( hWnd, name ); |
| if( hTheme != NULL ) |
| aThemeMap[name] = hTheme; |
| return hTheme; |
| } |
| |
| /* |
| * IsNativeControlSupported() |
| * |
| * Returns TRUE if the platform supports native |
| * drawing of the control defined by nPart |
| */ |
| sal_Bool WinSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) |
| { |
| HTHEME hTheme = NULL; |
| |
| switch( nType ) |
| { |
| case CTRL_PUSHBUTTON: |
| case CTRL_RADIOBUTTON: |
| case CTRL_CHECKBOX: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Button"); |
| break; |
| case CTRL_SCROLLBAR: |
| if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) |
| return FALSE; // no background painting needed |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Scrollbar"); |
| break; |
| case CTRL_COMBOBOX: |
| if( nPart == HAS_BACKGROUND_TEXTURE ) |
| return FALSE; // we do not paint the inner part (ie the selection background/focus indication) |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| else if( nPart == PART_BUTTON_DOWN ) |
| hTheme = getThemeHandle( mhWnd, L"Combobox"); |
| break; |
| case CTRL_SPINBOX: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| else if( nPart == PART_ALL_BUTTONS || |
| nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN || |
| nPart == PART_BUTTON_LEFT|| nPart == PART_BUTTON_RIGHT ) |
| hTheme = getThemeHandle( mhWnd, L"Spin"); |
| break; |
| case CTRL_SPINBUTTONS: |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_ALL_BUTTONS ) |
| hTheme = getThemeHandle( mhWnd, L"Spin"); |
| break; |
| case CTRL_EDITBOX: |
| case CTRL_MULTILINE_EDITBOX: |
| if( nPart == HAS_BACKGROUND_TEXTURE ) |
| return FALSE; // we do not paint the inner part (ie the selection background/focus indication) |
| //return TRUE; |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| break; |
| case CTRL_LISTBOX: |
| if( nPart == HAS_BACKGROUND_TEXTURE ) |
| return FALSE; // we do not paint the inner part (ie the selection background/focus indication) |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) |
| hTheme = getThemeHandle( mhWnd, L"Listview"); |
| else if( nPart == PART_BUTTON_DOWN ) |
| hTheme = getThemeHandle( mhWnd, L"Combobox"); |
| break; |
| case CTRL_TAB_PANE: |
| case CTRL_TAB_BODY: |
| case CTRL_TAB_ITEM: |
| case CTRL_FIXEDBORDER: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Tab"); |
| break; |
| case CTRL_TOOLBAR: |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON ) |
| hTheme = getThemeHandle( mhWnd, L"Toolbar"); |
| else |
| // use rebar theme for grip and background |
| hTheme = getThemeHandle( mhWnd, L"Rebar"); |
| break; |
| case CTRL_MENUBAR: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Rebar"); |
| else if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nPart == PART_MENU_ITEM ) |
| hTheme = getThemeHandle( mhWnd, L"Menu" ); |
| } |
| break; |
| case CTRL_MENU_POPUP: |
| if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nPart == PART_ENTIRE_CONTROL || |
| nPart == PART_MENU_ITEM || |
| nPart == PART_MENU_ITEM_CHECK_MARK || |
| nPart == PART_MENU_ITEM_RADIO_MARK || |
| nPart == PART_MENU_SEPARATOR ) |
| hTheme = getThemeHandle( mhWnd, L"Menu" ); |
| } |
| break; |
| case CTRL_PROGRESS: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Progress"); |
| break; |
| case CTRL_SLIDER: |
| if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) |
| hTheme = getThemeHandle( mhWnd, L"Trackbar" ); |
| break; |
| case CTRL_LISTNODE: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"TreeView" ); |
| break; |
| default: |
| hTheme = NULL; |
| break; |
| } |
| |
| return (hTheme != NULL); |
| } |
| |
| |
| /* |
| * HitTestNativeControl() |
| * |
| * If the return value is TRUE, bIsInside contains information whether |
| * aPos was or was not inside the native widget specified by the |
| * nType/nPart combination. |
| */ |
| sal_Bool WinSalGraphics::hitTestNativeControl( ControlType, |
| ControlPart, |
| const Rectangle&, |
| const Point&, |
| sal_Bool& ) |
| { |
| return FALSE; |
| } |
| |
| sal_Bool ImplDrawTheme( HTHEME hTheme, HDC hDC, int iPart, int iState, RECT rc, const OUString& aStr) |
| { |
| HRESULT hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| |
| if( aStr.getLength() ) |
| { |
| RECT rcContent; |
| hr = vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, iPart, iState, &rc, &rcContent); |
| hr = vsAPI.DrawThemeText( hTheme, hDC, iPart, iState, |
| reinterpret_cast<LPCWSTR>(aStr.getStr()), -1, |
| DT_CENTER | DT_VCENTER | DT_SINGLELINE, |
| 0, &rcContent); |
| } |
| return (hr == S_OK); |
| } |
| |
| |
| Rectangle ImplGetThemeRect( HTHEME hTheme, HDC hDC, int iPart, int iState, const Rectangle& aRect, THEMESIZE eTS = TS_TRUE ) |
| { |
| SIZE aSz; |
| RECT rc; |
| rc.left = aRect.nLeft; |
| rc.right = aRect.nRight; |
| rc.top = aRect.nTop; |
| rc.bottom = aRect.nBottom; |
| HRESULT hr = vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, NULL, eTS, &aSz ); // TS_TRUE returns optimal size |
| if( hr == S_OK ) |
| return Rectangle( 0, 0, aSz.cx, aSz.cy ); |
| else |
| return Rectangle(); |
| } |
| |
| // Helper functions |
| // ---- |
| |
| void ImplConvertSpinbuttonValues( int nControlPart, const ControlState& rState, const Rectangle& rRect, |
| int* pLunaPart, int *pLunaState, RECT *pRect ) |
| { |
| if( nControlPart == PART_BUTTON_DOWN ) |
| { |
| *pLunaPart = SPNP_DOWN; |
| if( rState & CTRL_STATE_PRESSED ) |
| *pLunaState = DNS_PRESSED; |
| else if( !(rState & CTRL_STATE_ENABLED) ) |
| *pLunaState = DNS_DISABLED; |
| else if( rState & CTRL_STATE_ROLLOVER ) |
| *pLunaState = DNS_HOT; |
| else |
| *pLunaState = DNS_NORMAL; |
| } |
| if( nControlPart == PART_BUTTON_UP ) |
| { |
| *pLunaPart = SPNP_UP; |
| if( rState & CTRL_STATE_PRESSED ) |
| *pLunaState = UPS_PRESSED; |
| else if( !(rState & CTRL_STATE_ENABLED) ) |
| *pLunaState = UPS_DISABLED; |
| else if( rState & CTRL_STATE_ROLLOVER ) |
| *pLunaState = UPS_HOT; |
| else |
| *pLunaState = UPS_NORMAL; |
| } |
| if( nControlPart == PART_BUTTON_RIGHT ) |
| { |
| *pLunaPart = SPNP_UPHORZ; |
| if( rState & CTRL_STATE_PRESSED ) |
| *pLunaState = DNHZS_PRESSED; |
| else if( !(rState & CTRL_STATE_ENABLED) ) |
| *pLunaState = DNHZS_DISABLED; |
| else if( rState & CTRL_STATE_ROLLOVER ) |
| *pLunaState = DNHZS_HOT; |
| else |
| *pLunaState = DNHZS_NORMAL; |
| } |
| if( nControlPart == PART_BUTTON_LEFT ) |
| { |
| *pLunaPart = SPNP_DOWNHORZ; |
| if( rState & CTRL_STATE_PRESSED ) |
| *pLunaState = UPHZS_PRESSED; |
| else if( !(rState & CTRL_STATE_ENABLED) ) |
| *pLunaState = UPHZS_DISABLED; |
| else if( rState & CTRL_STATE_ROLLOVER ) |
| *pLunaState = UPHZS_HOT; |
| else |
| *pLunaState = UPHZS_NORMAL; |
| } |
| |
| pRect->left = rRect.Left(); |
| pRect->right = rRect.Right()+1; |
| pRect->top = rRect.Top(); |
| pRect->bottom = rRect.Bottom()+1; |
| } |
| |
| // ---- |
| |
| sal_Bool ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc, |
| ControlType nType, |
| ControlPart nPart, |
| ControlState nState, |
| const ImplControlValue& aValue, |
| OUString aCaption ) |
| { |
| // a listbox dropdown is actually a combobox dropdown |
| if( nType == CTRL_LISTBOX ) |
| if( nPart == PART_BUTTON_DOWN ) |
| nType = CTRL_COMBOBOX; |
| |
| // draw entire combobox as a large edit box |
| if( nType == CTRL_COMBOBOX ) |
| if( nPart == PART_ENTIRE_CONTROL ) |
| nType = CTRL_EDITBOX; |
| |
| // draw entire spinbox as a large edit box |
| if( nType == CTRL_SPINBOX ) |
| if( nPart == PART_ENTIRE_CONTROL ) |
| nType = CTRL_EDITBOX; |
| |
| int iPart(0), iState(0); |
| if( nType == CTRL_SCROLLBAR ) |
| { |
| HRESULT hr; |
| if( nPart == PART_BUTTON_UP ) |
| { |
| iPart = SBP_ARROWBTN; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = ABS_UPPRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = ABS_UPDISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = ABS_UPHOT; |
| else |
| iState = ABS_UPNORMAL; |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| return (hr == S_OK); |
| } |
| if( nPart == PART_BUTTON_DOWN ) |
| { |
| iPart = SBP_ARROWBTN; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = ABS_DOWNPRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = ABS_DOWNDISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = ABS_DOWNHOT; |
| else |
| iState = ABS_DOWNNORMAL; |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| return (hr == S_OK); |
| } |
| if( nPart == PART_BUTTON_LEFT ) |
| { |
| iPart = SBP_ARROWBTN; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = ABS_LEFTPRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = ABS_LEFTDISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = ABS_LEFTHOT; |
| else |
| iState = ABS_LEFTNORMAL; |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| return (hr == S_OK); |
| } |
| if( nPart == PART_BUTTON_RIGHT ) |
| { |
| iPart = SBP_ARROWBTN; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = ABS_RIGHTPRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = ABS_RIGHTDISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = ABS_RIGHTHOT; |
| else |
| iState = ABS_RIGHTNORMAL; |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| return (hr == S_OK); |
| } |
| if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) |
| { |
| iPart = (nPart == PART_THUMB_HORZ) ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = SCRBS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = SCRBS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = SCRBS_HOT; |
| else |
| iState = SCRBS_NORMAL; |
| |
| SIZE sz; |
| vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_MIN, &sz); |
| vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_TRUE, &sz); |
| vsAPI.GetThemePartSize(hTheme, hDC, iPart, iState, NULL, TS_DRAW, &sz); |
| |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| // paint gripper on thumb if enough space |
| if( ( (nPart == PART_THUMB_VERT) && (rc.bottom-rc.top > 12) ) || |
| ( (nPart == PART_THUMB_HORZ) && (rc.right-rc.left > 12) ) ) |
| { |
| iPart = (nPart == PART_THUMB_HORZ) ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; |
| iState = 0; |
| vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| } |
| return (hr == S_OK); |
| } |
| if( nPart == PART_TRACK_HORZ_LEFT || nPart == PART_TRACK_HORZ_RIGHT || nPart == PART_TRACK_VERT_UPPER || nPart == PART_TRACK_VERT_LOWER ) |
| { |
| switch( nPart ) |
| { |
| case PART_TRACK_HORZ_LEFT: iPart = SBP_UPPERTRACKHORZ; break; |
| case PART_TRACK_HORZ_RIGHT: iPart = SBP_LOWERTRACKHORZ; break; |
| case PART_TRACK_VERT_UPPER: iPart = SBP_UPPERTRACKVERT; break; |
| case PART_TRACK_VERT_LOWER: iPart = SBP_LOWERTRACKVERT; break; |
| } |
| |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = SCRBS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = SCRBS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = SCRBS_HOT; |
| else |
| iState = SCRBS_NORMAL; |
| hr = vsAPI.DrawThemeBackground( hTheme, hDC, iPart, iState, &rc, 0); |
| return (hr == S_OK); |
| } |
| } |
| if( nType == CTRL_SPINBUTTONS && nPart == PART_ALL_BUTTONS ) |
| { |
| if( aValue.getType() == CTRL_SPINBUTTONS ) |
| { |
| const SpinbuttonValue* pValue = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue*>(&aValue) : NULL; |
| sal_Bool bOk = sal_False; |
| |
| RECT rect; |
| ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect ); |
| bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); |
| |
| if( bOk ) |
| { |
| ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect ); |
| bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); |
| } |
| |
| return bOk; |
| } |
| } |
| if( nType == CTRL_SPINBOX ) |
| { |
| // decrease spinbutton rects a little |
| //rc.right--; |
| //rc.bottom--; |
| if( nPart == PART_ALL_BUTTONS ) |
| { |
| if( aValue.getType() == CTRL_SPINBUTTONS ) |
| { |
| const SpinbuttonValue *pValue = static_cast<const SpinbuttonValue*>(&aValue); |
| sal_Bool bOk = sal_False; |
| |
| RECT rect; |
| ImplConvertSpinbuttonValues( pValue->mnUpperPart, pValue->mnUpperState, pValue->maUpperRect, &iPart, &iState, &rect ); |
| bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); |
| |
| if( bOk ) |
| { |
| ImplConvertSpinbuttonValues( pValue->mnLowerPart, pValue->mnLowerState, pValue->maLowerRect, &iPart, &iState, &rect ); |
| bOk = ImplDrawTheme( hTheme, hDC, iPart, iState, rect, aCaption); |
| } |
| |
| return bOk; |
| } |
| } |
| |
| if( nPart == PART_BUTTON_DOWN ) |
| { |
| iPart = SPNP_DOWN; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = DNS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = DNS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = DNS_HOT; |
| else |
| iState = DNS_NORMAL; |
| } |
| if( nPart == PART_BUTTON_UP ) |
| { |
| iPart = SPNP_UP; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = UPS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = UPS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = UPS_HOT; |
| else |
| iState = UPS_NORMAL; |
| } |
| if( nPart == PART_BUTTON_RIGHT ) |
| { |
| iPart = SPNP_DOWNHORZ; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = DNHZS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = DNHZS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = DNHZS_HOT; |
| else |
| iState = DNHZS_NORMAL; |
| } |
| if( nPart == PART_BUTTON_LEFT ) |
| { |
| iPart = SPNP_UPHORZ; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = UPHZS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = UPHZS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = UPHZS_HOT; |
| else |
| iState = UPHZS_NORMAL; |
| } |
| if( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN ) |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| if( nType == CTRL_COMBOBOX ) |
| { |
| if( nPart == PART_BUTTON_DOWN ) |
| { |
| iPart = CP_DROPDOWNBUTTON; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = CBXS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = CBXS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = CBXS_HOT; |
| else |
| iState = CBXS_NORMAL; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| } |
| if( nType == CTRL_PUSHBUTTON ) |
| { |
| iPart = BP_PUSHBUTTON; |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = PBS_PRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = PBS_DISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = PBS_HOT; |
| else if( nState & CTRL_STATE_DEFAULT ) |
| iState = PBS_DEFAULTED; |
| //else if( nState & CTRL_STATE_FOCUSED ) |
| // iState = PBS_DEFAULTED; // may need to draw focus rect |
| else |
| iState = PBS_NORMAL; |
| |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_RADIOBUTTON ) |
| { |
| iPart = BP_RADIOBUTTON; |
| sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON ); |
| |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = bChecked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED; |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = bChecked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = bChecked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT; |
| else |
| iState = bChecked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL; |
| |
| //if( nState & CTRL_STATE_FOCUSED ) |
| // iState |= PBS_DEFAULTED; // may need to draw focus rect |
| |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_CHECKBOX ) |
| { |
| iPart = BP_CHECKBOX; |
| ButtonValue v = aValue.getTristateVal(); |
| |
| if( nState & CTRL_STATE_PRESSED ) |
| iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDPRESSED : |
| ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED ); |
| else if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDDISABLED : |
| ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED ); |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDHOT : |
| ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT ); |
| else |
| iState = (v == BUTTONVALUE_ON) ? CBS_CHECKEDNORMAL : |
| ( (v == BUTTONVALUE_OFF) ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL ); |
| |
| //if( nState & CTRL_STATE_FOCUSED ) |
| // iState |= PBS_DEFAULTED; // may need to draw focus rect |
| |
| //SIZE sz; |
| //THEMESIZE eSize = TS_DRAW; // TS_MIN, TS_TRUE, TS_DRAW |
| //vsAPI.GetThemePartSize( hTheme, hDC, iPart, iState, &rc, eSize, &sz); |
| |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( ( nType == CTRL_EDITBOX ) || ( nType == CTRL_MULTILINE_EDITBOX ) ) |
| { |
| iPart = EP_EDITTEXT; |
| if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = ETS_DISABLED; |
| else if( nState & CTRL_STATE_FOCUSED ) |
| iState = ETS_FOCUSED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = ETS_HOT; |
| else |
| iState = ETS_NORMAL; |
| |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_LISTBOX ) |
| { |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) |
| { |
| iPart = LVP_EMPTYTEXT; // ??? no idea which part to choose here |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| } |
| |
| if( nType == CTRL_TAB_PANE ) |
| { |
| iPart = TABP_PANE; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_FIXEDBORDER ) |
| { |
| /* |
| iPart = BP_GROUPBOX; |
| if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = GBS_DISABLED; |
| else |
| iState = GBS_NORMAL; |
| */ |
| // The fixed border is only used around the tools->options tabpage where |
| // TABP_PANE fits best |
| iPart = TABP_PANE; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_TAB_BODY ) |
| { |
| iPart = TABP_BODY; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_TAB_ITEM ) |
| { |
| iPart = TABP_TABITEMLEFTEDGE; |
| rc.bottom--; |
| |
| OSL_ASSERT( aValue.getType() == CTRL_TAB_ITEM ); |
| |
| const TabitemValue *pValue = static_cast<const TabitemValue*>(&aValue); |
| if( pValue->isBothAligned() ) |
| { |
| iPart = TABP_TABITEMLEFTEDGE; |
| rc.right--; |
| } |
| else if( pValue->isLeftAligned() ) |
| iPart = TABP_TABITEMLEFTEDGE; |
| else if( pValue->isRightAligned() ) |
| iPart = TABP_TABITEMRIGHTEDGE; |
| else iPart = TABP_TABITEM; |
| |
| if( !(nState & CTRL_STATE_ENABLED) ) |
| iState = TILES_DISABLED; |
| else if( nState & CTRL_STATE_SELECTED ) |
| { |
| iState = TILES_SELECTED; |
| // increase the selected tab |
| rc.left-=2; |
| if( pValue && !pValue->isBothAligned() ) |
| { |
| if( pValue->isLeftAligned() || pValue->isNotAligned() ) |
| rc.right+=2; |
| if( pValue->isRightAligned() ) |
| rc.right+=1; |
| } |
| rc.top-=2; |
| rc.bottom+=2; |
| } |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = TILES_HOT; |
| else if( nState & CTRL_STATE_FOCUSED ) |
| iState = TILES_FOCUSED; // may need to draw focus rect |
| else |
| iState = TILES_NORMAL; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| |
| if( nType == CTRL_TOOLBAR ) |
| { |
| if( nPart == PART_BUTTON ) |
| { |
| iPart = TP_BUTTON; |
| sal_Bool bChecked = ( aValue.getTristateVal() == BUTTONVALUE_ON ); |
| if( !(nState & CTRL_STATE_ENABLED) ) |
| //iState = TS_DISABLED; |
| // disabled buttons are typically not painted at all but we need visual |
| // feedback when travelling by keyboard over disabled entries |
| iState = TS_HOT; |
| else if( nState & CTRL_STATE_PRESSED ) |
| iState = TS_PRESSED; |
| else if( nState & CTRL_STATE_ROLLOVER ) |
| iState = bChecked ? TS_HOTCHECKED : TS_HOT; |
| else |
| iState = bChecked ? TS_CHECKED : TS_NORMAL; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) |
| { |
| // the vertical gripper is not supported in most themes and it makes no |
| // sense to only support horizontal gripper |
| //iPart = (nPart == PART_THUMB_HORZ) ? RP_GRIPPERVERT : RP_GRIPPER; |
| //return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| else if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) |
| { |
| if( aValue.getType() == CTRL_TOOLBAR ) |
| { |
| const ToolbarValue *pValue = static_cast<const ToolbarValue*>(&aValue); |
| if( pValue->mbIsTopDockingArea ) |
| rc.top = 0; // extend potential gradient to cover menu bar as well |
| } |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| } |
| |
| if( nType == CTRL_MENUBAR ) |
| { |
| if( nPart == PART_ENTIRE_CONTROL ) |
| { |
| if( aValue.getType() == CTRL_MENUBAR ) |
| { |
| const MenubarValue *pValue = static_cast<const MenubarValue*>(&aValue); |
| rc.bottom += pValue->maTopDockingAreaHeight; // extend potential gradient to cover docking area as well |
| } |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption); |
| } |
| else if( nPart == PART_MENU_ITEM ) |
| { |
| if( (nState & CTRL_STATE_ENABLED) ) |
| iState = (nState & CTRL_STATE_SELECTED) ? MBI_HOT : MBI_NORMAL; |
| else |
| iState = (nState & CTRL_STATE_SELECTED) ? MBI_DISABLEDHOT : MBI_DISABLED; |
| return ImplDrawTheme( hTheme, hDC, MENU_BARITEM, iState, rc, aCaption ); |
| } |
| } |
| |
| if( nType == CTRL_PROGRESS ) |
| { |
| if( nPart != PART_ENTIRE_CONTROL ) |
| return FALSE; |
| |
| if( ! ImplDrawTheme( hTheme, hDC, PP_BAR, iState, rc, aCaption) ) |
| return false; |
| RECT aProgressRect = rc; |
| if( vsAPI.GetThemeBackgroundContentRect( hTheme, hDC, PP_BAR, iState, &rc, &aProgressRect) != S_OK ) |
| return false; |
| |
| long nProgressWidth = aValue.getNumericVal(); |
| nProgressWidth *= (aProgressRect.right - aProgressRect.left); |
| nProgressWidth /= (rc.right - rc.left); |
| if( Application::GetSettings().GetLayoutRTL() ) |
| aProgressRect.left = aProgressRect.right - nProgressWidth; |
| else |
| aProgressRect.right = aProgressRect.left + nProgressWidth; |
| |
| return ImplDrawTheme( hTheme, hDC, PP_CHUNK, iState, aProgressRect, aCaption ); |
| } |
| |
| if( nType == CTRL_SLIDER ) |
| { |
| iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_TRACK : TKP_TRACKVERT; |
| iState = (nPart == PART_TRACK_HORZ_AREA) ? TRS_NORMAL : TRVS_NORMAL; |
| |
| Rectangle aTrackRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() ); |
| RECT aTRect = rc; |
| if( nPart == PART_TRACK_HORZ_AREA ) |
| { |
| long nH = aTrackRect.GetHeight(); |
| aTRect.top += (rc.bottom - rc.top - nH)/2; |
| aTRect.bottom = aTRect.top + nH; |
| } |
| else |
| { |
| long nW = aTrackRect.GetWidth(); |
| aTRect.left += (rc.right - rc.left - nW)/2; |
| aTRect.right = aTRect.left + nW; |
| } |
| ImplDrawTheme( hTheme, hDC, iPart, iState, aTRect, aCaption ); |
| |
| RECT aThumbRect; |
| OSL_ASSERT( aValue.getType() == CTRL_SLIDER ); |
| const SliderValue* pVal = static_cast<const SliderValue*>(&aValue); |
| aThumbRect.left = pVal->maThumbRect.Left(); |
| aThumbRect.top = pVal->maThumbRect.Top(); |
| aThumbRect.right = pVal->maThumbRect.Right(); |
| aThumbRect.bottom = pVal->maThumbRect.Bottom(); |
| iPart = (nPart == PART_TRACK_HORZ_AREA) ? TKP_THUMB : TKP_THUMBVERT; |
| iState = (nState & CTRL_STATE_ENABLED) ? TUS_NORMAL : TUS_DISABLED; |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, aThumbRect, aCaption ); |
| } |
| |
| if( nType == CTRL_LISTNODE ) |
| { |
| if( nPart != PART_ENTIRE_CONTROL ) |
| return FALSE; |
| |
| ButtonValue aButtonValue = aValue.getTristateVal(); |
| iPart = TVP_GLYPH; |
| switch( aButtonValue ) |
| { |
| case BUTTONVALUE_ON: |
| iState = GLPS_OPENED; |
| break; |
| case BUTTONVALUE_OFF: |
| iState = GLPS_CLOSED; |
| break; |
| default: |
| return FALSE; |
| } |
| return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption ); |
| } |
| |
| if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nType == CTRL_MENU_POPUP ) |
| { |
| if( nPart == PART_ENTIRE_CONTROL ) |
| { |
| RECT aGutterRC = rc; |
| aGutterRC.left += aValue.getNumericVal(); |
| aGutterRC.right = aGutterRC.left+3; |
| return |
| ImplDrawTheme( hTheme, hDC, MENU_POPUPBACKGROUND, 0, rc, aCaption ) && |
| ImplDrawTheme( hTheme, hDC, MENU_POPUPGUTTER, 0, aGutterRC, aCaption ) |
| ; |
| } |
| else if( nPart == PART_MENU_ITEM ) |
| { |
| if( (nState & CTRL_STATE_ENABLED) ) |
| iState = (nState & CTRL_STATE_SELECTED) ? MPI_HOT : MPI_NORMAL; |
| else |
| iState = (nState & CTRL_STATE_SELECTED) ? MPI_DISABLEDHOT : MPI_DISABLED; |
| return ImplDrawTheme( hTheme, hDC, MENU_POPUPITEM, iState, rc, aCaption ); |
| } |
| else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ) |
| { |
| if( (nState & CTRL_STATE_PRESSED) ) |
| { |
| RECT aBGRect = rc; |
| if( aValue.getType() == CTRL_MENU_POPUP ) |
| { |
| const MenupopupValue& rMVal( static_cast<const MenupopupValue&>(aValue) ); |
| aBGRect.left = rMVal.maItemRect.Left(); |
| aBGRect.top = rMVal.maItemRect.Top(); |
| aBGRect.bottom = rMVal.maItemRect.Bottom()+1; // see below in drawNativeControl |
| aBGRect.right = rMVal.getNumericVal(); |
| |
| // FIXME: magic |
| aBGRect.left += 1; aBGRect.top += 1; aBGRect.bottom +=1; |
| } |
| iState = (nState & CTRL_STATE_ENABLED) ? MCB_NORMAL : MCB_DISABLED; |
| ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECKBACKGROUND, iState, aBGRect, aCaption ); |
| if( nPart == PART_MENU_ITEM_CHECK_MARK ) |
| iState = (nState & CTRL_STATE_ENABLED) ? MC_CHECKMARKNORMAL : MC_CHECKMARKDISABLED; |
| else |
| iState = (nState & CTRL_STATE_ENABLED) ? MC_BULLETNORMAL : MC_BULLETDISABLED; |
| return ImplDrawTheme( hTheme, hDC, MENU_POPUPCHECK, iState, rc, aCaption ); |
| } |
| else |
| return true; // unchecked: do nothing |
| } |
| else if( nPart == PART_MENU_SEPARATOR ) |
| { |
| rc.left += aValue.getNumericVal(); // adjust for gutter position |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, |
| MENU_POPUPSEPARATOR, 0, Rectangle( rc.left, rc.top, rc.right, rc.bottom ) ) ); |
| // center the separator inside the passed rectangle |
| long nDY = ((rc.bottom - rc.top + 1) - aRect.GetHeight()) / 2; |
| rc.top += nDY; |
| rc.bottom = rc.top+aRect.GetHeight()-1; |
| return ImplDrawTheme( hTheme, hDC, MENU_POPUPSEPARATOR, 0, rc, aCaption ); |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /* |
| * DrawNativeControl() |
| * |
| * Draws the requested control described by nPart/nState. |
| * |
| * rControlRegion: The bounding region of the complete control in VCL frame coordinates. |
| * aValue: An optional value (tristate/numerical/string) |
| * aCaption: A caption or title string (like button text etc) |
| */ |
| sal_Bool WinSalGraphics::drawNativeControl( ControlType nType, |
| ControlPart nPart, |
| const Rectangle& rControlRegion, |
| ControlState nState, |
| const ImplControlValue& aValue, |
| const OUString& aCaption ) |
| { |
| sal_Bool bOk = false; |
| HTHEME hTheme = NULL; |
| |
| switch( nType ) |
| { |
| case CTRL_PUSHBUTTON: |
| case CTRL_RADIOBUTTON: |
| case CTRL_CHECKBOX: |
| hTheme = getThemeHandle( mhWnd, L"Button"); |
| break; |
| case CTRL_SCROLLBAR: |
| hTheme = getThemeHandle( mhWnd, L"Scrollbar"); |
| break; |
| case CTRL_COMBOBOX: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| else if( nPart == PART_BUTTON_DOWN ) |
| hTheme = getThemeHandle( mhWnd, L"Combobox"); |
| break; |
| case CTRL_SPINBOX: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| else |
| hTheme = getThemeHandle( mhWnd, L"Spin"); |
| break; |
| case CTRL_SPINBUTTONS: |
| hTheme = getThemeHandle( mhWnd, L"Spin"); |
| break; |
| case CTRL_EDITBOX: |
| case CTRL_MULTILINE_EDITBOX: |
| hTheme = getThemeHandle( mhWnd, L"Edit"); |
| break; |
| case CTRL_LISTBOX: |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW ) |
| hTheme = getThemeHandle( mhWnd, L"Listview"); |
| else if( nPart == PART_BUTTON_DOWN ) |
| hTheme = getThemeHandle( mhWnd, L"Combobox"); |
| break; |
| case CTRL_TAB_PANE: |
| case CTRL_TAB_BODY: |
| case CTRL_TAB_ITEM: |
| case CTRL_FIXEDBORDER: |
| hTheme = getThemeHandle( mhWnd, L"Tab"); |
| break; |
| case CTRL_TOOLBAR: |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_BUTTON ) |
| hTheme = getThemeHandle( mhWnd, L"Toolbar"); |
| else |
| // use rebar for grip and background |
| hTheme = getThemeHandle( mhWnd, L"Rebar"); |
| break; |
| case CTRL_MENUBAR: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Rebar"); |
| else if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nPart == PART_MENU_ITEM ) |
| hTheme = getThemeHandle( mhWnd, L"Menu" ); |
| } |
| break; |
| case CTRL_PROGRESS: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"Progress"); |
| break; |
| case CTRL_LISTNODE: |
| if( nPart == PART_ENTIRE_CONTROL ) |
| hTheme = getThemeHandle( mhWnd, L"TreeView"); |
| break; |
| case CTRL_SLIDER: |
| if( nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA ) |
| hTheme = getThemeHandle( mhWnd, L"Trackbar" ); |
| break; |
| case CTRL_MENU_POPUP: |
| if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM || |
| nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK || |
| nPart == PART_MENU_SEPARATOR |
| ) |
| hTheme = getThemeHandle( mhWnd, L"Menu" ); |
| } |
| break; |
| default: |
| hTheme = NULL; |
| break; |
| } |
| |
| if( !hTheme ) |
| return false; |
| |
| Rectangle buttonRect = rControlRegion; |
| RECT rc; |
| rc.left = buttonRect.Left(); |
| rc.right = buttonRect.Right()+1; |
| rc.top = buttonRect.Top(); |
| rc.bottom = buttonRect.Bottom()+1; |
| |
| // set default text alignment |
| int ta = SetTextAlign( getHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP ); |
| |
| OUString aCaptionStr( aCaption.replace('~', '&') ); // translate mnemonics |
| bOk = ImplDrawNativeControl(getHDC(), hTheme, rc, |
| nType, nPart, nState, aValue, |
| aCaptionStr ); |
| |
| // restore alignment |
| SetTextAlign( getHDC(), ta ); |
| |
| |
| //GdiFlush(); |
| |
| return bOk; |
| } |
| |
| |
| /* |
| * DrawNativeControlText() |
| * |
| * OPTIONAL. Draws the requested text for the control described by nPart/nState. |
| * Used if text not drawn by DrawNativeControl(). |
| * |
| * rControlRegion: The bounding region of the complete control in VCL frame coordinates. |
| * aValue: An optional value (tristate/numerical/string) |
| * aCaption: A caption or title string (like button text etc) |
| */ |
| sal_Bool WinSalGraphics::drawNativeControlText( ControlType, |
| ControlPart, |
| const Rectangle&, |
| ControlState, |
| const ImplControlValue&, |
| const OUString& ) |
| { |
| return( false ); |
| } |
| |
| |
| /* |
| * GetNativeControlRegion() |
| * |
| * If the return value is TRUE, rNativeBoundingRegion |
| * contains the true bounding region covered by the control |
| * including any adornment, while rNativeContentRegion contains the area |
| * within the control that can be safely drawn into without drawing over |
| * the borders of the control. |
| * |
| * rControlRegion: The bounding region of the control in VCL frame coordinates. |
| * aValue: An optional value (tristate/numerical/string) |
| * aCaption: A caption or title string (like button text etc) |
| */ |
| sal_Bool WinSalGraphics::getNativeControlRegion( ControlType nType, |
| ControlPart nPart, |
| const Rectangle& rControlRegion, |
| ControlState nState, |
| const ImplControlValue& rControlValue, |
| const OUString&, |
| Rectangle &rNativeBoundingRegion, |
| Rectangle &rNativeContentRegion ) |
| { |
| sal_Bool bRet = FALSE; |
| |
| HDC hDC = GetDC( mhWnd ); |
| if( nType == CTRL_TOOLBAR ) |
| { |
| if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) |
| { |
| /* |
| // the vertical gripper is not supported in most themes and it makes no |
| // sense to only support horizontal gripper |
| |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Rebar"); |
| if( hTheme ) |
| { |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, nPart == PART_THUMB_HORZ ? RP_GRIPPERVERT : RP_GRIPPER, |
| 0, rControlRegion.GetBoundRect() ) ); |
| if( nPart == PART_THUMB_HORZ && !aRect.IsEmpty() ) |
| { |
| Rectangle aVertRect( 0, 0, aRect.getHeight(), aRect.getWidth() ); |
| rNativeContentRegion = aVertRect; |
| } |
| else |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| if( !rNativeContentRegion.IsEmpty() ) |
| bRet = TRUE; |
| } |
| */ |
| } |
| if( nPart == PART_BUTTON ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Toolbar"); |
| if( hTheme ) |
| { |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, TP_SPLITBUTTONDROPDOWN, |
| TS_HOT, rControlRegion ) ); |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| if( !rNativeContentRegion.IsEmpty() ) |
| bRet = TRUE; |
| } |
| } |
| } |
| if( nType == CTRL_PROGRESS && nPart == PART_ENTIRE_CONTROL ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Progress"); |
| if( hTheme ) |
| { |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, PP_BAR, |
| 0, rControlRegion ) ); |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| if( !rNativeContentRegion.IsEmpty() ) |
| bRet = TRUE; |
| } |
| } |
| if( (nType == CTRL_LISTBOX || nType == CTRL_COMBOBOX ) && nPart == PART_ENTIRE_CONTROL ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Combobox"); |
| if( hTheme ) |
| { |
| Rectangle aBoxRect( rControlRegion ); |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, CP_DROPDOWNBUTTON, |
| CBXS_NORMAL, aBoxRect ) ); |
| if( aRect.GetHeight() > aBoxRect.GetHeight() ) |
| aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight(); |
| if( aRect.GetWidth() > aBoxRect.GetWidth() ) |
| aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth(); |
| rNativeContentRegion = aBoxRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| if( !aRect.IsEmpty() ) |
| bRet = TRUE; |
| } |
| } |
| |
| if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Edit"); |
| if( hTheme ) |
| { |
| // get border size |
| Rectangle aBoxRect( rControlRegion ); |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, EP_BACKGROUNDWITHBORDER, |
| EBWBS_HOT, aBoxRect ) ); |
| // ad app font height |
| NONCLIENTMETRICSW aNonClientMetrics; |
| aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); |
| if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) |
| { |
| long nFontHeight = aNonClientMetrics.lfMessageFont.lfHeight; |
| if( nFontHeight < 0 ) |
| nFontHeight = -nFontHeight; |
| |
| if( aRect.GetHeight() && nFontHeight ) |
| { |
| aRect.Bottom() += aRect.GetHeight(); |
| aRect.Bottom() += nFontHeight; |
| if( aRect.GetHeight() > aBoxRect.GetHeight() ) |
| aBoxRect.Bottom() = aBoxRect.Top() + aRect.GetHeight(); |
| if( aRect.GetWidth() > aBoxRect.GetWidth() ) |
| aBoxRect.Right() = aBoxRect.Left() + aRect.GetWidth(); |
| rNativeContentRegion = aBoxRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| bRet = TRUE; |
| } |
| } |
| } |
| } |
| |
| if( GetSalData()->mbThemeMenuSupport ) |
| { |
| if( nType == CTRL_MENU_POPUP ) |
| { |
| if( nPart == PART_MENU_ITEM_CHECK_MARK || |
| nPart == PART_MENU_ITEM_RADIO_MARK ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Menu"); |
| Rectangle aBoxRect( rControlRegion ); |
| Rectangle aRect( ImplGetThemeRect( hTheme, hDC, |
| MENU_POPUPCHECK, |
| MC_CHECKMARKNORMAL, |
| aBoxRect ) ); |
| if( aBoxRect.GetWidth() && aBoxRect.GetHeight() ) |
| { |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| bRet = TRUE; |
| } |
| } |
| } |
| } |
| |
| if( nType == CTRL_SLIDER && ( (nPart == PART_THUMB_HORZ) || (nPart == PART_THUMB_VERT) ) ) |
| { |
| HTHEME hTheme = getThemeHandle( mhWnd, L"Trackbar"); |
| if( hTheme ) |
| { |
| int iPart = (nPart == PART_THUMB_HORZ) ? TKP_THUMB : TKP_THUMBVERT; |
| int iState = (nPart == PART_THUMB_HORZ) ? TUS_NORMAL : TUVS_NORMAL; |
| Rectangle aThumbRect = ImplGetThemeRect( hTheme, hDC, iPart, iState, Rectangle() ); |
| if( nPart == PART_THUMB_HORZ ) |
| { |
| long nW = aThumbRect.GetWidth(); |
| Rectangle aRect( rControlRegion ); |
| aRect.Right() = aRect.Left() + nW - 1; |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| } |
| else |
| { |
| long nH = aThumbRect.GetHeight(); |
| Rectangle aRect( rControlRegion ); |
| aRect.Bottom() = aRect.Top() + nH - 1; |
| rNativeContentRegion = aRect; |
| rNativeBoundingRegion = rNativeContentRegion; |
| } |
| bRet = TRUE; |
| } |
| } |
| |
| if ( ( nType == CTRL_TAB_ITEM ) && ( nPart == PART_ENTIRE_CONTROL ) ) |
| { |
| Rectangle aControlRect( rControlRegion ); |
| rNativeContentRegion = aControlRect; |
| |
| --aControlRect.Bottom(); |
| |
| if( rControlValue.getType() == CTRL_TAB_ITEM ) |
| { |
| const TabitemValue *pValue = static_cast<const TabitemValue*>(&rControlValue); |
| if ( pValue->isBothAligned() ) |
| --aControlRect.Right(); |
| |
| if ( nState & CTRL_STATE_SELECTED ) |
| { |
| aControlRect.Left() -= 2; |
| if ( pValue && !pValue->isBothAligned() ) |
| { |
| if ( pValue->isLeftAligned() || pValue->isNotAligned() ) |
| aControlRect.Right() += 2; |
| if ( pValue->isRightAligned() ) |
| aControlRect.Right() += 1; |
| } |
| aControlRect.Top() -= 2; |
| aControlRect.Bottom() += 2; |
| } |
| } |
| rNativeBoundingRegion = aControlRect; |
| bRet = TRUE; |
| } |
| |
| ReleaseDC( mhWnd, hDC ); |
| return( bRet ); |
| } |
| |