// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UI_NATIVE_THEME_NATIVE_THEME_WIN_H_ #define UI_NATIVE_THEME_NATIVE_THEME_WIN_H_ // A wrapper class for working with custom XP/Vista themes provided in // uxtheme.dll. This is a singleton class that can be grabbed using // NativeThemeWin::instance(). // For more information on visual style parts and states, see: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp #include <map> #include <windows.h> #include <uxtheme.h> #include "base/basictypes.h" #include "base/compiler_specific.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/size.h" #include "ui/gfx/sys_color_change_listener.h" #include "ui/native_theme/native_theme.h" class SkCanvas; namespace ui { // Windows implementation of native theme class. // // At the moment, this class in in transition from an older API that consists // of several PaintXXX methods to an API, inherited from the NativeTheme base // class, that consists of a single Paint() method with a argument to indicate // what kind of part to paint. class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme, public gfx::SysColorChangeListener { public: enum ThemeName { BUTTON, LIST, MENU, MENULIST, SCROLLBAR, STATUS, TAB, TEXTFIELD, TRACKBAR, WINDOW, PROGRESS, SPIN, LAST }; bool IsThemingActive() const; // Returns true if a high contrast theme is being used. bool IsUsingHighContrastTheme() const; HRESULT GetThemeColor(ThemeName theme, int part_id, int state_id, int prop_id, SkColor* color) const; // Get the theme color if theming is enabled. If theming is unsupported // for this part, use Win32's GetSysColor to find the color specified // by default_sys_color. SkColor GetThemeColorWithDefault(ThemeName theme, int part_id, int state_id, int prop_id, int default_sys_color) const; // Get the thickness of the border associated with the specified theme, // defaulting to GetSystemMetrics edge size if themes are disabled. // In Classic Windows, borders are typically 2px; on XP+, they are 1px. gfx::Size GetThemeBorderSize(ThemeName theme) const; // Disables all theming for top-level windows in the entire process, from // when this method is called until the process exits. All the other // methods in this class will continue to work, but their output will ignore // the user's theme. This is meant for use when running tests that require // consistent visual results. void DisableTheming() const; // Closes cached theme handles so we can unload the DLL or update our UI // for a theme change. void CloseHandles() const; // Returns true if classic theme is in use. bool IsClassicTheme(ThemeName name) const; // Gets our singleton instance. static NativeThemeWin* instance(); HRESULT PaintTextField(HDC hdc, int part_id, int state_id, int classic_state, RECT* rect, COLORREF color, bool fill_content_area, bool draw_edges) const; // NativeTheme implementation: virtual gfx::Size GetPartSize(Part part, State state, const ExtraParams& extra) const OVERRIDE; virtual void Paint(SkCanvas* canvas, Part part, State state, const gfx::Rect& rect, const ExtraParams& extra) const OVERRIDE; virtual SkColor GetSystemColor(ColorId color_id) const OVERRIDE; private: NativeThemeWin(); ~NativeThemeWin(); // gfx::SysColorChangeListener implementation: virtual void OnSysColorChange() OVERRIDE; // Update the locally cached set of system colors. void UpdateSystemColors(); // Paint directly to canvas' HDC. void PaintDirect(SkCanvas* canvas, Part part, State state, const gfx::Rect& rect, const ExtraParams& extra) const; // Create a temporary HDC, paint to that, clean up the alpha values in the // temporary HDC, and then blit the result to canvas. This is to work around // the fact that Windows XP and some classic themes give bogus alpha values. void PaintIndirect(SkCanvas* canvas, Part part, State state, const gfx::Rect& rect, const ExtraParams& extra) const; HRESULT GetThemePartSize(ThemeName themeName, HDC hdc, int part_id, int state_id, RECT* rect, int ts, SIZE* size) const; HRESULT PaintButton(HDC hdc, State state, const ButtonExtraParams& extra, int part_id, int state_id, RECT* rect) const; HRESULT PaintMenuSeparator(HDC hdc, const gfx::Rect& rect, const MenuSeparatorExtraParams& extra) const; HRESULT PaintMenuGutter(HDC hdc, const gfx::Rect& rect) const; // |arrow_direction| determines whether the arrow is pointing to the left or // to the right. In RTL locales, sub-menus open from right to left and // therefore the menu arrow should point to the left and not to the right. HRESULT PaintMenuArrow(HDC hdc, State state, const gfx::Rect& rect, const MenuArrowExtraParams& extra) const; HRESULT PaintMenuBackground(HDC hdc, const gfx::Rect& rect) const; HRESULT PaintMenuCheck(HDC hdc, State state, const gfx::Rect& rect, const MenuCheckExtraParams& extra) const; HRESULT PaintMenuCheckBackground(HDC hdc, State state, const gfx::Rect& rect) const; HRESULT PaintMenuItemBackground(HDC hdc, State state, const gfx::Rect& rect, const MenuItemExtraParams& extra) const; HRESULT PaintPushButton(HDC hdc, Part part, State state, const gfx::Rect& rect, const ButtonExtraParams& extra) const; HRESULT PaintRadioButton(HDC hdc, Part part, State state, const gfx::Rect& rect, const ButtonExtraParams& extra) const; HRESULT PaintCheckbox(HDC hdc, Part part, State state, const gfx::Rect& rect, const ButtonExtraParams& extra) const; HRESULT PaintMenuList(HDC hdc, State state, const gfx::Rect& rect, const MenuListExtraParams& extra) const; // Paints a scrollbar arrow. |classic_state| should have the appropriate // classic part number ORed in already. HRESULT PaintScrollbarArrow(HDC hdc, Part part, State state, const gfx::Rect& rect, const ScrollbarArrowExtraParams& extra) const; HRESULT PaintScrollbarThumb(HDC hdc, Part part, State state, const gfx::Rect& rect, const ScrollbarThumbExtraParams& extra) const; // This method is deprecated and will be removed in the near future. // Paints a scrollbar track section. |align_rect| is only used in classic // mode, and makes sure the checkerboard pattern in |target_rect| is aligned // with one presumed to be in |align_rect|. HRESULT PaintScrollbarTrack(SkCanvas* canvas, HDC hdc, Part part, State state, const gfx::Rect& rect, const ScrollbarTrackExtraParams& extra) const; HRESULT PaintSpinButton(HDC hdc, Part part, State state, const gfx::Rect& rect, const InnerSpinButtonExtraParams& extra) const; HRESULT PaintTrackbar(SkCanvas* canvas, HDC hdc, Part part, State state, const gfx::Rect& rect, const TrackbarExtraParams& extra) const; HRESULT PaintProgressBar(HDC hdc, const gfx::Rect& rect, const ProgressBarExtraParams& extra) const; HRESULT PaintWindowResizeGripper(HDC hdc, const gfx::Rect& rect) const; HRESULT PaintTabPanelBackground(HDC hdc, const gfx::Rect& rect) const; HRESULT PaintTextField(HDC hdc, Part part, State state, const gfx::Rect& rect, const TextFieldExtraParams& extra) const; // Paints a theme part, with support for scene scaling in high-DPI mode. // |theme| is the theme handle. |hdc| is the handle for the device context. // |part_id| is the identifier for the part (e.g. thumb gripper). |state_id| // is the identifier for the rendering state of the part (e.g. hover). |rect| // is the bounds for rendering, expressed in logical coordinates. HRESULT PaintScaledTheme(HANDLE theme, HDC hdc, int part_id, int state_id, const gfx::Rect& rect) const; // Get the windows theme name/part/state. These three helper functions are // used only by GetPartSize(), as each of the corresponding PaintXXX() // methods do further validation of the part and state that is required for // getting the size. static ThemeName GetThemeName(Part part); static int GetWindowsPart(Part part, State state, const ExtraParams& extra); static int GetWindowsState(Part part, State state, const ExtraParams& extra); HRESULT GetThemeInt(ThemeName theme, int part_id, int state_id, int prop_id, int *result) const; HRESULT PaintFrameControl(HDC hdc, const gfx::Rect& rect, UINT type, UINT state, bool is_selected, State control_state) const; // Returns a handle to the theme data. HANDLE GetThemeHandle(ThemeName theme_name) const; typedef HRESULT (WINAPI* DrawThemeBackgroundPtr)(HANDLE theme, HDC hdc, int part_id, int state_id, const RECT* rect, const RECT* clip_rect); typedef HRESULT (WINAPI* DrawThemeBackgroundExPtr)(HANDLE theme, HDC hdc, int part_id, int state_id, const RECT* rect, const DTBGOPTS* opts); typedef HRESULT (WINAPI* GetThemeColorPtr)(HANDLE hTheme, int part_id, int state_id, int prop_id, COLORREF* color); typedef HRESULT (WINAPI* GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int part_id, int state_id, const RECT* rect, RECT* content_rect); typedef HRESULT (WINAPI* GetThemePartSizePtr)(HANDLE hTheme, HDC hdc, int part_id, int state_id, RECT* rect, int ts, SIZE* size); typedef HANDLE (WINAPI* OpenThemeDataPtr)(HWND window, LPCWSTR class_list); typedef HRESULT (WINAPI* CloseThemeDataPtr)(HANDLE theme); typedef void (WINAPI* SetThemeAppPropertiesPtr) (DWORD flags); typedef BOOL (WINAPI* IsThemeActivePtr)(); typedef HRESULT (WINAPI* GetThemeIntPtr)(HANDLE hTheme, int part_id, int state_id, int prop_id, int *value); // Function pointers into uxtheme.dll. DrawThemeBackgroundPtr draw_theme_; DrawThemeBackgroundExPtr draw_theme_ex_; GetThemeColorPtr get_theme_color_; GetThemeContentRectPtr get_theme_content_rect_; GetThemePartSizePtr get_theme_part_size_; OpenThemeDataPtr open_theme_; CloseThemeDataPtr close_theme_; SetThemeAppPropertiesPtr set_theme_properties_; IsThemeActivePtr is_theme_active_; GetThemeIntPtr get_theme_int_; // Handle to uxtheme.dll. HMODULE theme_dll_; // A cache of open theme handles. mutable HANDLE theme_handles_[LAST]; // The system color change listener and the updated cache of system colors. gfx::ScopedSysColorChangeListener color_change_listener_; mutable std::map<int, SkColor> system_colors_; // Is a high contrast theme active? mutable bool is_using_high_contrast_; // Is |is_using_high_contrast_| valid? mutable bool is_using_high_contrast_valid_; DISALLOW_COPY_AND_ASSIGN(NativeThemeWin); }; } // namespace ui #endif // UI_NATIVE_THEME_NATIVE_THEME_WIN_H_