• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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