1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_NATIVE_THEME_NATIVE_THEME_WIN_H_ 6 #define UI_NATIVE_THEME_NATIVE_THEME_WIN_H_ 7 8 // A wrapper class for working with custom XP/Vista themes provided in 9 // uxtheme.dll. This is a singleton class that can be grabbed using 10 // NativeThemeWin::instance(). 11 // For more information on visual style parts and states, see: 12 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp 13 14 #include <map> 15 16 #include <windows.h> 17 #include <uxtheme.h> 18 19 #include "base/basictypes.h" 20 #include "base/compiler_specific.h" 21 #include "third_party/skia/include/core/SkColor.h" 22 #include "ui/gfx/size.h" 23 #include "ui/gfx/sys_color_change_listener.h" 24 #include "ui/native_theme/native_theme.h" 25 26 class SkCanvas; 27 28 namespace ui { 29 30 // Windows implementation of native theme class. 31 // 32 // At the moment, this class in in transition from an older API that consists 33 // of several PaintXXX methods to an API, inherited from the NativeTheme base 34 // class, that consists of a single Paint() method with a argument to indicate 35 // what kind of part to paint. 36 class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme, 37 public gfx::SysColorChangeListener { 38 public: 39 enum ThemeName { 40 BUTTON, 41 LIST, 42 MENU, 43 MENULIST, 44 SCROLLBAR, 45 STATUS, 46 TAB, 47 TEXTFIELD, 48 TRACKBAR, 49 WINDOW, 50 PROGRESS, 51 SPIN, 52 LAST 53 }; 54 55 bool IsThemingActive() const; 56 57 HRESULT GetThemeColor(ThemeName theme, 58 int part_id, 59 int state_id, 60 int prop_id, 61 SkColor* color) const; 62 63 // Get the theme color if theming is enabled. If theming is unsupported 64 // for this part, use Win32's GetSysColor to find the color specified 65 // by default_sys_color. 66 SkColor GetThemeColorWithDefault(ThemeName theme, 67 int part_id, 68 int state_id, 69 int prop_id, 70 int default_sys_color) const; 71 72 // Get the thickness of the border associated with the specified theme, 73 // defaulting to GetSystemMetrics edge size if themes are disabled. 74 // In Classic Windows, borders are typically 2px; on XP+, they are 1px. 75 gfx::Size GetThemeBorderSize(ThemeName theme) const; 76 77 // Disables all theming for top-level windows in the entire process, from 78 // when this method is called until the process exits. All the other 79 // methods in this class will continue to work, but their output will ignore 80 // the user's theme. This is meant for use when running tests that require 81 // consistent visual results. 82 void DisableTheming() const; 83 84 // Closes cached theme handles so we can unload the DLL or update our UI 85 // for a theme change. 86 void CloseHandles() const; 87 88 // Returns true if classic theme is in use. 89 bool IsClassicTheme(ThemeName name) const; 90 91 // Gets our singleton instance. 92 static NativeThemeWin* instance(); 93 94 HRESULT PaintTextField(HDC hdc, 95 int part_id, 96 int state_id, 97 int classic_state, 98 RECT* rect, 99 COLORREF color, 100 bool fill_content_area, 101 bool draw_edges) const; 102 103 // NativeTheme implementation: 104 virtual gfx::Size GetPartSize(Part part, 105 State state, 106 const ExtraParams& extra) const OVERRIDE; 107 virtual void Paint(SkCanvas* canvas, 108 Part part, 109 State state, 110 const gfx::Rect& rect, 111 const ExtraParams& extra) const OVERRIDE; 112 virtual SkColor GetSystemColor(ColorId color_id) const OVERRIDE; 113 114 private: 115 NativeThemeWin(); 116 ~NativeThemeWin(); 117 118 // gfx::SysColorChangeListener implementation: 119 virtual void OnSysColorChange() OVERRIDE; 120 121 // Update the locally cached set of system colors. 122 void UpdateSystemColors(); 123 124 // Paint directly to canvas' HDC. 125 void PaintDirect(SkCanvas* canvas, 126 Part part, 127 State state, 128 const gfx::Rect& rect, 129 const ExtraParams& extra) const; 130 131 // Create a temporary HDC, paint to that, clean up the alpha values in the 132 // temporary HDC, and then blit the result to canvas. This is to work around 133 // the fact that Windows XP and some classic themes give bogus alpha values. 134 void PaintIndirect(SkCanvas* canvas, 135 Part part, 136 State state, 137 const gfx::Rect& rect, 138 const ExtraParams& extra) const; 139 140 HRESULT GetThemePartSize(ThemeName themeName, 141 HDC hdc, 142 int part_id, 143 int state_id, 144 RECT* rect, 145 int ts, 146 SIZE* size) const; 147 148 HRESULT PaintButton(HDC hdc, 149 State state, 150 const ButtonExtraParams& extra, 151 int part_id, 152 int state_id, 153 RECT* rect) const; 154 155 HRESULT PaintMenuSeparator(HDC hdc, 156 const gfx::Rect& rect, 157 const MenuSeparatorExtraParams& extra) const; 158 159 HRESULT PaintMenuGutter(HDC hdc, const gfx::Rect& rect) const; 160 161 // |arrow_direction| determines whether the arrow is pointing to the left or 162 // to the right. In RTL locales, sub-menus open from right to left and 163 // therefore the menu arrow should point to the left and not to the right. 164 HRESULT PaintMenuArrow(HDC hdc, 165 State state, 166 const gfx::Rect& rect, 167 const MenuArrowExtraParams& extra) const; 168 169 HRESULT PaintMenuBackground(HDC hdc, const gfx::Rect& rect) const; 170 171 HRESULT PaintMenuCheck(HDC hdc, 172 State state, 173 const gfx::Rect& rect, 174 const MenuCheckExtraParams& extra) const; 175 176 HRESULT PaintMenuCheckBackground(HDC hdc, 177 State state, 178 const gfx::Rect& rect) const; 179 180 HRESULT PaintMenuItemBackground(HDC hdc, 181 State state, 182 const gfx::Rect& rect, 183 const MenuItemExtraParams& extra) const; 184 185 HRESULT PaintPushButton(HDC hdc, 186 Part part, 187 State state, 188 const gfx::Rect& rect, 189 const ButtonExtraParams& extra) const; 190 191 HRESULT PaintRadioButton(HDC hdc, 192 Part part, 193 State state, 194 const gfx::Rect& rect, 195 const ButtonExtraParams& extra) const; 196 197 HRESULT PaintCheckbox(HDC hdc, 198 Part part, 199 State state, 200 const gfx::Rect& rect, 201 const ButtonExtraParams& extra) const; 202 203 HRESULT PaintMenuList(HDC hdc, 204 State state, 205 const gfx::Rect& rect, 206 const MenuListExtraParams& extra) const; 207 208 // Paints a scrollbar arrow. |classic_state| should have the appropriate 209 // classic part number ORed in already. 210 HRESULT PaintScrollbarArrow(HDC hdc, 211 Part part, 212 State state, 213 const gfx::Rect& rect, 214 const ScrollbarArrowExtraParams& extra) const; 215 216 HRESULT PaintScrollbarThumb(HDC hdc, 217 Part part, 218 State state, 219 const gfx::Rect& rect, 220 const ScrollbarThumbExtraParams& extra) const; 221 222 // This method is deprecated and will be removed in the near future. 223 // Paints a scrollbar track section. |align_rect| is only used in classic 224 // mode, and makes sure the checkerboard pattern in |target_rect| is aligned 225 // with one presumed to be in |align_rect|. 226 HRESULT PaintScrollbarTrack(SkCanvas* canvas, 227 HDC hdc, 228 Part part, 229 State state, 230 const gfx::Rect& rect, 231 const ScrollbarTrackExtraParams& extra) const; 232 233 HRESULT PaintSpinButton(HDC hdc, 234 Part part, 235 State state, 236 const gfx::Rect& rect, 237 const InnerSpinButtonExtraParams& extra) const; 238 239 HRESULT PaintTrackbar(SkCanvas* canvas, 240 HDC hdc, 241 Part part, 242 State state, 243 const gfx::Rect& rect, 244 const TrackbarExtraParams& extra) const; 245 246 HRESULT PaintProgressBar(HDC hdc, 247 const gfx::Rect& rect, 248 const ProgressBarExtraParams& extra) const; 249 250 HRESULT PaintWindowResizeGripper(HDC hdc, const gfx::Rect& rect) const; 251 252 HRESULT PaintTabPanelBackground(HDC hdc, const gfx::Rect& rect) const; 253 254 HRESULT PaintTextField(HDC hdc, 255 Part part, 256 State state, 257 const gfx::Rect& rect, 258 const TextFieldExtraParams& extra) const; 259 260 // Paints a theme part, with support for scene scaling in high-DPI mode. 261 // |theme| is the theme handle. |hdc| is the handle for the device context. 262 // |part_id| is the identifier for the part (e.g. thumb gripper). |state_id| 263 // is the identifier for the rendering state of the part (e.g. hover). |rect| 264 // is the bounds for rendering, expressed in logical coordinates. 265 HRESULT PaintScaledTheme(HANDLE theme, 266 HDC hdc, 267 int part_id, 268 int state_id, 269 const gfx::Rect& rect) const; 270 271 // Get the windows theme name/part/state. These three helper functions are 272 // used only by GetPartSize(), as each of the corresponding PaintXXX() 273 // methods do further validation of the part and state that is required for 274 // getting the size. 275 static ThemeName GetThemeName(Part part); 276 static int GetWindowsPart(Part part, State state, const ExtraParams& extra); 277 static int GetWindowsState(Part part, State state, const ExtraParams& extra); 278 279 HRESULT GetThemeInt(ThemeName theme, 280 int part_id, 281 int state_id, 282 int prop_id, 283 int *result) const; 284 285 HRESULT PaintFrameControl(HDC hdc, 286 const gfx::Rect& rect, 287 UINT type, 288 UINT state, 289 bool is_selected, 290 State control_state) const; 291 292 // Returns a handle to the theme data. 293 HANDLE GetThemeHandle(ThemeName theme_name) const; 294 295 typedef HRESULT (WINAPI* DrawThemeBackgroundPtr)(HANDLE theme, 296 HDC hdc, 297 int part_id, 298 int state_id, 299 const RECT* rect, 300 const RECT* clip_rect); 301 typedef HRESULT (WINAPI* DrawThemeBackgroundExPtr)(HANDLE theme, 302 HDC hdc, 303 int part_id, 304 int state_id, 305 const RECT* rect, 306 const DTBGOPTS* opts); 307 typedef HRESULT (WINAPI* GetThemeColorPtr)(HANDLE hTheme, 308 int part_id, 309 int state_id, 310 int prop_id, 311 COLORREF* color); 312 typedef HRESULT (WINAPI* GetThemeContentRectPtr)(HANDLE hTheme, 313 HDC hdc, 314 int part_id, 315 int state_id, 316 const RECT* rect, 317 RECT* content_rect); 318 typedef HRESULT (WINAPI* GetThemePartSizePtr)(HANDLE hTheme, 319 HDC hdc, 320 int part_id, 321 int state_id, 322 RECT* rect, 323 int ts, 324 SIZE* size); 325 typedef HANDLE (WINAPI* OpenThemeDataPtr)(HWND window, 326 LPCWSTR class_list); 327 typedef HRESULT (WINAPI* CloseThemeDataPtr)(HANDLE theme); 328 329 typedef void (WINAPI* SetThemeAppPropertiesPtr) (DWORD flags); 330 typedef BOOL (WINAPI* IsThemeActivePtr)(); 331 typedef HRESULT (WINAPI* GetThemeIntPtr)(HANDLE hTheme, 332 int part_id, 333 int state_id, 334 int prop_id, 335 int *value); 336 337 // Function pointers into uxtheme.dll. 338 DrawThemeBackgroundPtr draw_theme_; 339 DrawThemeBackgroundExPtr draw_theme_ex_; 340 GetThemeColorPtr get_theme_color_; 341 GetThemeContentRectPtr get_theme_content_rect_; 342 GetThemePartSizePtr get_theme_part_size_; 343 OpenThemeDataPtr open_theme_; 344 CloseThemeDataPtr close_theme_; 345 SetThemeAppPropertiesPtr set_theme_properties_; 346 IsThemeActivePtr is_theme_active_; 347 GetThemeIntPtr get_theme_int_; 348 349 // Handle to uxtheme.dll. 350 HMODULE theme_dll_; 351 352 // A cache of open theme handles. 353 mutable HANDLE theme_handles_[LAST]; 354 355 // The system color change listener and the updated cache of system colors. 356 gfx::ScopedSysColorChangeListener color_change_listener_; 357 mutable std::map<int, SkColor> system_colors_; 358 359 DISALLOW_COPY_AND_ASSIGN(NativeThemeWin); 360 }; 361 362 } // namespace ui 363 364 #endif // UI_NATIVE_THEME_NATIVE_THEME_WIN_H_ 365