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