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.
5 #include "ui/native_theme/native_theme_win.h"
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/win/scoped_gdi_object.h"
16 #include "base/win/scoped_hdc.h"
17 #include "base/win/scoped_select_object.h"
18 #include "base/win/windows_version.h"
19 #include "skia/ext/bitmap_platform_device.h"
20 #include "skia/ext/platform_canvas.h"
21 #include "skia/ext/skia_utils_win.h"
22 #include "third_party/skia/include/core/SkCanvas.h"
23 #include "third_party/skia/include/core/SkColor.h"
24 #include "third_party/skia/include/core/SkColorPriv.h"
25 #include "third_party/skia/include/core/SkShader.h"
26 #include "ui/base/resource/material_design/material_design_controller.h"
27 #include "ui/gfx/color_utils.h"
28 #include "ui/gfx/gdi_util.h"
29 #include "ui/gfx/geometry/rect.h"
30 #include "ui/gfx/geometry/rect_conversions.h"
31 #include "ui/gfx/win/dpi.h"
32 #include "ui/native_theme/common_theme.h"
34 // This was removed from Winvers.h but is still used.
35 #if !defined(COLOR_MENUHIGHLIGHT)
36 #define COLOR_MENUHIGHLIGHT 29
41 // Windows system color IDs cached and updated by the native theme.
42 const int kSystemColors
[] = {
55 void SetCheckerboardShader(SkPaint
* paint
, const RECT
& align_rect
) {
56 // Create a 2x2 checkerboard pattern using the 3D face and highlight colors.
57 const SkColor face
= color_utils::GetSysSkColor(COLOR_3DFACE
);
58 const SkColor highlight
= color_utils::GetSysSkColor(COLOR_3DHILIGHT
);
59 SkColor buffer
[] = { face
, highlight
, highlight
, face
};
60 // Confusing bit: we first create a temporary bitmap with our desired pattern,
61 // then copy it to another bitmap. The temporary bitmap doesn't take
62 // ownership of the pixel data, and so will point to garbage when this
63 // function returns. The copy will copy the pixel data into a place owned by
64 // the bitmap, which is in turn owned by the shader, etc., so it will live
65 // until we're done using it.
66 SkImageInfo info
= SkImageInfo::MakeN32Premul(2, 2);
68 temp_bitmap
.installPixels(info
, buffer
, info
.minRowBytes());
70 temp_bitmap
.copyTo(&bitmap
);
72 // Align the pattern with the upper corner of |align_rect|.
73 SkMatrix local_matrix
;
74 local_matrix
.setTranslate(SkIntToScalar(align_rect
.left
),
75 SkIntToScalar(align_rect
.top
));
76 skia::RefPtr
<SkShader
> shader
=
77 skia::AdoptRef(SkShader::CreateBitmapShader(bitmap
,
78 SkShader::kRepeat_TileMode
,
79 SkShader::kRepeat_TileMode
,
81 paint
->setShader(shader
.get());
87 // <-a-> <------b----->
90 // *: animating object
92 // - the animation goes from "[" to "]" repeatedly.
93 // - the animation offset is at first "|"
95 int ComputeAnimationProgress(int frame_width
,
97 int pixels_per_second
,
98 double animated_seconds
) {
99 int animation_width
= frame_width
+ object_width
;
100 double interval
= static_cast<double>(animation_width
) / pixels_per_second
;
101 double ratio
= fmod(animated_seconds
, interval
) / interval
;
102 return static_cast<int>(animation_width
* ratio
) - object_width
;
105 RECT
InsetRect(const RECT
* rect
, int size
) {
106 gfx::Rect
result(*rect
);
107 result
.Inset(size
, size
);
108 return result
.ToRECT();
115 bool NativeThemeWin::IsThemingActive() const {
116 return is_theme_active_
&& is_theme_active_();
119 bool NativeThemeWin::IsUsingHighContrastTheme() const {
120 if (is_using_high_contrast_valid_
)
121 return is_using_high_contrast_
;
123 result
.cbSize
= sizeof(HIGHCONTRAST
);
124 is_using_high_contrast_
=
125 SystemParametersInfo(SPI_GETHIGHCONTRAST
, result
.cbSize
, &result
, 0) &&
126 (result
.dwFlags
& HCF_HIGHCONTRASTON
) == HCF_HIGHCONTRASTON
;
127 is_using_high_contrast_valid_
= true;
128 return is_using_high_contrast_
;
131 HRESULT
NativeThemeWin::GetThemeColor(ThemeName theme
,
135 SkColor
* color
) const {
136 HANDLE handle
= GetThemeHandle(theme
);
137 if (!handle
|| !get_theme_color_
)
140 if (get_theme_color_(handle
, part_id
, state_id
, prop_id
, &color_ref
) != S_OK
)
142 *color
= skia::COLORREFToSkColor(color_ref
);
146 SkColor
NativeThemeWin::GetThemeColorWithDefault(ThemeName theme
,
150 int default_sys_color
) const {
152 return (GetThemeColor(theme
, part_id
, state_id
, prop_id
, &color
) == S_OK
) ?
153 color
: color_utils::GetSysSkColor(default_sys_color
);
156 gfx::Size
NativeThemeWin::GetThemeBorderSize(ThemeName theme
) const {
157 // For simplicity use the wildcard state==0, part==0, since it works
158 // for the cases we currently depend on.
160 return (GetThemeInt(theme
, 0, 0, TMT_BORDERSIZE
, &border
) == S_OK
) ?
161 gfx::Size(border
, border
) :
162 gfx::Size(GetSystemMetrics(SM_CXEDGE
), GetSystemMetrics(SM_CYEDGE
));
165 void NativeThemeWin::DisableTheming() const {
166 if (set_theme_properties_
)
167 set_theme_properties_(0);
170 void NativeThemeWin::CloseHandles() const {
174 for (int i
= 0; i
< LAST
; ++i
) {
175 if (theme_handles_
[i
]) {
176 close_theme_(theme_handles_
[i
]);
177 theme_handles_
[i
] = NULL
;
182 bool NativeThemeWin::IsClassicTheme(ThemeName name
) const {
183 return !theme_dll_
|| !GetThemeHandle(name
);
187 NativeThemeWin
* NativeThemeWin::instance() {
188 CR_DEFINE_STATIC_LOCAL(NativeThemeWin
, s_native_theme
, ());
189 return &s_native_theme
;
192 gfx::Size
NativeThemeWin::GetPartSize(Part part
,
194 const ExtraParams
& extra
) const {
195 gfx::Size part_size
= CommonThemeGetPartSize(part
, state
, extra
);
196 if (!part_size
.IsEmpty())
199 // The GetThemePartSize call below returns the default size without
200 // accounting for user customization (crbug/218291).
202 case kScrollbarDownArrow
:
203 case kScrollbarLeftArrow
:
204 case kScrollbarRightArrow
:
205 case kScrollbarUpArrow
:
206 case kScrollbarHorizontalThumb
:
207 case kScrollbarVerticalThumb
:
208 case kScrollbarHorizontalTrack
:
209 case kScrollbarVerticalTrack
: {
210 int size
= gfx::win::GetSystemMetricsInDIP(SM_CXVSCROLL
);
213 return gfx::Size(size
, size
);
219 int part_id
= GetWindowsPart(part
, state
, extra
);
220 int state_id
= GetWindowsState(part
, state
, extra
);
222 base::win::ScopedGetDC
screen_dc(NULL
);
224 if (SUCCEEDED(GetThemePartSize(GetThemeName(part
), screen_dc
, part_id
,
225 state_id
, NULL
, TS_TRUE
, &size
)))
226 return gfx::Size(size
.cx
, size
.cy
);
228 // TODO(rogerta): For now, we need to support radio buttons and checkboxes
229 // when theming is not enabled. Support for other parts can be added
231 return (part
== kCheckbox
|| part
== kRadio
) ?
232 gfx::Size(13, 13) : gfx::Size();
235 void NativeThemeWin::Paint(SkCanvas
* canvas
,
238 const gfx::Rect
& rect
,
239 const ExtraParams
& extra
) const {
245 CommonThemePaintComboboxArrow(canvas
, rect
);
247 case kMenuPopupGutter
:
248 CommonThemePaintMenuGutter(canvas
, rect
);
250 case kMenuPopupSeparator
:
251 CommonThemePaintMenuSeparator(canvas
, rect
);
253 case kMenuPopupBackground
:
254 CommonThemePaintMenuBackground(canvas
, rect
);
256 case kMenuItemBackground
:
257 CommonThemePaintMenuItemBackground(canvas
, state
, rect
);
263 bool needs_paint_indirect
= false;
264 if (!skia::SupportsPlatformPaint(canvas
)) {
265 // This block will only get hit with --enable-accelerated-drawing flag.
266 needs_paint_indirect
= true;
268 // Scrollbar components on Windows Classic theme (on all Windows versions)
269 // have particularly problematic alpha values, so always draw them
270 // indirectly. In addition, scrollbar thumbs and grippers for the Windows XP
271 // theme (available only on Windows XP) also need their alpha values
274 case kScrollbarDownArrow
:
275 case kScrollbarUpArrow
:
276 case kScrollbarLeftArrow
:
277 case kScrollbarRightArrow
:
278 needs_paint_indirect
= !GetThemeHandle(SCROLLBAR
);
280 case kScrollbarHorizontalThumb
:
281 case kScrollbarVerticalThumb
:
282 case kScrollbarHorizontalGripper
:
283 case kScrollbarVerticalGripper
:
284 needs_paint_indirect
= !GetThemeHandle(SCROLLBAR
) ||
285 base::win::GetVersion() == base::win::VERSION_XP
;
292 if (needs_paint_indirect
)
293 PaintIndirect(canvas
, part
, state
, rect
, extra
);
295 PaintDirect(canvas
, part
, state
, rect
, extra
);
298 NativeThemeWin::NativeThemeWin()
300 draw_theme_ex_(NULL
),
301 get_theme_color_(NULL
),
302 get_theme_content_rect_(NULL
),
303 get_theme_part_size_(NULL
),
306 set_theme_properties_(NULL
),
307 is_theme_active_(NULL
),
308 get_theme_int_(NULL
),
309 theme_dll_(LoadLibrary(L
"uxtheme.dll")),
310 color_change_listener_(this),
311 is_using_high_contrast_(false),
312 is_using_high_contrast_valid_(false) {
314 draw_theme_
= reinterpret_cast<DrawThemeBackgroundPtr
>(
315 GetProcAddress(theme_dll_
, "DrawThemeBackground"));
316 draw_theme_ex_
= reinterpret_cast<DrawThemeBackgroundExPtr
>(
317 GetProcAddress(theme_dll_
, "DrawThemeBackgroundEx"));
318 get_theme_color_
= reinterpret_cast<GetThemeColorPtr
>(
319 GetProcAddress(theme_dll_
, "GetThemeColor"));
320 get_theme_content_rect_
= reinterpret_cast<GetThemeContentRectPtr
>(
321 GetProcAddress(theme_dll_
, "GetThemeBackgroundContentRect"));
322 get_theme_part_size_
= reinterpret_cast<GetThemePartSizePtr
>(
323 GetProcAddress(theme_dll_
, "GetThemePartSize"));
324 open_theme_
= reinterpret_cast<OpenThemeDataPtr
>(
325 GetProcAddress(theme_dll_
, "OpenThemeData"));
326 close_theme_
= reinterpret_cast<CloseThemeDataPtr
>(
327 GetProcAddress(theme_dll_
, "CloseThemeData"));
328 set_theme_properties_
= reinterpret_cast<SetThemeAppPropertiesPtr
>(
329 GetProcAddress(theme_dll_
, "SetThemeAppProperties"));
330 is_theme_active_
= reinterpret_cast<IsThemeActivePtr
>(
331 GetProcAddress(theme_dll_
, "IsThemeActive"));
332 get_theme_int_
= reinterpret_cast<GetThemeIntPtr
>(
333 GetProcAddress(theme_dll_
, "GetThemeInt"));
335 memset(theme_handles_
, 0, sizeof(theme_handles_
));
337 // Initialize the cached system colors.
338 UpdateSystemColors();
341 NativeThemeWin::~NativeThemeWin() {
343 // todo (cpu): fix this soon. Making a call to CloseHandles() here breaks
344 // certain tests and the reliability bots.
346 FreeLibrary(theme_dll_
);
350 void NativeThemeWin::OnSysColorChange() {
351 UpdateSystemColors();
352 is_using_high_contrast_valid_
= false;
356 void NativeThemeWin::UpdateSystemColors() {
357 for (int i
= 0; i
< arraysize(kSystemColors
); ++i
) {
358 system_colors_
[kSystemColors
[i
]] =
359 color_utils::GetSysSkColor(kSystemColors
[i
]);
363 void NativeThemeWin::PaintDirect(SkCanvas
* canvas
,
366 const gfx::Rect
& rect
,
367 const ExtraParams
& extra
) const {
368 skia::ScopedPlatformPaint
scoped_platform_paint(canvas
);
369 HDC hdc
= scoped_platform_paint
.GetPlatformSurface();
373 PaintCheckbox(hdc
, part
, state
, rect
, extra
.button
);
375 case kInnerSpinButton
:
376 PaintSpinButton(hdc
, part
, state
, rect
, extra
.inner_spin
);
379 PaintMenuList(hdc
, state
, rect
, extra
.menu_list
);
382 PaintMenuCheck(hdc
, state
, rect
, extra
.menu_check
);
384 case kMenuCheckBackground
:
385 PaintMenuCheckBackground(hdc
, state
, rect
);
387 case kMenuPopupArrow
:
388 PaintMenuArrow(hdc
, state
, rect
, extra
.menu_arrow
);
390 case kMenuPopupBackground
:
391 PaintMenuBackground(hdc
, rect
);
393 case kMenuPopupGutter
:
394 PaintMenuGutter(hdc
, rect
);
396 case kMenuPopupSeparator
:
397 PaintMenuSeparator(hdc
, rect
);
399 case kMenuItemBackground
:
400 PaintMenuItemBackground(hdc
, state
, rect
, extra
.menu_item
);
403 PaintProgressBar(hdc
, rect
, extra
.progress_bar
);
406 PaintPushButton(hdc
, part
, state
, rect
, extra
.button
);
409 PaintRadioButton(hdc
, part
, state
, rect
, extra
.button
);
411 case kScrollbarDownArrow
:
412 case kScrollbarUpArrow
:
413 case kScrollbarLeftArrow
:
414 case kScrollbarRightArrow
:
415 PaintScrollbarArrow(hdc
, part
, state
, rect
, extra
.scrollbar_arrow
);
417 case kScrollbarHorizontalThumb
:
418 case kScrollbarVerticalThumb
:
419 case kScrollbarHorizontalGripper
:
420 case kScrollbarVerticalGripper
:
421 PaintScrollbarThumb(hdc
, part
, state
, rect
, extra
.scrollbar_thumb
);
423 case kScrollbarHorizontalTrack
:
424 case kScrollbarVerticalTrack
:
425 PaintScrollbarTrack(canvas
, hdc
, part
, state
, rect
,
426 extra
.scrollbar_track
);
428 case kScrollbarCorner
:
429 canvas
->drawColor(SK_ColorWHITE
, SkXfermode::kSrc_Mode
);
431 case kTabPanelBackground
:
432 PaintTabPanelBackground(hdc
, rect
);
435 PaintTextField(hdc
, part
, state
, rect
, extra
.text_field
);
439 PaintTrackbar(canvas
, hdc
, part
, state
, rect
, extra
.trackbar
);
441 case kWindowResizeGripper
:
442 PaintWindowResizeGripper(hdc
, rect
);
452 SkColor
NativeThemeWin::GetSystemColor(ColorId color_id
) const {
454 if (CommonThemeGetSystemColor(color_id
, &color
))
457 // TODO: Obtain the correct colors using GetSysColor.
458 const SkColor kInvalidColorIdColor
= SkColorSetRGB(255, 0, 128);
459 const SkColor kUrlTextColor
= SkColorSetRGB(0x0b, 0x80, 0x43);
461 const SkColor kDialogBackgroundColor
= SkColorSetRGB(251, 251, 251);
463 const SkColor kFocusedBorderColor
= SkColorSetRGB(0x4d, 0x90, 0xfe);
464 const SkColor kUnfocusedBorderColor
= SkColorSetRGB(0xd9, 0xd9, 0xd9);
466 const SkColor kButtonBackgroundColor
= SkColorSetRGB(0xde, 0xde, 0xde);
467 const SkColor kButtonHighlightColor
= SkColorSetARGB(200, 255, 255, 255);
468 const SkColor kButtonHoverColor
= SkColorSetRGB(6, 45, 117);
469 const SkColor kButtonHoverBackgroundColor
= SkColorSetRGB(0xEA, 0xEA, 0xEA);
471 const SkColor kEnabledMenuItemForegroundColor
= SkColorSetRGB(6, 45, 117);
472 const SkColor kDisabledMenuItemForegroundColor
= SkColorSetRGB(161, 161, 146);
473 const SkColor kFocusedMenuItemBackgroundColor
= SkColorSetRGB(246, 249, 253);
474 const SkColor kMenuSeparatorColor
= SkColorSetARGB(50, 0, 0, 0);
476 const SkColor kPositiveTextColor
= SkColorSetRGB(0x0b, 0x80, 0x43);
477 const SkColor kNegativeTextColor
= SkColorSetRGB(0xc5, 0x39, 0x29);
481 case kColorId_WindowBackground
:
482 return system_colors_
[COLOR_WINDOW
];
485 case kColorId_DialogBackground
:
486 return color_utils::IsInvertedColorScheme() ?
487 color_utils::InvertColor(kDialogBackgroundColor
) :
488 kDialogBackgroundColor
;
491 case kColorId_FocusedBorderColor
:
492 return kFocusedBorderColor
;
493 case kColorId_UnfocusedBorderColor
:
494 return kUnfocusedBorderColor
;
497 case kColorId_ButtonBackgroundColor
:
498 return kButtonBackgroundColor
;
499 case kColorId_ButtonEnabledColor
:
500 return system_colors_
[COLOR_BTNTEXT
];
501 case kColorId_ButtonDisabledColor
:
502 return system_colors_
[COLOR_GRAYTEXT
];
503 case kColorId_ButtonHighlightColor
:
504 return kButtonHighlightColor
;
505 case kColorId_ButtonHoverColor
:
506 return kButtonHoverColor
;
507 case kColorId_ButtonHoverBackgroundColor
:
508 return kButtonHoverBackgroundColor
;
509 case kColorId_BlueButtonEnabledColor
:
510 case kColorId_BlueButtonDisabledColor
:
511 case kColorId_BlueButtonPressedColor
:
512 case kColorId_BlueButtonHoverColor
:
514 return kInvalidColorIdColor
;
517 case kColorId_EnabledMenuItemForegroundColor
:
518 return kEnabledMenuItemForegroundColor
;
519 case kColorId_DisabledMenuItemForegroundColor
:
520 return kDisabledMenuItemForegroundColor
;
521 case kColorId_DisabledEmphasizedMenuItemForegroundColor
:
522 return SK_ColorBLACK
;
523 case kColorId_FocusedMenuItemBackgroundColor
:
524 return kFocusedMenuItemBackgroundColor
;
525 case kColorId_MenuSeparatorColor
:
526 return kMenuSeparatorColor
;
527 case kColorId_SelectedMenuItemForegroundColor
:
528 case kColorId_HoverMenuItemBackgroundColor
:
529 case kColorId_MenuBackgroundColor
:
530 case kColorId_MenuBorderColor
:
532 return kInvalidColorIdColor
;
535 case kColorId_EnabledMenuButtonBorderColor
:
536 case kColorId_FocusedMenuButtonBorderColor
:
537 case kColorId_HoverMenuButtonBorderColor
:
539 return kInvalidColorIdColor
;
542 case kColorId_LabelEnabledColor
:
543 return system_colors_
[COLOR_BTNTEXT
];
544 case kColorId_LabelDisabledColor
:
545 return system_colors_
[COLOR_GRAYTEXT
];
546 case kColorId_LabelBackgroundColor
:
547 return system_colors_
[COLOR_WINDOW
];
550 case kColorId_LinkDisabled
:
551 return system_colors_
[COLOR_WINDOWTEXT
];
552 case kColorId_LinkEnabled
:
553 return system_colors_
[COLOR_HOTLIGHT
];
554 case kColorId_LinkPressed
:
555 return SkColorSetRGB(200, 0, 0);
558 case kColorId_TextfieldDefaultColor
:
559 return system_colors_
[COLOR_WINDOWTEXT
];
560 case kColorId_TextfieldDefaultBackground
:
561 return system_colors_
[COLOR_WINDOW
];
562 case kColorId_TextfieldReadOnlyColor
:
563 return system_colors_
[COLOR_GRAYTEXT
];
564 case kColorId_TextfieldReadOnlyBackground
:
565 return system_colors_
[COLOR_3DFACE
];
566 case kColorId_TextfieldSelectionColor
:
567 return system_colors_
[COLOR_HIGHLIGHTTEXT
];
568 case kColorId_TextfieldSelectionBackgroundFocused
:
569 return system_colors_
[COLOR_HIGHLIGHT
];
572 case kColorId_TooltipBackground
:
573 case kColorId_TooltipText
:
575 return kInvalidColorIdColor
;
578 // NOTE: these aren't right for all themes, but as close as I could get.
579 case kColorId_TreeBackground
:
580 return system_colors_
[COLOR_WINDOW
];
581 case kColorId_TreeText
:
582 return system_colors_
[COLOR_WINDOWTEXT
];
583 case kColorId_TreeSelectedText
:
584 return system_colors_
[COLOR_HIGHLIGHTTEXT
];
585 case kColorId_TreeSelectedTextUnfocused
:
586 return system_colors_
[COLOR_BTNTEXT
];
587 case kColorId_TreeSelectionBackgroundFocused
:
588 return system_colors_
[COLOR_HIGHLIGHT
];
589 case kColorId_TreeSelectionBackgroundUnfocused
:
590 return system_colors_
[IsUsingHighContrastTheme() ?
591 COLOR_MENUHIGHLIGHT
: COLOR_BTNFACE
];
592 case kColorId_TreeArrow
:
593 return system_colors_
[COLOR_WINDOWTEXT
];
596 case kColorId_TableBackground
:
597 return system_colors_
[COLOR_WINDOW
];
598 case kColorId_TableText
:
599 return system_colors_
[COLOR_WINDOWTEXT
];
600 case kColorId_TableSelectedText
:
601 return system_colors_
[COLOR_HIGHLIGHTTEXT
];
602 case kColorId_TableSelectedTextUnfocused
:
603 return system_colors_
[COLOR_BTNTEXT
];
604 case kColorId_TableSelectionBackgroundFocused
:
605 return system_colors_
[COLOR_HIGHLIGHT
];
606 case kColorId_TableSelectionBackgroundUnfocused
:
607 return system_colors_
[IsUsingHighContrastTheme() ?
608 COLOR_MENUHIGHLIGHT
: COLOR_BTNFACE
];
609 case kColorId_TableGroupingIndicatorColor
:
610 return system_colors_
[COLOR_GRAYTEXT
];
613 case kColorId_ResultsTableNormalBackground
:
614 return system_colors_
[COLOR_WINDOW
];
615 case kColorId_ResultsTableHoveredBackground
:
616 return color_utils::AlphaBlend(system_colors_
[COLOR_HIGHLIGHT
],
617 system_colors_
[COLOR_WINDOW
], 0x40);
618 case kColorId_ResultsTableSelectedBackground
:
619 return system_colors_
[COLOR_HIGHLIGHT
];
620 case kColorId_ResultsTableNormalText
:
621 return system_colors_
[COLOR_WINDOWTEXT
];
622 case kColorId_ResultsTableHoveredText
:
623 return color_utils::GetReadableColor(
624 system_colors_
[COLOR_WINDOWTEXT
],
625 GetSystemColor(kColorId_ResultsTableHoveredBackground
));
626 case kColorId_ResultsTableSelectedText
:
627 return system_colors_
[COLOR_HIGHLIGHTTEXT
];
628 case kColorId_ResultsTableNormalDimmedText
:
629 return color_utils::AlphaBlend(system_colors_
[COLOR_WINDOWTEXT
],
630 system_colors_
[COLOR_WINDOW
], 0x80);
631 case kColorId_ResultsTableHoveredDimmedText
:
632 return color_utils::AlphaBlend(
633 system_colors_
[COLOR_WINDOWTEXT
],
634 GetSystemColor(kColorId_ResultsTableHoveredBackground
), 0x80);
635 case kColorId_ResultsTableSelectedDimmedText
:
636 return color_utils::AlphaBlend(system_colors_
[COLOR_HIGHLIGHTTEXT
],
637 system_colors_
[COLOR_HIGHLIGHT
], 0x80);
638 case kColorId_ResultsTableNormalUrl
:
639 return color_utils::GetReadableColor(kUrlTextColor
,
640 system_colors_
[COLOR_WINDOW
]);
641 case kColorId_ResultsTableHoveredUrl
:
642 return color_utils::GetReadableColor(
644 GetSystemColor(kColorId_ResultsTableHoveredBackground
));
645 case kColorId_ResultsTableSelectedUrl
:
646 return color_utils::GetReadableColor(kUrlTextColor
,
647 system_colors_
[COLOR_HIGHLIGHT
]);
648 case kColorId_ResultsTableNormalDivider
:
649 return color_utils::AlphaBlend(system_colors_
[COLOR_WINDOWTEXT
],
650 system_colors_
[COLOR_WINDOW
], 0x34);
651 case kColorId_ResultsTableHoveredDivider
:
652 return color_utils::AlphaBlend(
653 system_colors_
[COLOR_WINDOWTEXT
],
654 GetSystemColor(kColorId_ResultsTableHoveredBackground
), 0x34);
655 case kColorId_ResultsTableSelectedDivider
:
656 return color_utils::AlphaBlend(system_colors_
[COLOR_HIGHLIGHTTEXT
],
657 system_colors_
[COLOR_HIGHLIGHT
], 0x34);
658 case kColorId_ResultsTablePositiveText
:
659 return color_utils::GetReadableColor(kPositiveTextColor
,
660 system_colors_
[COLOR_WINDOW
]);
661 case kColorId_ResultsTablePositiveHoveredText
:
662 return color_utils::GetReadableColor(
664 GetSystemColor(kColorId_ResultsTableHoveredBackground
));
665 case kColorId_ResultsTablePositiveSelectedText
:
666 return color_utils::GetReadableColor(kPositiveTextColor
,
667 system_colors_
[COLOR_HIGHLIGHT
]);
668 case kColorId_ResultsTableNegativeText
:
669 return color_utils::GetReadableColor(kNegativeTextColor
,
670 system_colors_
[COLOR_WINDOW
]);
671 case kColorId_ResultsTableNegativeHoveredText
:
672 return color_utils::GetReadableColor(
674 GetSystemColor(kColorId_ResultsTableHoveredBackground
));
675 case kColorId_ResultsTableNegativeSelectedText
:
676 return color_utils::GetReadableColor(kNegativeTextColor
,
677 system_colors_
[COLOR_HIGHLIGHT
]);
680 return kInvalidColorIdColor
;
684 void NativeThemeWin::PaintIndirect(SkCanvas
* canvas
,
687 const gfx::Rect
& rect
,
688 const ExtraParams
& extra
) const {
689 // TODO(asvitkine): This path is pretty inefficient - for each paint operation
690 // it creates a new offscreen bitmap Skia canvas. This can
691 // be sped up by doing it only once per part/state and
692 // keeping a cache of the resulting bitmaps.
694 // Create an offscreen canvas that is backed by an HDC.
695 skia::RefPtr
<skia::BitmapPlatformDevice
> device
= skia::AdoptRef(
696 skia::BitmapPlatformDevice::Create(
697 rect
.width(), rect
.height(), false, NULL
));
699 SkCanvas
offscreen_canvas(device
.get());
700 DCHECK(skia::SupportsPlatformPaint(&offscreen_canvas
));
702 // Some of the Windows theme drawing operations do not write correct alpha
703 // values for fully-opaque pixels; instead the pixels get alpha 0. This is
704 // especially a problem on Windows XP or when using the Classic theme.
706 // To work-around this, mark all pixels with a placeholder value, to detect
707 // which pixels get touched by the paint operation. After paint, set any
708 // pixels that have alpha 0 to opaque and placeholders to fully-transparent.
709 const SkColor placeholder
= SkColorSetARGB(1, 0, 0, 0);
710 offscreen_canvas
.clear(placeholder
);
712 // Offset destination rects to have origin (0,0).
713 gfx::Rect
adjusted_rect(rect
.size());
714 ExtraParams
adjusted_extra(extra
);
717 adjusted_extra
.progress_bar
.value_rect_x
= 0;
718 adjusted_extra
.progress_bar
.value_rect_y
= 0;
720 case kScrollbarHorizontalTrack
:
721 case kScrollbarVerticalTrack
:
722 adjusted_extra
.scrollbar_track
.track_x
= 0;
723 adjusted_extra
.scrollbar_track
.track_y
= 0;
728 // Draw the theme controls using existing HDC-drawing code.
729 PaintDirect(&offscreen_canvas
, part
, state
, adjusted_rect
, adjusted_extra
);
731 // Copy the pixels to a bitmap that has ref-counted pixel storage, which is
732 // necessary to have when drawing to a SkPicture.
733 const SkBitmap
& hdc_bitmap
=
734 offscreen_canvas
.getDevice()->accessBitmap(false);
736 hdc_bitmap
.copyTo(&bitmap
, kN32_SkColorType
);
738 // Post-process the pixels to fix up the alpha values (see big comment above).
739 const SkPMColor placeholder_value
= SkPreMultiplyColor(placeholder
);
740 const int pixel_count
= rect
.width() * rect
.height();
741 SkPMColor
* pixels
= bitmap
.getAddr32(0, 0);
742 for (int i
= 0; i
< pixel_count
; i
++) {
743 if (pixels
[i
] == placeholder_value
) {
744 // Pixel wasn't touched - make it fully transparent.
745 pixels
[i
] = SkPackARGB32(0, 0, 0, 0);
746 } else if (SkGetPackedA32(pixels
[i
]) == 0) {
747 // Pixel was touched but has incorrect alpha of 0, make it fully opaque.
748 pixels
[i
] = SkPackARGB32(0xFF,
749 SkGetPackedR32(pixels
[i
]),
750 SkGetPackedG32(pixels
[i
]),
751 SkGetPackedB32(pixels
[i
]));
755 // Draw the offscreen bitmap to the destination canvas.
756 canvas
->drawBitmap(bitmap
, rect
.x(), rect
.y());
759 HRESULT
NativeThemeWin::GetThemePartSize(ThemeName theme_name
,
766 HANDLE handle
= GetThemeHandle(theme_name
);
767 return (handle
&& get_theme_part_size_
) ?
768 get_theme_part_size_(handle
, hdc
, part_id
, state_id
, rect
, ts
, size
) :
772 HRESULT
NativeThemeWin::PaintButton(HDC hdc
,
774 const ButtonExtraParams
& extra
,
778 HANDLE handle
= GetThemeHandle(BUTTON
);
779 if (handle
&& draw_theme_
)
780 return draw_theme_(handle
, hdc
, part_id
, state_id
, rect
, NULL
);
782 // Adjust classic_state based on part, state, and extras.
783 int classic_state
= extra
.classic_state
;
786 classic_state
|= DFCS_BUTTONCHECK
;
789 classic_state
|= DFCS_BUTTONRADIO
;
792 classic_state
|= DFCS_BUTTONPUSH
;
801 classic_state
|= DFCS_INACTIVE
;
807 classic_state
|= DFCS_PUSHED
;
815 classic_state
|= DFCS_CHECKED
;
818 // All pressed states have both low bits set, and no other states do.
819 const bool focused
= ((state_id
& ETS_FOCUSED
) == ETS_FOCUSED
);
820 const bool pressed
= ((state_id
& PBS_PRESSED
) == PBS_PRESSED
);
821 if ((BP_PUSHBUTTON
== part_id
) && (pressed
|| focused
)) {
822 // BP_PUSHBUTTON has a focus rect drawn around the outer edge, and the
823 // button itself is shrunk by 1 pixel.
824 HBRUSH brush
= GetSysColorBrush(COLOR_3DDKSHADOW
);
826 FrameRect(hdc
, rect
, brush
);
827 InflateRect(rect
, -1, -1);
830 DrawFrameControl(hdc
, rect
, DFC_BUTTON
, classic_state
);
832 // Draw the focus rectangle (the dotted line box) only on buttons. For radio
833 // and checkboxes, we let webkit draw the focus rectangle (orange glow).
834 if ((BP_PUSHBUTTON
== part_id
) && focused
) {
835 // The focus rect is inside the button. The exact number of pixels depends
836 // on whether we're in classic mode or using uxtheme.
837 if (handle
&& get_theme_content_rect_
) {
838 get_theme_content_rect_(handle
, hdc
, part_id
, state_id
, rect
, rect
);
840 InflateRect(rect
, -GetSystemMetrics(SM_CXEDGE
),
841 -GetSystemMetrics(SM_CYEDGE
));
843 DrawFocusRect(hdc
, rect
);
846 // Classic theme doesn't support indeterminate checkboxes. We draw
847 // a recangle inside a checkbox like IE10 does.
848 if (part_id
== BP_CHECKBOX
&& extra
.indeterminate
) {
849 RECT inner_rect
= *rect
;
850 // "4 / 13" is same as IE10 in classic theme.
851 int padding
= (inner_rect
.right
- inner_rect
.left
) * 4 / 13;
852 InflateRect(&inner_rect
, -padding
, -padding
);
853 int color_index
= state
== kDisabled
? COLOR_GRAYTEXT
: COLOR_WINDOWTEXT
;
854 FillRect(hdc
, &inner_rect
, GetSysColorBrush(color_index
));
860 HRESULT
NativeThemeWin::PaintMenuSeparator(
862 const gfx::Rect
& rect
) const {
863 RECT rect_win
= rect
.ToRECT();
865 HANDLE handle
= GetThemeHandle(MENU
);
866 if (handle
&& draw_theme_
) {
867 // Delta is needed for non-classic to move separator up slightly.
870 return draw_theme_(handle
, hdc
, MENU_POPUPSEPARATOR
, MPI_NORMAL
, &rect_win
,
874 DrawEdge(hdc
, &rect_win
, EDGE_ETCHED
, BF_TOP
);
878 HRESULT
NativeThemeWin::PaintMenuGutter(HDC hdc
,
879 const gfx::Rect
& rect
) const {
880 RECT rect_win
= rect
.ToRECT();
881 HANDLE handle
= GetThemeHandle(MENU
);
882 return (handle
&& draw_theme_
) ?
883 draw_theme_(handle
, hdc
, MENU_POPUPGUTTER
, MPI_NORMAL
, &rect_win
, NULL
) :
887 HRESULT
NativeThemeWin::PaintMenuArrow(
890 const gfx::Rect
& rect
,
891 const MenuArrowExtraParams
& extra
) const {
892 int state_id
= MSM_NORMAL
;
893 if (state
== kDisabled
)
894 state_id
= MSM_DISABLED
;
896 HANDLE handle
= GetThemeHandle(MENU
);
897 RECT rect_win
= rect
.ToRECT();
898 if (handle
&& draw_theme_
) {
899 if (extra
.pointing_right
) {
900 return draw_theme_(handle
, hdc
, MENU_POPUPSUBMENU
, state_id
, &rect_win
,
903 // There is no way to tell the uxtheme API to draw a left pointing arrow; it
904 // doesn't have a flag equivalent to DFCS_MENUARROWRIGHT. But they are
905 // needed for RTL locales on Vista. So use a memory DC and mirror the
906 // region with GDI's StretchBlt.
908 base::win::ScopedCreateDC
mem_dc(CreateCompatibleDC(hdc
));
909 base::win::ScopedBitmap
mem_bitmap(CreateCompatibleBitmap(hdc
, r
.width(),
911 base::win::ScopedSelectObject
select_bitmap(mem_dc
.Get(), mem_bitmap
);
912 // Copy and horizontally mirror the background from hdc into mem_dc. Use
913 // a negative-width source rect, starting at the rightmost pixel.
914 StretchBlt(mem_dc
.Get(), 0, 0, r
.width(), r
.height(),
915 hdc
, r
.right()-1, r
.y(), -r
.width(), r
.height(), SRCCOPY
);
917 RECT theme_rect
= {0, 0, r
.width(), r
.height()};
918 HRESULT result
= draw_theme_(handle
, mem_dc
.Get(), MENU_POPUPSUBMENU
,
919 state_id
, &theme_rect
, NULL
);
920 // Copy and mirror the result back into mem_dc.
921 StretchBlt(hdc
, r
.x(), r
.y(), r
.width(), r
.height(),
922 mem_dc
.Get(), r
.width()-1, 0, -r
.width(), r
.height(), SRCCOPY
);
926 // For some reason, Windows uses the name DFCS_MENUARROWRIGHT to indicate a
927 // left pointing arrow. This makes the following statement counterintuitive.
928 UINT pfc_state
= extra
.pointing_right
? DFCS_MENUARROW
: DFCS_MENUARROWRIGHT
;
929 return PaintFrameControl(hdc
, rect
, DFC_MENU
, pfc_state
, extra
.is_selected
,
933 HRESULT
NativeThemeWin::PaintMenuBackground(HDC hdc
,
934 const gfx::Rect
& rect
) const {
935 HANDLE handle
= GetThemeHandle(MENU
);
936 RECT rect_win
= rect
.ToRECT();
937 if (handle
&& draw_theme_
) {
938 HRESULT result
= draw_theme_(handle
, hdc
, MENU_POPUPBACKGROUND
, 0,
940 FrameRect(hdc
, &rect_win
, GetSysColorBrush(COLOR_3DSHADOW
));
944 FillRect(hdc
, &rect_win
, GetSysColorBrush(COLOR_MENU
));
945 DrawEdge(hdc
, &rect_win
, EDGE_RAISED
, BF_RECT
);
949 HRESULT
NativeThemeWin::PaintMenuCheck(
952 const gfx::Rect
& rect
,
953 const MenuCheckExtraParams
& extra
) const {
954 HANDLE handle
= GetThemeHandle(MENU
);
955 if (handle
&& draw_theme_
) {
956 const int state_id
= extra
.is_radio
?
957 ((state
== kDisabled
) ? MC_BULLETDISABLED
: MC_BULLETNORMAL
) :
958 ((state
== kDisabled
) ? MC_CHECKMARKDISABLED
: MC_CHECKMARKNORMAL
);
959 RECT rect_win
= rect
.ToRECT();
960 return draw_theme_(handle
, hdc
, MENU_POPUPCHECK
, state_id
, &rect_win
, NULL
);
963 return PaintFrameControl(hdc
, rect
, DFC_MENU
,
964 extra
.is_radio
? DFCS_MENUBULLET
: DFCS_MENUCHECK
,
965 extra
.is_selected
, state
);
968 HRESULT
NativeThemeWin::PaintMenuCheckBackground(HDC hdc
,
970 const gfx::Rect
& rect
) const {
971 HANDLE handle
= GetThemeHandle(MENU
);
972 if (!handle
|| !draw_theme_
)
973 return S_OK
; // Nothing to do for background.
975 int state_id
= state
== kDisabled
? MCB_DISABLED
: MCB_NORMAL
;
976 RECT rect_win
= rect
.ToRECT();
977 return draw_theme_(handle
, hdc
, MENU_POPUPCHECKBACKGROUND
, state_id
,
981 HRESULT
NativeThemeWin::PaintMenuItemBackground(
984 const gfx::Rect
& rect
,
985 const MenuItemExtraParams
& extra
) const {
986 HANDLE handle
= GetThemeHandle(MENU
);
987 RECT rect_win
= rect
.ToRECT();
988 int state_id
= MPI_NORMAL
;
991 state_id
= extra
.is_selected
? MPI_DISABLEDHOT
: MPI_DISABLED
;
1004 if (handle
&& draw_theme_
)
1005 return draw_theme_(handle
, hdc
, MENU_POPUPITEM
, state_id
, &rect_win
, NULL
);
1007 if (extra
.is_selected
)
1008 FillRect(hdc
, &rect_win
, GetSysColorBrush(COLOR_HIGHLIGHT
));
1012 HRESULT
NativeThemeWin::PaintPushButton(HDC hdc
,
1015 const gfx::Rect
& rect
,
1016 const ButtonExtraParams
& extra
) const {
1017 int state_id
= extra
.is_default
? PBS_DEFAULTED
: PBS_NORMAL
;
1020 state_id
= PBS_DISABLED
;
1028 state_id
= PBS_PRESSED
;
1035 RECT rect_win
= rect
.ToRECT();
1036 return PaintButton(hdc
, state
, extra
, BP_PUSHBUTTON
, state_id
, &rect_win
);
1039 HRESULT
NativeThemeWin::PaintRadioButton(HDC hdc
,
1042 const gfx::Rect
& rect
,
1043 const ButtonExtraParams
& extra
) const {
1044 int state_id
= extra
.checked
? RBS_CHECKEDNORMAL
: RBS_UNCHECKEDNORMAL
;
1047 state_id
= extra
.checked
? RBS_CHECKEDDISABLED
: RBS_UNCHECKEDDISABLED
;
1050 state_id
= extra
.checked
? RBS_CHECKEDHOT
: RBS_UNCHECKEDHOT
;
1055 state_id
= extra
.checked
? RBS_CHECKEDPRESSED
: RBS_UNCHECKEDPRESSED
;
1062 RECT rect_win
= rect
.ToRECT();
1063 return PaintButton(hdc
, state
, extra
, BP_RADIOBUTTON
, state_id
, &rect_win
);
1066 HRESULT
NativeThemeWin::PaintCheckbox(HDC hdc
,
1069 const gfx::Rect
& rect
,
1070 const ButtonExtraParams
& extra
) const {
1071 int state_id
= extra
.checked
?
1073 (extra
.indeterminate
? CBS_MIXEDNORMAL
: CBS_UNCHECKEDNORMAL
);
1076 state_id
= extra
.checked
?
1077 CBS_CHECKEDDISABLED
:
1078 (extra
.indeterminate
? CBS_MIXEDDISABLED
: CBS_UNCHECKEDDISABLED
);
1081 state_id
= extra
.checked
?
1083 (extra
.indeterminate
? CBS_MIXEDHOT
: CBS_UNCHECKEDHOT
);
1088 state_id
= extra
.checked
?
1089 CBS_CHECKEDPRESSED
:
1090 (extra
.indeterminate
? CBS_MIXEDPRESSED
: CBS_UNCHECKEDPRESSED
);
1097 RECT rect_win
= rect
.ToRECT();
1098 return PaintButton(hdc
, state
, extra
, BP_CHECKBOX
, state_id
, &rect_win
);
1101 HRESULT
NativeThemeWin::PaintMenuList(HDC hdc
,
1103 const gfx::Rect
& rect
,
1104 const MenuListExtraParams
& extra
) const {
1105 HANDLE handle
= GetThemeHandle(MENULIST
);
1106 RECT rect_win
= rect
.ToRECT();
1107 int state_id
= CBXS_NORMAL
;
1110 state_id
= CBXS_DISABLED
;
1113 state_id
= CBXS_HOT
;
1118 state_id
= CBXS_PRESSED
;
1125 if (handle
&& draw_theme_
)
1126 return draw_theme_(handle
, hdc
, CP_DROPDOWNBUTTON
, state_id
, &rect_win
,
1129 // Draw it manually.
1130 DrawFrameControl(hdc
, &rect_win
, DFC_SCROLL
,
1131 DFCS_SCROLLCOMBOBOX
| extra
.classic_state
);
1135 HRESULT
NativeThemeWin::PaintScrollbarArrow(
1139 const gfx::Rect
& rect
,
1140 const ScrollbarArrowExtraParams
& extra
) const {
1141 static const int state_id_matrix
[4][kNumStates
] = {
1142 {ABS_DOWNDISABLED
, ABS_DOWNHOT
, ABS_DOWNNORMAL
, ABS_DOWNPRESSED
},
1143 {ABS_LEFTDISABLED
, ABS_LEFTHOT
, ABS_LEFTNORMAL
, ABS_LEFTPRESSED
},
1144 {ABS_RIGHTDISABLED
, ABS_RIGHTHOT
, ABS_RIGHTNORMAL
, ABS_RIGHTPRESSED
},
1145 {ABS_UPDISABLED
, ABS_UPHOT
, ABS_UPNORMAL
, ABS_UPPRESSED
},
1147 HANDLE handle
= GetThemeHandle(SCROLLBAR
);
1148 RECT rect_win
= rect
.ToRECT();
1149 if (handle
&& draw_theme_
) {
1150 int index
= part
- kScrollbarDownArrow
;
1151 DCHECK_GE(index
, 0);
1152 DCHECK_LT(static_cast<size_t>(index
), arraysize(state_id_matrix
));
1153 int state_id
= state_id_matrix
[index
][state
];
1155 // Hovering means that the cursor is over the scroolbar, but not over the
1156 // specific arrow itself. We don't want to show it "hot" mode, but only
1158 if (state
== kHovered
&& extra
.is_hovering
) {
1160 case kScrollbarDownArrow
:
1161 state_id
= ABS_DOWNHOVER
;
1163 case kScrollbarLeftArrow
:
1164 state_id
= ABS_LEFTHOVER
;
1166 case kScrollbarRightArrow
:
1167 state_id
= ABS_RIGHTHOVER
;
1169 case kScrollbarUpArrow
:
1170 state_id
= ABS_UPHOVER
;
1177 return PaintScaledTheme(handle
, hdc
, SBP_ARROWBTN
, state_id
, rect
);
1180 int classic_state
= DFCS_SCROLLDOWN
;
1182 case kScrollbarDownArrow
:
1184 case kScrollbarLeftArrow
:
1185 classic_state
= DFCS_SCROLLLEFT
;
1187 case kScrollbarRightArrow
:
1188 classic_state
= DFCS_SCROLLRIGHT
;
1190 case kScrollbarUpArrow
:
1191 classic_state
= DFCS_SCROLLUP
;
1199 classic_state
|= DFCS_INACTIVE
;
1202 classic_state
|= DFCS_HOT
;
1207 classic_state
|= DFCS_PUSHED
;
1213 DrawFrameControl(hdc
, &rect_win
, DFC_SCROLL
, classic_state
);
1217 HRESULT
NativeThemeWin::PaintScrollbarThumb(
1221 const gfx::Rect
& rect
,
1222 const ScrollbarThumbExtraParams
& extra
) const {
1223 HANDLE handle
= GetThemeHandle(SCROLLBAR
);
1224 RECT rect_win
= rect
.ToRECT();
1226 int part_id
= SBP_THUMBBTNVERT
;
1228 case kScrollbarHorizontalThumb
:
1229 part_id
= SBP_THUMBBTNHORZ
;
1231 case kScrollbarVerticalThumb
:
1233 case kScrollbarHorizontalGripper
:
1234 part_id
= SBP_GRIPPERHORZ
;
1236 case kScrollbarVerticalGripper
:
1237 part_id
= SBP_GRIPPERVERT
;
1244 int state_id
= SCRBS_NORMAL
;
1247 state_id
= SCRBS_DISABLED
;
1250 state_id
= extra
.is_hovering
? SCRBS_HOVER
: SCRBS_HOT
;
1255 state_id
= SCRBS_PRESSED
;
1262 if (handle
&& draw_theme_
)
1263 return PaintScaledTheme(handle
, hdc
, part_id
, state_id
, rect
);
1265 // Draw it manually.
1266 if ((part_id
== SBP_THUMBBTNHORZ
) || (part_id
== SBP_THUMBBTNVERT
))
1267 DrawEdge(hdc
, &rect_win
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
1268 // Classic mode doesn't have a gripper.
1272 HRESULT
NativeThemeWin::PaintScrollbarTrack(
1277 const gfx::Rect
& rect
,
1278 const ScrollbarTrackExtraParams
& extra
) const {
1279 HANDLE handle
= GetThemeHandle(SCROLLBAR
);
1280 RECT rect_win
= rect
.ToRECT();
1282 const int part_id
= extra
.is_upper
?
1283 ((part
== kScrollbarHorizontalTrack
) ?
1284 SBP_UPPERTRACKHORZ
: SBP_UPPERTRACKVERT
) :
1285 ((part
== kScrollbarHorizontalTrack
) ?
1286 SBP_LOWERTRACKHORZ
: SBP_LOWERTRACKVERT
);
1288 int state_id
= SCRBS_NORMAL
;
1291 state_id
= SCRBS_DISABLED
;
1294 state_id
= SCRBS_HOVER
;
1299 state_id
= SCRBS_PRESSED
;
1306 if (handle
&& draw_theme_
)
1307 return draw_theme_(handle
, hdc
, part_id
, state_id
, &rect_win
, NULL
);
1309 // Draw it manually.
1310 if ((system_colors_
[COLOR_SCROLLBAR
] != system_colors_
[COLOR_3DFACE
]) &&
1311 (system_colors_
[COLOR_SCROLLBAR
] != system_colors_
[COLOR_WINDOW
])) {
1312 FillRect(hdc
, &rect_win
, reinterpret_cast<HBRUSH
>(COLOR_SCROLLBAR
+ 1));
1315 RECT align_rect
= gfx::Rect(extra
.track_x
, extra
.track_y
, extra
.track_width
,
1316 extra
.track_height
).ToRECT();
1317 SetCheckerboardShader(&paint
, align_rect
);
1318 canvas
->drawIRect(skia::RECTToSkIRect(rect_win
), paint
);
1320 if (extra
.classic_state
& DFCS_PUSHED
)
1321 InvertRect(hdc
, &rect_win
);
1325 HRESULT
NativeThemeWin::PaintSpinButton(
1329 const gfx::Rect
& rect
,
1330 const InnerSpinButtonExtraParams
& extra
) const {
1331 HANDLE handle
= GetThemeHandle(SPIN
);
1332 RECT rect_win
= rect
.ToRECT();
1333 int part_id
= extra
.spin_up
? SPNP_UP
: SPNP_DOWN
;
1334 int state_id
= extra
.spin_up
? UPS_NORMAL
: DNS_NORMAL
;
1337 state_id
= extra
.spin_up
? UPS_DISABLED
: DNS_DISABLED
;
1340 state_id
= extra
.spin_up
? UPS_HOT
: DNS_HOT
;
1345 state_id
= extra
.spin_up
? UPS_PRESSED
: DNS_PRESSED
;
1352 if (handle
&& draw_theme_
)
1353 return draw_theme_(handle
, hdc
, part_id
, state_id
, &rect_win
, NULL
);
1354 DrawFrameControl(hdc
, &rect_win
, DFC_SCROLL
, extra
.classic_state
);
1358 HRESULT
NativeThemeWin::PaintTrackbar(
1363 const gfx::Rect
& rect
,
1364 const TrackbarExtraParams
& extra
) const {
1365 const int part_id
= extra
.vertical
?
1366 ((part
== kTrackbarTrack
) ? TKP_TRACKVERT
: TKP_THUMBVERT
) :
1367 ((part
== kTrackbarTrack
) ? TKP_TRACK
: TKP_THUMBBOTTOM
);
1369 int state_id
= TUS_NORMAL
;
1372 state_id
= TUS_DISABLED
;
1380 state_id
= TUS_PRESSED
;
1387 // Make the channel be 4 px thick in the center of the supplied rect. (4 px
1388 // matches what XP does in various menus; GetThemePartSize() doesn't seem to
1389 // return good values here.)
1390 RECT rect_win
= rect
.ToRECT();
1391 RECT channel_rect
= rect
.ToRECT();
1392 const int channel_thickness
= 4;
1393 if (part_id
== TKP_TRACK
) {
1395 ((channel_rect
.bottom
- channel_rect
.top
- channel_thickness
) / 2);
1396 channel_rect
.bottom
= channel_rect
.top
+ channel_thickness
;
1397 } else if (part_id
== TKP_TRACKVERT
) {
1398 channel_rect
.left
+=
1399 ((channel_rect
.right
- channel_rect
.left
- channel_thickness
) / 2);
1400 channel_rect
.right
= channel_rect
.left
+ channel_thickness
;
1401 } // else this isn't actually a channel, so |channel_rect| == |rect|.
1403 HANDLE handle
= GetThemeHandle(TRACKBAR
);
1404 if (handle
&& draw_theme_
)
1405 return draw_theme_(handle
, hdc
, part_id
, state_id
, &channel_rect
, NULL
);
1407 // Classic mode, draw it manually.
1408 if ((part_id
== TKP_TRACK
) || (part_id
== TKP_TRACKVERT
)) {
1409 DrawEdge(hdc
, &channel_rect
, EDGE_SUNKEN
, BF_RECT
);
1410 } else if (part_id
== TKP_THUMBVERT
) {
1411 DrawEdge(hdc
, &rect_win
, EDGE_RAISED
, BF_RECT
| BF_SOFT
| BF_MIDDLE
);
1413 // Split rect into top and bottom pieces.
1414 RECT top_section
= rect
.ToRECT();
1415 RECT bottom_section
= rect
.ToRECT();
1416 top_section
.bottom
-= ((bottom_section
.right
- bottom_section
.left
) / 2);
1417 bottom_section
.top
= top_section
.bottom
;
1418 DrawEdge(hdc
, &top_section
, EDGE_RAISED
,
1419 BF_LEFT
| BF_TOP
| BF_RIGHT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
1421 // Split triangular piece into two diagonals.
1422 RECT
& left_half
= bottom_section
;
1423 RECT right_half
= bottom_section
;
1424 right_half
.left
+= ((bottom_section
.right
- bottom_section
.left
) / 2);
1425 left_half
.right
= right_half
.left
;
1426 DrawEdge(hdc
, &left_half
, EDGE_RAISED
,
1427 BF_DIAGONAL_ENDTOPLEFT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
1428 DrawEdge(hdc
, &right_half
, EDGE_RAISED
,
1429 BF_DIAGONAL_ENDBOTTOMLEFT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
1431 // If the button is pressed, draw hatching.
1432 if (extra
.classic_state
& DFCS_PUSHED
) {
1434 SetCheckerboardShader(&paint
, rect_win
);
1436 // Fill all three pieces with the pattern.
1437 canvas
->drawIRect(skia::RECTToSkIRect(top_section
), paint
);
1439 SkScalar left_triangle_top
= SkIntToScalar(left_half
.top
);
1440 SkScalar left_triangle_right
= SkIntToScalar(left_half
.right
);
1441 SkPath left_triangle
;
1442 left_triangle
.moveTo(SkIntToScalar(left_half
.left
), left_triangle_top
);
1443 left_triangle
.lineTo(left_triangle_right
, left_triangle_top
);
1444 left_triangle
.lineTo(left_triangle_right
,
1445 SkIntToScalar(left_half
.bottom
));
1446 left_triangle
.close();
1447 canvas
->drawPath(left_triangle
, paint
);
1449 SkScalar right_triangle_left
= SkIntToScalar(right_half
.left
);
1450 SkScalar right_triangle_top
= SkIntToScalar(right_half
.top
);
1451 SkPath right_triangle
;
1452 right_triangle
.moveTo(right_triangle_left
, right_triangle_top
);
1453 right_triangle
.lineTo(SkIntToScalar(right_half
.right
),
1454 right_triangle_top
);
1455 right_triangle
.lineTo(right_triangle_left
,
1456 SkIntToScalar(right_half
.bottom
));
1457 right_triangle
.close();
1458 canvas
->drawPath(right_triangle
, paint
);
1464 HRESULT
NativeThemeWin::PaintProgressBar(
1466 const gfx::Rect
& rect
,
1467 const ProgressBarExtraParams
& extra
) const {
1468 // There is no documentation about the animation speed, frame-rate, nor
1469 // size of moving overlay of the indeterminate progress bar.
1470 // So we just observed real-world programs and guessed following parameters.
1471 const int kDeterminateOverlayPixelsPerSecond
= 300;
1472 const int kDeterminateOverlayWidth
= 120;
1473 const int kIndeterminateOverlayPixelsPerSecond
= 175;
1474 const int kVistaIndeterminateOverlayWidth
= 120;
1475 const int kXPIndeterminateOverlayWidth
= 55;
1476 // The thickness of the bar frame inside |value_rect|
1477 const int kXPBarPadding
= 3;
1479 RECT bar_rect
= rect
.ToRECT();
1480 RECT value_rect
= gfx::Rect(extra
.value_rect_x
,
1482 extra
.value_rect_width
,
1483 extra
.value_rect_height
).ToRECT();
1485 HANDLE handle
= GetThemeHandle(PROGRESS
);
1486 if (!handle
|| !draw_theme_
|| !draw_theme_ex_
) {
1487 FillRect(hdc
, &bar_rect
, GetSysColorBrush(COLOR_BTNFACE
));
1488 FillRect(hdc
, &value_rect
, GetSysColorBrush(COLOR_BTNSHADOW
));
1489 DrawEdge(hdc
, &bar_rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1493 draw_theme_(handle
, hdc
, PP_BAR
, 0, &bar_rect
, NULL
);
1495 bool pre_vista
= base::win::GetVersion() < base::win::VERSION_VISTA
;
1496 int bar_width
= bar_rect
.right
- bar_rect
.left
;
1497 if (!extra
.determinate
) {
1498 // The glossy overlay for the indeterminate progress bar has a small pause
1499 // after each animation. We emulate this by adding an invisible margin the
1500 // animation has to traverse.
1501 int width_with_margin
= bar_width
+ kIndeterminateOverlayPixelsPerSecond
;
1502 int overlay_width
= pre_vista
?
1503 kXPIndeterminateOverlayWidth
: kVistaIndeterminateOverlayWidth
;
1504 RECT overlay_rect
= bar_rect
;
1505 overlay_rect
.left
+= ComputeAnimationProgress(
1506 width_with_margin
, overlay_width
, kIndeterminateOverlayPixelsPerSecond
,
1507 extra
.animated_seconds
);
1508 overlay_rect
.right
= overlay_rect
.left
+ overlay_width
;
1510 RECT shrunk_rect
= InsetRect(&overlay_rect
, kXPBarPadding
);
1511 RECT shrunk_bar_rect
= InsetRect(&bar_rect
, kXPBarPadding
);
1512 draw_theme_(handle
, hdc
, PP_CHUNK
, 0, &shrunk_rect
, &shrunk_bar_rect
);
1514 draw_theme_(handle
, hdc
, PP_MOVEOVERLAY
, 0, &overlay_rect
, &bar_rect
);
1519 // We care about the direction here because PP_CHUNK painting is asymmetric.
1520 // TODO(morrita): This RTL guess can be wrong. We should pass in the
1521 // direction from WebKit.
1522 const DTBGOPTS value_draw_options
= {
1524 (bar_rect
.right
== value_rect
.right
&& bar_rect
.left
!= value_rect
.left
) ?
1529 // On XP, the progress bar is chunk-style and has no glossy effect. We need
1530 // to shrink the destination rect to fit the part inside the bar with an
1531 // appropriate margin.
1532 RECT shrunk_value_rect
= InsetRect(&value_rect
, kXPBarPadding
);
1533 draw_theme_ex_(handle
, hdc
, PP_CHUNK
, 0, &shrunk_value_rect
,
1534 &value_draw_options
);
1536 // On Vista or later, the progress bar part has a single-block value part
1537 // and a glossy effect. The value part has exactly same height as the bar
1538 // part, so we don't need to shrink the rect.
1539 draw_theme_ex_(handle
, hdc
, PP_FILL
, 0, &value_rect
, &value_draw_options
);
1541 RECT overlay_rect
= value_rect
;
1542 overlay_rect
.left
+= ComputeAnimationProgress(
1543 bar_width
, kDeterminateOverlayWidth
, kDeterminateOverlayPixelsPerSecond
,
1544 extra
.animated_seconds
);
1545 overlay_rect
.right
= overlay_rect
.left
+ kDeterminateOverlayWidth
;
1546 draw_theme_(handle
, hdc
, PP_MOVEOVERLAY
, 0, &overlay_rect
, &value_rect
);
1551 HRESULT
NativeThemeWin::PaintWindowResizeGripper(HDC hdc
,
1552 const gfx::Rect
& rect
) const {
1553 HANDLE handle
= GetThemeHandle(STATUS
);
1554 RECT rect_win
= rect
.ToRECT();
1555 if (handle
&& draw_theme_
) {
1556 // Paint the status bar gripper. There doesn't seem to be a standard
1557 // gripper in Windows for the space between scrollbars. This is pretty
1558 // close, but it's supposed to be painted over a status bar.
1559 return draw_theme_(handle
, hdc
, SP_GRIPPER
, 0, &rect_win
, NULL
);
1562 // Draw a windows classic scrollbar gripper.
1563 DrawFrameControl(hdc
, &rect_win
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
1567 HRESULT
NativeThemeWin::PaintTabPanelBackground(HDC hdc
,
1568 const gfx::Rect
& rect
) const {
1569 HANDLE handle
= GetThemeHandle(TAB
);
1570 RECT rect_win
= rect
.ToRECT();
1571 if (handle
&& draw_theme_
)
1572 return draw_theme_(handle
, hdc
, TABP_BODY
, 0, &rect_win
, NULL
);
1574 // Classic just renders a flat color background.
1575 FillRect(hdc
, &rect_win
, reinterpret_cast<HBRUSH
>(COLOR_3DFACE
+ 1));
1579 HRESULT
NativeThemeWin::PaintTextField(
1583 const gfx::Rect
& rect
,
1584 const TextFieldExtraParams
& extra
) const {
1585 int state_id
= ETS_NORMAL
;
1588 state_id
= ETS_DISABLED
;
1594 if (extra
.is_read_only
)
1595 state_id
= ETS_READONLY
;
1596 else if (extra
.is_focused
)
1597 state_id
= ETS_FOCUSED
;
1600 state_id
= ETS_SELECTED
;
1607 RECT rect_win
= rect
.ToRECT();
1608 return PaintTextField(hdc
, EP_EDITTEXT
, state_id
, extra
.classic_state
,
1610 skia::SkColorToCOLORREF(extra
.background_color
),
1611 extra
.fill_content_area
, extra
.draw_edges
);
1614 HRESULT
NativeThemeWin::PaintTextField(HDC hdc
,
1620 bool fill_content_area
,
1621 bool draw_edges
) const {
1622 // TODO(ojan): http://b/1210017 Figure out how to give the ability to
1623 // exclude individual edges from being drawn.
1625 HANDLE handle
= GetThemeHandle(TEXTFIELD
);
1626 // TODO(mpcomplete): can we detect if the color is specified by the user,
1627 // and if not, just use the system color?
1628 // CreateSolidBrush() accepts a RGB value but alpha must be 0.
1629 base::win::ScopedGDIObject
<HBRUSH
> bg_brush(CreateSolidBrush(color
));
1630 // DrawThemeBackgroundEx was introduced in XP SP2, so that it's possible
1631 // draw_theme_ex_ is NULL and draw_theme_ is non-null.
1632 if (!handle
|| (!draw_theme_ex_
&& (!draw_theme_
|| !draw_edges
))) {
1633 // Draw it manually.
1635 DrawEdge(hdc
, rect
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
1637 if (fill_content_area
) {
1638 FillRect(hdc
, rect
, (classic_state
& DFCS_INACTIVE
) ?
1639 reinterpret_cast<HBRUSH
>(COLOR_BTNFACE
+ 1) : bg_brush
);
1644 static const DTBGOPTS omit_border_options
= {
1649 HRESULT hr
= draw_theme_ex_
?
1650 draw_theme_ex_(handle
, hdc
, part_id
, state_id
, rect
,
1651 draw_edges
? NULL
: &omit_border_options
) :
1652 draw_theme_(handle
, hdc
, part_id
, state_id
, rect
, NULL
);
1654 // TODO(maruel): Need to be fixed if get_theme_content_rect_ is NULL.
1655 if (fill_content_area
&& get_theme_content_rect_
) {
1657 hr
= get_theme_content_rect_(handle
, hdc
, part_id
, state_id
, rect
,
1659 FillRect(hdc
, &content_rect
, bg_brush
);
1664 HRESULT
NativeThemeWin::PaintScaledTheme(HANDLE theme
,
1668 const gfx::Rect
& rect
) const {
1669 // Correct the scaling and positioning of sub-components such as scrollbar
1670 // arrows and thumb grippers in the event that the world transform applies
1671 // scaling (e.g. in high-DPI mode).
1672 XFORM save_transform
;
1673 if (GetWorldTransform(hdc
, &save_transform
)) {
1674 float scale
= save_transform
.eM11
;
1675 if (scale
!= 1 && save_transform
.eM12
== 0) {
1676 ModifyWorldTransform(hdc
, NULL
, MWT_IDENTITY
);
1677 gfx::Rect scaled_rect
= gfx::ScaleToEnclosedRect(rect
, scale
);
1678 scaled_rect
.Offset(save_transform
.eDx
, save_transform
.eDy
);
1679 RECT bounds
= scaled_rect
.ToRECT();
1680 HRESULT result
= draw_theme_(theme
, hdc
, part_id
, state_id
, &bounds
,
1682 SetWorldTransform(hdc
, &save_transform
);
1686 RECT bounds
= rect
.ToRECT();
1687 return draw_theme_(theme
, hdc
, part_id
, state_id
, &bounds
, NULL
);
1691 NativeThemeWin::ThemeName
NativeThemeWin::GetThemeName(Part part
) {
1697 case kInnerSpinButton
:
1701 case kMenuPopupArrow
:
1702 case kMenuPopupGutter
:
1703 case kMenuPopupSeparator
:
1707 case kScrollbarDownArrow
:
1708 case kScrollbarLeftArrow
:
1709 case kScrollbarRightArrow
:
1710 case kScrollbarUpArrow
:
1711 case kScrollbarHorizontalThumb
:
1712 case kScrollbarVerticalThumb
:
1713 case kScrollbarHorizontalTrack
:
1714 case kScrollbarVerticalTrack
:
1721 case kWindowResizeGripper
:
1723 case kComboboxArrow
:
1724 case kMenuCheckBackground
:
1725 case kMenuPopupBackground
:
1726 case kMenuItemBackground
:
1727 case kScrollbarHorizontalGripper
:
1728 case kScrollbarVerticalGripper
:
1729 case kScrollbarCorner
:
1730 case kTabPanelBackground
:
1731 case kTrackbarThumb
:
1732 case kTrackbarTrack
:
1740 int NativeThemeWin::GetWindowsPart(Part part
,
1742 const ExtraParams
& extra
) {
1747 return MENU_POPUPCHECK
;
1748 case kMenuPopupArrow
:
1749 return MENU_POPUPSUBMENU
;
1750 case kMenuPopupGutter
:
1751 return MENU_POPUPGUTTER
;
1752 case kMenuPopupSeparator
:
1753 return MENU_POPUPSEPARATOR
;
1755 return BP_PUSHBUTTON
;
1757 return BP_RADIOBUTTON
;
1758 case kScrollbarDownArrow
:
1759 case kScrollbarLeftArrow
:
1760 case kScrollbarRightArrow
:
1761 case kScrollbarUpArrow
:
1762 return SBP_ARROWBTN
;
1763 case kScrollbarHorizontalThumb
:
1764 return SBP_THUMBBTNHORZ
;
1765 case kScrollbarVerticalThumb
:
1766 return SBP_THUMBBTNVERT
;
1767 case kWindowResizeGripper
:
1769 case kComboboxArrow
:
1770 case kInnerSpinButton
:
1772 case kMenuCheckBackground
:
1773 case kMenuPopupBackground
:
1774 case kMenuItemBackground
:
1776 case kScrollbarHorizontalTrack
:
1777 case kScrollbarVerticalTrack
:
1778 case kScrollbarHorizontalGripper
:
1779 case kScrollbarVerticalGripper
:
1780 case kScrollbarCorner
:
1783 case kTabPanelBackground
:
1785 case kTrackbarThumb
:
1786 case kTrackbarTrack
:
1793 int NativeThemeWin::GetWindowsState(Part part
,
1795 const ExtraParams
& extra
) {
1800 return CBS_UNCHECKEDDISABLED
;
1802 return CBS_UNCHECKEDHOT
;
1804 return CBS_UNCHECKEDNORMAL
;
1806 return CBS_UNCHECKEDPRESSED
;
1814 return extra
.menu_check
.is_radio
?
1815 MC_BULLETDISABLED
: MC_CHECKMARKDISABLED
;
1819 return extra
.menu_check
.is_radio
?
1820 MC_BULLETNORMAL
: MC_CHECKMARKNORMAL
;
1825 case kMenuPopupArrow
:
1826 case kMenuPopupGutter
:
1827 case kMenuPopupSeparator
:
1830 return MBI_DISABLED
;
1844 return PBS_DISABLED
;
1858 return RBS_UNCHECKEDDISABLED
;
1860 return RBS_UNCHECKEDHOT
;
1862 return RBS_UNCHECKEDNORMAL
;
1864 return RBS_UNCHECKEDPRESSED
;
1869 case kScrollbarDownArrow
:
1872 return ABS_DOWNDISABLED
;
1874 // Mimic ScrollbarThemeChromiumWin.cpp in WebKit.
1875 return base::win::GetVersion() < base::win::VERSION_VISTA
?
1876 ABS_DOWNHOT
: ABS_DOWNHOVER
;
1878 return ABS_DOWNNORMAL
;
1880 return ABS_DOWNPRESSED
;
1885 case kScrollbarLeftArrow
:
1888 return ABS_LEFTDISABLED
;
1890 // Mimic ScrollbarThemeChromiumWin.cpp in WebKit.
1891 return base::win::GetVersion() < base::win::VERSION_VISTA
?
1892 ABS_LEFTHOT
: ABS_LEFTHOVER
;
1894 return ABS_LEFTNORMAL
;
1896 return ABS_LEFTPRESSED
;
1901 case kScrollbarRightArrow
:
1904 return ABS_RIGHTDISABLED
;
1906 // Mimic ScrollbarThemeChromiumWin.cpp in WebKit.
1907 return base::win::GetVersion() < base::win::VERSION_VISTA
?
1908 ABS_RIGHTHOT
: ABS_RIGHTHOVER
;
1910 return ABS_RIGHTNORMAL
;
1912 return ABS_RIGHTPRESSED
;
1918 case kScrollbarUpArrow
:
1921 return ABS_UPDISABLED
;
1923 // Mimic ScrollbarThemeChromiumWin.cpp in WebKit.
1924 return base::win::GetVersion() < base::win::VERSION_VISTA
?
1925 ABS_UPHOT
: ABS_UPHOVER
;
1927 return ABS_UPNORMAL
;
1929 return ABS_UPPRESSED
;
1935 case kScrollbarHorizontalThumb
:
1936 case kScrollbarVerticalThumb
:
1939 return SCRBS_DISABLED
;
1941 // Mimic WebKit's behaviour in ScrollbarThemeChromiumWin.cpp.
1942 return base::win::GetVersion() < base::win::VERSION_VISTA
?
1943 SCRBS_HOT
: SCRBS_HOVER
;
1945 return SCRBS_NORMAL
;
1947 return SCRBS_PRESSED
;
1952 case kWindowResizeGripper
:
1958 return 1; // gripper has no windows state
1963 case kComboboxArrow
:
1964 case kInnerSpinButton
:
1966 case kMenuCheckBackground
:
1967 case kMenuPopupBackground
:
1968 case kMenuItemBackground
:
1970 case kScrollbarHorizontalTrack
:
1971 case kScrollbarVerticalTrack
:
1972 case kScrollbarHorizontalGripper
:
1973 case kScrollbarVerticalGripper
:
1974 case kScrollbarCorner
:
1977 case kTabPanelBackground
:
1979 case kTrackbarThumb
:
1980 case kTrackbarTrack
:
1987 HRESULT
NativeThemeWin::GetThemeInt(ThemeName theme
,
1992 HANDLE handle
= GetThemeHandle(theme
);
1993 return (handle
&& get_theme_int_
) ?
1994 get_theme_int_(handle
, part_id
, state_id
, prop_id
, value
) : E_NOTIMPL
;
1997 HRESULT
NativeThemeWin::PaintFrameControl(HDC hdc
,
1998 const gfx::Rect
& rect
,
2002 State control_state
) const {
2003 const int width
= rect
.width();
2004 const int height
= rect
.height();
2006 // DrawFrameControl for menu arrow/check wants a monochrome bitmap.
2007 base::win::ScopedBitmap
mask_bitmap(CreateBitmap(width
, height
, 1, 1, NULL
));
2009 if (mask_bitmap
== NULL
)
2010 return E_OUTOFMEMORY
;
2012 base::win::ScopedCreateDC
bitmap_dc(CreateCompatibleDC(NULL
));
2013 base::win::ScopedSelectObject
select_bitmap(bitmap_dc
.Get(), mask_bitmap
);
2014 RECT local_rect
= { 0, 0, width
, height
};
2015 DrawFrameControl(bitmap_dc
.Get(), &local_rect
, type
, state
);
2017 // We're going to use BitBlt with a b&w mask. This results in using the dest
2018 // dc's text color for the black bits in the mask, and the dest dc's
2019 // background color for the white bits in the mask. DrawFrameControl draws the
2020 // check in black, and the background in white.
2021 int bg_color_key
= COLOR_MENU
;
2022 int text_color_key
= COLOR_MENUTEXT
;
2023 switch (control_state
) {
2025 bg_color_key
= is_selected
? COLOR_HIGHLIGHT
: COLOR_MENU
;
2026 text_color_key
= COLOR_GRAYTEXT
;
2029 bg_color_key
= COLOR_HIGHLIGHT
;
2030 text_color_key
= COLOR_HIGHLIGHTTEXT
;
2039 COLORREF old_bg_color
= SetBkColor(hdc
, GetSysColor(bg_color_key
));
2040 COLORREF old_text_color
= SetTextColor(hdc
, GetSysColor(text_color_key
));
2041 BitBlt(hdc
, rect
.x(), rect
.y(), width
, height
, bitmap_dc
.Get(), 0, 0,
2043 SetBkColor(hdc
, old_bg_color
);
2044 SetTextColor(hdc
, old_text_color
);
2049 HANDLE
NativeThemeWin::GetThemeHandle(ThemeName theme_name
) const {
2050 if (!open_theme_
|| theme_name
< 0 || theme_name
>= LAST
)
2053 if (theme_handles_
[theme_name
])
2054 return theme_handles_
[theme_name
];
2056 // Not found, try to load it.
2058 switch (theme_name
) {
2060 handle
= open_theme_(NULL
, L
"Button");
2063 handle
= open_theme_(NULL
, L
"Listview");
2066 handle
= open_theme_(NULL
, L
"Menu");
2069 handle
= open_theme_(NULL
, L
"Combobox");
2072 handle
= open_theme_(NULL
, L
"Scrollbar");
2075 handle
= open_theme_(NULL
, L
"Status");
2078 handle
= open_theme_(NULL
, L
"Tab");
2081 handle
= open_theme_(NULL
, L
"Edit");
2084 handle
= open_theme_(NULL
, L
"Trackbar");
2087 handle
= open_theme_(NULL
, L
"Window");
2090 handle
= open_theme_(NULL
, L
"Progress");
2093 handle
= open_theme_(NULL
, L
"Spin");
2099 theme_handles_
[theme_name
] = handle
;