|
//------------------------------------------------------------------------------
// <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.VisualStyles;
internal abstract class RadioButtonBaseAdapter : CheckableControlBaseAdapter {
internal RadioButtonBaseAdapter(ButtonBase control) : base(control) {}
protected new RadioButton Control {
get {
return ((RadioButton)base.Control);
}
}
#region Drawing helpers
protected void DrawCheckFlat(PaintEventArgs e, LayoutData layout, Color checkColor, Color checkBackground, Color checkBorder) {
DrawCheckBackgroundFlat(e, layout.checkBounds, checkBorder, checkBackground);
DrawCheckOnly(e, layout, checkColor, checkBackground, true);
}
protected void DrawCheckBackground3DLite(PaintEventArgs e, Rectangle bounds, Color checkColor, Color checkBackground, ColorData colors, bool disabledColors) {
Graphics g = e.Graphics;
Color field = checkBackground;
if (!Control.Enabled && disabledColors) {
field = SystemColors.Control;
}
using (Brush fieldBrush = new SolidBrush(field)) {
using (Pen dark = new Pen(colors.buttonShadow),
light = new Pen(colors.buttonFace),
lightlight = new Pen(colors.highlight)) {
bounds.Width--;
bounds.Height--;
// fall a little short of SW, NW, NE, SE because corners come out nasty
g.DrawPie(dark, bounds, (float)(135 + 1), (float)(90 - 2));
g.DrawPie(dark, bounds, (float)(225 + 1), (float)(90 - 2));
g.DrawPie(lightlight, bounds, (float)(315 + 1), (float)(90 - 2));
g.DrawPie(lightlight, bounds, (float)(45 + 1), (float)(90 - 2));
bounds.Inflate(-1, -1);
g.FillEllipse(fieldBrush, bounds);
g.DrawEllipse(light, bounds);
}
}
}
protected void DrawCheckBackgroundFlat(PaintEventArgs e, Rectangle bounds, Color borderColor, Color checkBackground) {
Color field = checkBackground;
Color border = borderColor;
if (!Control.Enabled) {
// if we are not in HighContrast mode OR we opted into the legacy behavior
if (!SystemInformation.HighContrast || !AccessibilityImprovements.Level1) {
border = ControlPaint.ContrastControlDark;
}
// otherwise we are in HighContrast mode
field = SystemColors.Control;
}
double scale = GetDpiScaleRatio(e.Graphics);
using( WindowsGraphics wg = WindowsGraphics.FromGraphics(e.Graphics) ) {
using( WindowsPen borderPen = new WindowsPen(wg.DeviceContext, border) ) {
using( WindowsBrush fieldBrush = new WindowsSolidBrush(wg.DeviceContext, field) ) {
// for Dev10 525537, in high DPI mode when we draw ellipse as three rectantles,
// the quality of ellipse is poor. Draw it directly as ellipse
if(scale > 1.1) {
bounds.Width--;
bounds.Height--;
wg.DrawAndFillEllipse(borderPen, fieldBrush, bounds);
bounds.Inflate(-1, -1);
}
else {
DrawAndFillEllipse(wg, borderPen, fieldBrush, bounds);
}
}
}
}
}
// Helper method to overcome the poor GDI ellipse drawing routine
// VSWhidbey #334097
private static void DrawAndFillEllipse(WindowsGraphics wg, WindowsPen borderPen, WindowsBrush fieldBrush, Rectangle bounds)
{
Debug.Assert(wg != null,"Calling DrawAndFillEllipse with null wg");
if (wg == null) {
return;
}
wg.FillRectangle(fieldBrush, new Rectangle(bounds.X + 2, bounds.Y + 2, 8, 8));
wg.FillRectangle(fieldBrush, new Rectangle(bounds.X + 4, bounds.Y + 1, 4, 10));
wg.FillRectangle(fieldBrush, new Rectangle(bounds.X + 1, bounds.Y + 4, 10, 4));
wg.DrawLine(borderPen, new Point(bounds.X + 4, bounds.Y + 0), new Point(bounds.X + 8, bounds.Y + 0));
wg.DrawLine(borderPen, new Point(bounds.X + 4, bounds.Y + 11), new Point(bounds.X + 8, bounds.Y + 11));
wg.DrawLine(borderPen, new Point(bounds.X + 2, bounds.Y + 1), new Point(bounds.X + 4, bounds.Y + 1));
wg.DrawLine(borderPen, new Point(bounds.X + 8, bounds.Y + 1), new Point(bounds.X + 10, bounds.Y + 1));
wg.DrawLine(borderPen, new Point(bounds.X + 2, bounds.Y + 10), new Point(bounds.X + 4, bounds.Y + 10));
wg.DrawLine(borderPen, new Point(bounds.X + 8, bounds.Y + 10), new Point(bounds.X + 10, bounds.Y + 10));
wg.DrawLine(borderPen, new Point(bounds.X + 0, bounds.Y + 4), new Point(bounds.X + 0, bounds.Y + 8));
wg.DrawLine(borderPen, new Point(bounds.X + 11, bounds.Y + 4), new Point(bounds.X + 11, bounds.Y + 8));
wg.DrawLine(borderPen, new Point(bounds.X + 1, bounds.Y + 2), new Point(bounds.X + 1, bounds.Y + 4));
wg.DrawLine(borderPen, new Point(bounds.X + 1, bounds.Y + 8), new Point(bounds.X + 1, bounds.Y + 10));
wg.DrawLine(borderPen, new Point(bounds.X + 10, bounds.Y + 2), new Point(bounds.X + 10, bounds.Y + 4));
wg.DrawLine(borderPen, new Point(bounds.X + 10, bounds.Y + 8), new Point(bounds.X + 10, bounds.Y + 10));
}
private static int GetScaledNumber(int n, double scale)
{
return (int)(n * scale);
}
protected void DrawCheckOnly(PaintEventArgs e, LayoutData layout, Color checkColor, Color checkBackground, bool disabledColors) {
// check
//
if (Control.Checked) {
if (!Control.Enabled && disabledColors) {
checkColor = SystemColors.ControlDark;
}
double scale = GetDpiScaleRatio(e.Graphics);
using( WindowsGraphics wg = WindowsGraphics.FromGraphics(e.Graphics) ) {
using (WindowsBrush brush = new WindowsSolidBrush(wg.DeviceContext, checkColor)) {
// circle drawing doesn't work at this size
int offset = 5;
Rectangle vCross = new Rectangle (layout.checkBounds.X + GetScaledNumber(offset, scale), layout.checkBounds.Y + GetScaledNumber(offset - 1, scale), GetScaledNumber(2, scale), GetScaledNumber(4, scale));
wg.FillRectangle(brush, vCross);
Rectangle hCross = new Rectangle (layout.checkBounds.X + GetScaledNumber(offset - 1, scale), layout.checkBounds.Y + GetScaledNumber(offset, scale), GetScaledNumber(4, scale), GetScaledNumber(2, scale));
wg.FillRectangle(brush, hCross);
}
}
}
}
protected ButtonState GetState() {
ButtonState style = (ButtonState)0;
if (Control.Checked) {
style |= ButtonState.Checked;
}
else {
style |= ButtonState.Normal;
}
if (!Control.Enabled) {
style |= ButtonState.Inactive;
}
if (Control.MouseIsDown) {
style |= ButtonState.Pushed;
}
return style;
}
protected void DrawCheckBox(PaintEventArgs e, LayoutData layout) {
Graphics g = e.Graphics;
Rectangle check = layout.checkBounds;
if (!Application.RenderWithVisualStyles) {
check.X--; // compensate for Windows drawing slightly offset to right
}
ButtonState style = GetState();
if (Application.RenderWithVisualStyles) {
RadioButtonRenderer.DrawRadioButton(g, new Point(check.Left, check.Top), RadioButtonRenderer.ConvertFromButtonState(style, Control.MouseIsOver), Control.HandleInternal);
}
else {
ControlPaint.DrawRadioButton(g, check, style);
}
}
#endregion
protected void AdjustFocusRectangle(LayoutData layout) {
if (AccessibilityImprovements.Level2 && String.IsNullOrEmpty(Control.Text)) {
// When a RadioButton has no text, AutoSize sets the size to zero
// and thus there's no place around which to draw the focus rectangle.
// So, when AutoSize == true we want the focus rectangle to be rendered around the circle area.
// Otherwise, it should encircle all the available space next to the box (like it's done in WPF and ComCtl32).
layout.focus = Control.AutoSize ? layout.checkBounds : layout.field;
}
}
internal override LayoutOptions CommonLayout() {
LayoutOptions layout = base.CommonLayout();
layout.checkAlign = Control.CheckAlign;
return layout;
}
}
}
|