|
//------------------------------------------------------------------------------
// <copyright file="ButtonBase.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Windows.Forms.ButtonInternal {
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms.Internal;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
using System.Windows.Forms.VisualStyles;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
internal class ButtonStandardAdapter : ButtonBaseAdapter {
private const int borderWidth = 2;
internal ButtonStandardAdapter(ButtonBase control) : base(control) {}
protected bool IsFilledWithHighlightColor { get; private set; }
private PushButtonState DetermineState(bool up) {
PushButtonState state = PushButtonState.Normal;
if (!up) {
state = PushButtonState.Pressed;
}
else if (Control.MouseIsOver) {
state = PushButtonState.Hot;
}
else if (!Control.Enabled) {
state = PushButtonState.Disabled;
}
else if (Control.Focused || Control.IsDefault) {
state = PushButtonState.Default;
}
return state;
}
internal override void PaintUp(PaintEventArgs e, CheckState state) {
PaintWorker(e, true, state);
}
internal override void PaintDown(PaintEventArgs e, CheckState state) {
PaintWorker(e, false, state);
}
internal override void PaintOver(PaintEventArgs e, CheckState state) {
PaintUp(e, state);
}
private void PaintThemedButtonBackground(PaintEventArgs e, Rectangle bounds, bool up) {
PushButtonState pbState = DetermineState(up);
// First handle transparent case
if (ButtonRenderer.IsBackgroundPartiallyTransparent(pbState)) {
ButtonRenderer.DrawParentBackground(e.Graphics, bounds, Control);
}
// Now draw the actual themed background
if (!DpiHelper.EnableDpiChangedHighDpiImprovements) {
ButtonRenderer.DrawButton(e.Graphics, Control.ClientRectangle, false, pbState);
}
else {
ButtonRenderer.DrawButtonForHandle(e.Graphics, Control.ClientRectangle, false, pbState, this.Control.HandleInternal);
}
// Now overlay the background image or backcolor (the former overrides the latter), leaving a
// margin. We hardcode this margin for now since GetThemeMargins returns 0 all the
// time.
//HACK We need to see what's best here. changing this to HACK because GetThemeMargins simply does not
// work in some cases.
bounds.Inflate(-buttonBorderSize, -buttonBorderSize);
//only paint if the user said not to use the themed backcolor.
if (!Control.UseVisualStyleBackColor) {
bool painted = false;
bool isHighContrastHighlighted = up && IsHighContrastHighlighted();
Color color = isHighContrastHighlighted ? SystemColors.Highlight : Control.BackColor;
// Note: PaintEvent.HDC == 0 if GDI+ has used the HDC -- it wouldn't be safe for us
// to use it without enough bookkeeping to negate any performance gain of using GDI.
if (color.A == 255 && e.HDC != IntPtr.Zero) {
if (DisplayInformation.BitsPerPixel > 8) {
NativeMethods.RECT r = new NativeMethods.RECT(bounds.X, bounds.Y, bounds.Right, bounds.Bottom);
// SysColorBrush does not have to be deleted.
SafeNativeMethods.FillRect(new HandleRef(e, e.HDC), ref r, new HandleRef(this,
isHighContrastHighlighted ? SafeNativeMethods.GetSysColorBrush(ColorTranslator.ToOle(color) & 0xFF) : Control.BackColorBrush));
painted = true;
}
}
if (!painted) {
// don't paint anything from 100% transparent background
//
if (color.A > 0) {
if (color.A == 255) {
color = e.Graphics.GetNearestColor(color);
}
// Color has some transparency or we have no HDC, so we must
// fall back to using GDI+.
//
using (Brush brush = new SolidBrush(color)) {
e.Graphics.FillRectangle(brush, bounds);
IsFilledWithHighlightColor = (color.ToArgb() == SystemColors.Highlight.ToArgb());
}
}
}
}
//This code is mostly taken from the non-themed rendering code path.
if (Control.BackgroundImage != null && !DisplayInformation.HighContrast) {
ControlPaint.DrawBackgroundImage(e.Graphics, Control.BackgroundImage, Color.Transparent, Control.BackgroundImageLayout, Control.ClientRectangle, bounds, Control.DisplayRectangle.Location, Control.RightToLeft);
}
}
void PaintWorker(PaintEventArgs e, bool up, CheckState state) {
up = up && state == CheckState.Unchecked;
IsFilledWithHighlightColor = false;
ColorData colors = PaintRender(e.Graphics).Calculate();
LayoutData layout;
if (Application.RenderWithVisualStyles) {
//don't have the text-pressed-down effect when we use themed painting
//this is for consistency with win32 app.
layout = PaintLayout(e, true).Layout();
}
else {
layout = PaintLayout(e, up).Layout();
}
Graphics g = e.Graphics;
Button thisbutton = this.Control as Button;
if (Application.RenderWithVisualStyles) {
PaintThemedButtonBackground(e, Control.ClientRectangle, up);
}
else {
Brush backbrush = null;
if (state == CheckState.Indeterminate) {
backbrush = CreateDitherBrush(colors.highlight, colors.buttonFace);
}
try {
Rectangle bounds = Control.ClientRectangle;
if (up) {
// We are going to draw a 2 pixel border
bounds.Inflate(-borderWidth, -borderWidth); // VS Whidbey #459900
}
else {
// We are going to draw a 1 pixel border.
bounds.Inflate(-1, -1); // VS Whidbey #503487
}
PaintButtonBackground(e, bounds, backbrush);
}
finally {
if (backbrush != null) {
backbrush.Dispose();
backbrush = null;
}
}
}
PaintImage(e, layout);
//inflate the focus rectangle to be consistent with the behavior of Win32 app
if (Application.RenderWithVisualStyles) {
layout.focus.Inflate(1, 1);
}
if (up & IsHighContrastHighlighted2()) {
var highlightTextColor = SystemColors.HighlightText;
PaintField(e, layout, colors, highlightTextColor, false);
if (Control.Focused && Control.ShowFocusCues) {
// drawing focus rectangle of HighlightText color
ControlPaint.DrawHighContrastFocusRectangle(g, layout.focus, highlightTextColor);
}
}
else if (up & IsHighContrastHighlighted()) {
PaintField(e, layout, colors, SystemColors.HighlightText, true);
}
else {
PaintField(e, layout, colors, colors.windowText, true);
}
if (!Application.RenderWithVisualStyles) {
Rectangle r = Control.ClientRectangle;
if (Control.IsDefault) {
r.Inflate(-1, -1);
}
DrawDefaultBorder(g, r, colors.windowFrame, this.Control.IsDefault);
if (up) {
Draw3DBorder(g, r, colors, up);
}
else {
// contrary to popular belief, not Draw3DBorder(..., false);
//
ControlPaint.DrawBorder(g, r, colors.buttonShadow, ButtonBorderStyle.Solid);
}
}
}
#region Layout
protected override LayoutOptions Layout(PaintEventArgs e) {
LayoutOptions layout = PaintLayout(e, /* up = */ false);
Debug.Assert(layout.GetPreferredSizeCore(LayoutUtils.MaxSize) == PaintLayout(e, /* up = */ true).GetPreferredSizeCore(LayoutUtils.MaxSize),
"The state of up should not effect PreferredSize");
return layout;
}
[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] // removed graphics, may have to put it back
private LayoutOptions PaintLayout(PaintEventArgs e, bool up) {
LayoutOptions layout = CommonLayout();
layout.textOffset = !up;
layout.everettButtonCompat = !Application.RenderWithVisualStyles;
return layout;
}
#endregion
}
}
|