Home | History | Annotate | Download | only in native_theme
      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