Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / WinForms / Managed / System / WinForms / ButtonInternal / ButtonBaseAdapter.cs / 1 / ButtonBaseAdapter.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms.ButtonInternal { using System; using System.Collections.Specialized; 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; ////// PLEASE READ /// ----------- /// This class is used for more than just Button: /// it's used for things that derive from ButtonBase, /// parts of ToolStripItem, and parts of the DataGridView. /// internal abstract class ButtonBaseAdapter { private ButtonBase control; // SystemInformation.Border3DSize + 2 pixels for focus rect protected static int buttonBorderSize = 4; internal ButtonBaseAdapter(ButtonBase control) { this.control = control; } protected ButtonBase Control { get { return this.control; } } internal void Paint(PaintEventArgs pevent) { if (Control.MouseIsDown) { PaintDown(pevent, CheckState.Unchecked); } else if (Control.MouseIsOver) { PaintOver(pevent, CheckState.Unchecked); } else { PaintUp(pevent, CheckState.Unchecked); } } internal virtual Size GetPreferredSizeCore(Size proposedSize) { // this is a shared cached graphics, therefore it does not require dispose. using (Graphics measurementGraphics = WindowsFormsUtils.CreateMeasurementGraphics()) { using (PaintEventArgs pe = new PaintEventArgs(measurementGraphics, new Rectangle())) { LayoutOptions options = Layout(pe); return options.GetPreferredSizeCore(proposedSize); } } } protected abstract LayoutOptions Layout(PaintEventArgs e); internal abstract void PaintUp(PaintEventArgs e, CheckState state); internal abstract void PaintDown(PaintEventArgs e, CheckState state); internal abstract void PaintOver(PaintEventArgs e, CheckState state); #region Drawing Helpers internal static Color MixedColor(Color color1, Color color2) { byte a1 = color1.A; byte r1 = color1.R; byte g1 = color1.G; byte b1 = color1.B; byte a2 = color2.A; byte r2 = color2.R; byte g2 = color2.G; byte b2 = color2.B; int a3 = (a1 + a2) / 2; int r3 = (r1 + r2) / 2; int g3 = (g1 + g2) / 2; int b3 = (b1 + b2) / 2; return Color.FromArgb(a3, r3, g3, b3); } internal static Brush CreateDitherBrush(Color color1, Color color2) { // Note: Don't dispose the bitmap here. The texture brush will take ownership // of the bitmap. So the bitmap will get disposed by the brush's Dispose(). using (Bitmap b = new Bitmap(2, 2)) { b.SetPixel(0, 0, color1); b.SetPixel(0, 1, color2); b.SetPixel(1, 1, color1); b.SetPixel(1, 0, color2); return new TextureBrush(b); } } ////// Get StringFormat object for rendering text using GDI+ (Graphics). /// internal virtual StringFormat CreateStringFormat() { return ControlPaint.CreateStringFormat( Control, Control.TextAlign, Control.ShowToolTip, Control.UseMnemonic ); } ////// Get TextFormatFlags flags for rendering text using GDI (TextRenderer). /// internal virtual TextFormatFlags CreateTextFormatFlags(){ return ControlPaint.CreateTextFormatFlags( Control, Control.TextAlign, Control.ShowToolTip, Control.UseMnemonic ); } internal static void DrawDitheredFill(Graphics g, Color color1, Color color2, Rectangle bounds) { using (Brush brush = CreateDitherBrush(color1, color2)) { g.FillRectangle(brush, bounds); } } protected void Draw3DBorder(Graphics g, Rectangle bounds, ColorData colors, bool raised) { if (Control.BackColor != SystemColors.Control && SystemInformation.HighContrast) { if (raised) { Draw3DBorderHighContrastRaised(g, ref bounds, colors); } else { ControlPaint.DrawBorder(g, bounds, ControlPaint.Dark(Control.BackColor), ButtonBorderStyle.Solid); } } else { if (raised) { Draw3DBorderRaised(g, ref bounds, colors); } else { Draw3DBorderNormal(g, ref bounds, colors); } } } private void Draw3DBorderHighContrastRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. WindowsPen penTopLeft = null; WindowsPen penBottomRight = null; WindowsPen insetPen = null; WindowsPen bottomRightInsetPen = null; try { // top + left penTopLeft = stockColor ? /*SystemPens.ControlLightLight*/ new WindowsPen(wg.DeviceContext, SystemColors.ControlLightLight) : new WindowsPen(wg.DeviceContext, colors.highlight); wg.DrawLine(penTopLeft, p1, p2); // top (right-left) wg.DrawLine(penTopLeft, p2, p3); // left (up-down) // bottom + right penBottomRight = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlDarkDark) : new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(penBottomRight, p3, p4); // bottom (left-right) wg.DrawLine(penBottomRight, p4, p1); // right (bottom-up ) // Draw inset if (stockColor) { if (SystemInformation.HighContrast) { insetPen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { insetPen = new WindowsPen(wg.DeviceContext, SystemColors.Control); } } else { if (SystemInformation.HighContrast) { insetPen = new WindowsPen(wg.DeviceContext, colors.highlight); } else { insetPen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } } p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); // top + left inset wg.DrawLine(insetPen, p1, p2); // top (right-left) wg.DrawLine(insetPen, p2, p3); // left( up-down) // Bottom + right inset bottomRightInsetPen = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlDark) : new WindowsPen(wg.DeviceContext, colors.buttonShadow); p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(bottomRightInsetPen, p3, p4); // bottom (left-right) wg.DrawLine(bottomRightInsetPen, p4, p1); // right (bottom-up) } finally { if (penTopLeft != null) { penTopLeft.Dispose(); } if (penBottomRight != null) { penBottomRight.Dispose(); } if (insetPen != null) { insetPen.Dispose(); } if (bottomRightInsetPen != null) { bottomRightInsetPen.Dispose(); } } } } private void Draw3DBorderNormal(Graphics g, ref Rectangle bounds, ColorData colors) { using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. // top + left WindowsPen pen = new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right pen = new WindowsPen(wg.DeviceContext, colors.highlight); try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } // Draw inset pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); // top + left inset try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right inset if (colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor()) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } } } private void Draw3DBorderRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. // Draw counter-clock-wise. // top + left WindowsPen pen = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlLightLight) : new WindowsPen(wg.DeviceContext, colors.highlight); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right if (stockColor) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlDarkDark); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } // Draw inset p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); if (stockColor) { if (SystemInformation.HighContrast) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { pen = new WindowsPen(wg.DeviceContext, SystemColors.Control); } } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } // top + left inset try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // Bottom + right inset if (stockColor) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlDark); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonShadow); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } } } ////// Draws a border for the in the 3D style of the popup button. /// protected internal static void Draw3DLiteBorder(Graphics g, Rectangle r, ColorData colors, bool up) { using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(r.Right - 1, r.Top ); // upper inner right. Point p2 = new Point(r.Left , r.Top ); // upper left. Point p3 = new Point(r.Left , r.Bottom - 1); // bottom inner left. Point p4 = new Point(r.Right - 1, r.Bottom - 1); // inner bottom right. // top, left WindowsPen pen = up ? new WindowsPen(wg.DeviceContext, colors.highlight) : new WindowsPen(wg.DeviceContext, colors.buttonShadow); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left (top-down) } finally { pen.Dispose(); } // bottom, right pen = up ? new WindowsPen(wg.DeviceContext, colors.buttonShadow) : new WindowsPen(wg.DeviceContext, colors.highlight); try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom (left-right) wg.DrawLine(pen, p4, p1); // right(bottom-up) } finally { pen.Dispose(); } } } internal static void DrawFlatBorder(Graphics g, Rectangle r, Color c) { ControlPaint.DrawBorder(g, r, c, ButtonBorderStyle.Solid); } ////// /// internal static void DrawFlatBorderWithSize(Graphics g, Rectangle r, Color c, int size) { bool stockBorder = c.IsSystemColor; SolidBrush brush = null; if (size > 1) { brush = new SolidBrush(c); } else { if (stockBorder) { brush = (SolidBrush)SystemBrushes.FromSystemColor(c); } else { brush = new SolidBrush(c); } } try { size = System.Math.Min(size, System.Math.Min(r.Width, r.Height)); // ...truncate pen width to button size, to avoid overflow if border size is huge! //Left Border g.FillRectangle(brush, r.X, r.Y, size, r.Height); //Right Border g.FillRectangle(brush, (r.X + r.Width - size), r.Y, size, r.Height); //Top Border g.FillRectangle(brush, (r.X + size), r.Y, (r.Width - size * 2), size); //Bottom Border g.FillRectangle(brush, (r.X + size), (r.Y + r.Height - size), (r.Width - size * 2), size); } finally { if (!stockBorder && brush != null) { brush.Dispose(); } } } internal static void DrawFlatFocus(Graphics g, Rectangle r, Color c) { using(WindowsGraphics wg = WindowsGraphics.FromGraphics(g)) { using (WindowsPen focus = new WindowsPen(wg.DeviceContext, c)) { wg.DrawRectangle(focus, r); } } } ////// Draws the flat border with specified bordersize. /// This function gets called only for Flatstyle == Flatstyle.Flat. /// ////// void DrawFocus(Graphics g, Rectangle r) { if (Control.Focused && Control.ShowFocusCues) { ControlPaint.DrawFocusRectangle(g, r, Control.ForeColor, Control.BackColor); } } ////// Draws the focus rectangle if the control has focus. /// /// ////// Draws the button's image. /// void DrawImage(Graphics graphics, LayoutData layout) { if (Control.Image != null) { //setup new clip region & draw DrawImageCore(graphics, Control.Image, layout.imageBounds, layout.imageStart, layout); } } // here for DropDownButton internal virtual void DrawImageCore(Graphics graphics, Image image, Rectangle imageBounds, Point imageStart, LayoutData layout) { Region oldClip = graphics.Clip; if (!layout.options.everettButtonCompat) { // FOR EVERETT COMPATIBILITY - DO NOT CHANGE Rectangle bounds = new Rectangle(buttonBorderSize, buttonBorderSize, this.Control.Width - (2 * buttonBorderSize), this.Control.Height - (2 * buttonBorderSize)); Region newClip = oldClip.Clone(); newClip.Intersect(bounds); // If we don't do this, DrawImageUnscaled will happily draw the entire image, even though imageBounds // is smaller than the image size. newClip.Intersect(imageBounds); graphics.Clip = newClip; } else { // FOR EVERETT COMPATIBILITY - DO NOT CHANGE imageBounds.Width += 1; imageBounds.Height +=1; imageBounds.X = imageStart.X + 1; imageBounds.Y = imageStart.Y + 1; } try { if (!Control.Enabled) // need to specify width and height ControlPaint.DrawImageDisabled(graphics, image, imageBounds, Control.BackColor, true /* unscaled image*/); else { graphics.DrawImage(image, imageBounds.X, imageBounds.Y, image.Width, image.Height); } } finally { if (!layout.options.everettButtonCompat) {// FOR EVERETT COMPATIBILITY - DO NOT CHANGE graphics.Clip = oldClip; } } } internal static void DrawDefaultBorder(Graphics g, Rectangle r, Color c, bool isDefault) { if (isDefault) { r.Inflate(1, 1); Pen pen; if (c.IsSystemColor) { pen = SystemPens.FromSystemColor(c); } else { pen = new Pen(c); } g.DrawRectangle(pen, r.X, r.Y, r.Width - 1, r.Height - 1); if (!c.IsSystemColor) { pen.Dispose(); } } } ////// Draws the button's text. /// void DrawText(Graphics g, LayoutData layout, Color c, ColorData colors) { Rectangle r = layout.textBounds; bool disabledText3D = layout.options.shadowedText; if (Control.UseCompatibleTextRendering) { // Draw text using GDI+ using (StringFormat stringFormat = CreateStringFormat()) { // DrawString doesn't seem to draw where it says it does if ((Control.TextAlign & LayoutUtils.AnyCenter) == 0) { r.X -= 1; } r.Width += 1; if (disabledText3D && !Control.Enabled) { r.Offset(1, 1); using (SolidBrush brush = new SolidBrush(colors.highlight)) { g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); r.Offset(-1, -1); brush.Color = colors.buttonShadow; g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); } } else { Brush brush; if (c.IsSystemColor) { brush = SystemBrushes.FromSystemColor(c); } else { brush = new SolidBrush(c); } g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); if (!c.IsSystemColor) { brush.Dispose(); } } } } else { // Draw text using GDI (Whidbey feature). TextFormatFlags formatFlags = CreateTextFormatFlags(); if (disabledText3D && !Control.Enabled) { if (Application.RenderWithVisualStyles) { //don't draw chiseled text if themed as win32 app does. TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.buttonShadow, formatFlags); } else { r.Offset(1, 1); TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.highlight, formatFlags); r.Offset(-1, -1); TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.buttonShadow, formatFlags); } } else { TextRenderer.DrawText(g, Control.Text, Control.Font, r, c, formatFlags); } } } #endregion Drawing Helpers #region Draw Content Helpers // the DataGridViewButtonCell uses this method internal static void PaintButtonBackground(WindowsGraphics wg, Rectangle bounds, WindowsBrush background) { wg.FillRectangle(background, bounds); } internal void PaintButtonBackground(PaintEventArgs e, Rectangle bounds, Brush background) { if (background == null) { Control.PaintBackground(e, bounds); } else { e.Graphics.FillRectangle(background, bounds); } } internal void PaintField(PaintEventArgs e, LayoutData layout, ColorData colors, Color foreColor, bool drawFocus) { Graphics g = e.Graphics; Rectangle maxFocus = layout.focus; DrawText(g, layout, foreColor, colors); if (drawFocus) { DrawFocus(g, maxFocus); } } internal void PaintImage(PaintEventArgs e, LayoutData layout) { Graphics g = e.Graphics; DrawImage(g, layout); } #endregion #region Color internal class ColorOptions { internal Color backColor; internal Color foreColor; internal bool enabled; internal bool disabledTextDim; internal bool highContrast; internal Graphics graphics; internal ColorOptions(Graphics graphics, Color foreColor, Color backColor) { this.graphics = graphics; this.backColor = backColor; this.foreColor = foreColor; highContrast = SystemInformation.HighContrast; } internal static int Adjust255(float percentage, int value) { int v = (int)(percentage * value); if (v > 255) { return 255; } return v; } internal ColorData Calculate() { ColorData colors = new ColorData(this); colors.buttonFace = backColor; if (backColor == SystemColors.Control) { colors.buttonShadow = SystemColors.ControlDark; colors.buttonShadowDark = SystemColors.ControlDarkDark; colors.highlight = SystemColors.ControlLightLight; } else { if (!highContrast) { colors.buttonShadow = ControlPaint.Dark(backColor); colors.buttonShadowDark = ControlPaint.DarkDark(backColor); colors.highlight = ControlPaint.LightLight(backColor); } else { colors.buttonShadow = ControlPaint.Dark(backColor); colors.buttonShadowDark = ControlPaint.LightLight(backColor); colors.highlight = ControlPaint.LightLight(backColor); } } const float lowlight = .1f; float adjust = 1 - lowlight; if (colors.buttonFace.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } colors.lowButtonFace = Color.FromArgb(Adjust255(adjust, colors.buttonFace.R), Adjust255(adjust, colors.buttonFace.G), Adjust255(adjust, colors.buttonFace.B)); adjust = 1 - lowlight; if (colors.highlight.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } colors.lowHighlight = Color.FromArgb(Adjust255(adjust, colors.highlight.R), Adjust255(adjust, colors.highlight.G), Adjust255(adjust, colors.highlight.B)); if (highContrast && backColor != SystemColors.Control) { colors.highlight = colors.lowHighlight; } colors.windowFrame = foreColor; /* debug * / colors.buttonFace = Color.Yellow; colors.buttonShadow = Color.Blue; colors.highlight = Color.Brown; colors.lowButtonFace = Color.Beige; colors.lowHighlight = Color.Cyan; colors.windowFrame = Color.Red; colors.windowText = Color.Green; / * debug */ if (colors.buttonFace.GetBrightness() < .5) { colors.constrastButtonShadow = colors.lowHighlight; } else { colors.constrastButtonShadow = colors.buttonShadow; } if (!enabled && disabledTextDim) { colors.windowText = colors.buttonShadow; } else { colors.windowText = colors.windowFrame; } IntPtr hdc = this.graphics.GetHdc(); try { using (WindowsGraphics wg = WindowsGraphics.FromHdc(hdc)) { colors.buttonFace = wg.GetNearestColor(colors.buttonFace); colors.buttonShadow = wg.GetNearestColor(colors.buttonShadow); colors.buttonShadowDark = wg.GetNearestColor(colors.buttonShadowDark); colors.constrastButtonShadow = wg.GetNearestColor(colors.constrastButtonShadow); colors.windowText = wg.GetNearestColor(colors.windowText); colors.highlight = wg.GetNearestColor(colors.highlight); colors.lowHighlight = wg.GetNearestColor(colors.lowHighlight); colors.lowButtonFace = wg.GetNearestColor(colors.lowButtonFace); colors.windowFrame = wg.GetNearestColor(colors.windowFrame); } } finally { this.graphics.ReleaseHdc(); } return colors; } } internal class ColorData { internal Color buttonFace; internal Color buttonShadow; internal Color buttonShadowDark; internal Color constrastButtonShadow; internal Color windowText; internal Color highlight; internal Color lowHighlight; internal Color lowButtonFace; internal Color windowFrame; internal ColorOptions options; internal ColorData(ColorOptions options) { this.options = options; } } #endregion #region Layout internal class LayoutOptions { internal Rectangle client; internal bool growBorderBy1PxWhenDefault; internal bool isDefault; internal int borderSize; internal int paddingSize; internal bool maxFocus; internal bool focusOddEvenFixup; internal Font font; internal string text; internal Size imageSize; internal int checkSize; internal int checkPaddingSize; internal ContentAlignment checkAlign; internal ContentAlignment imageAlign; internal ContentAlignment textAlign; internal TextImageRelation textImageRelation; internal bool hintTextUp; internal bool textOffset; internal bool shadowedText; internal bool layoutRTL; internal bool verticalText = false; internal bool useCompatibleTextRendering = false; internal bool everettButtonCompat = true; internal TextFormatFlags gdiTextFormatFlags = TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl; internal StringFormatFlags gdipFormatFlags; internal StringTrimming gdipTrimming; internal HotkeyPrefix gdipHotkeyPrefix; internal StringAlignment gdipAlignment; // horizontal alignment. internal StringAlignment gdipLineAlignment; // vertical alignment. private bool disableWordWrapping; ////// We don't cache the StringFormat itself because we don't have a deterministic way of disposing it, instead /// we cache the flags that make it up and create it on demand so it can be disposed by calling code. /// public StringFormat StringFormat { get { StringFormat format = new StringFormat(); format.FormatFlags = this.gdipFormatFlags; format.Trimming = this.gdipTrimming; format.HotkeyPrefix = this.gdipHotkeyPrefix; format.Alignment = this.gdipAlignment; format.LineAlignment = this.gdipLineAlignment; if (disableWordWrapping) { format.FormatFlags |= StringFormatFlags.NoWrap; } return format; } set { this.gdipFormatFlags = value.FormatFlags; this.gdipTrimming = value.Trimming; this.gdipHotkeyPrefix = value.HotkeyPrefix; this.gdipAlignment = value.Alignment; this.gdipLineAlignment = value.LineAlignment; } } ////// public TextFormatFlags TextFormatFlags { get { if (disableWordWrapping) { return gdiTextFormatFlags & ~TextFormatFlags.WordBreak; } return gdiTextFormatFlags; } //set { // this.gdiTextFormatFlags = value; //} } // textImageInset compensates for two factors: 3d text when the button is disabled, // and moving text on 3d-look buttons. These factors make the text require a couple // more pixels of space. We inset image by the same amount so they line up. internal int textImageInset = 2; internal Padding padding; #region PreferredSize private static readonly int combineCheck = BitVector32.CreateMask(); private static readonly int combineImageText = BitVector32.CreateMask(combineCheck); private enum Composition { NoneCombined = 0x00, CheckCombined = 0x01, TextImageCombined = 0x02, AllCombined = 0x03 } // Uses checkAlign, imageAlign, and textAlign to figure out how to compose // checkSize, imageSize, and textSize into the preferredSize. private Size Compose(Size checkSize, Size imageSize, Size textSize) { Composition hComposition = GetHorizontalComposition(); Composition vComposition = GetVerticalComposition(); return new Size( xCompose(hComposition, checkSize.Width, imageSize.Width, textSize.Width), xCompose(vComposition, checkSize.Height, imageSize.Height, textSize.Height) ); } private int xCompose(Composition composition, int checkSize, int imageSize, int textSize) { switch(composition) { case Composition.NoneCombined: return checkSize + imageSize + textSize; case Composition.CheckCombined: return Math.Max(checkSize, imageSize + textSize); case Composition.TextImageCombined: return Math.Max(imageSize, textSize) + checkSize; case Composition.AllCombined: return Math.Max(Math.Max(checkSize, imageSize), textSize); default: Debug.Fail(SR.GetString(SR.InvalidArgument, "composition", composition.ToString())); return -7107; } } // Uses checkAlign, imageAlign, and textAlign to figure out how to decompose // proposedSize into just the space left over for text. private Size Decompose(Size checkSize, Size imageSize, Size proposedSize) { Composition hComposition = GetHorizontalComposition(); Composition vComposition = GetVerticalComposition(); return new Size( xDecompose(hComposition, checkSize.Width, imageSize.Width, proposedSize.Width), xDecompose(vComposition, checkSize.Height, imageSize.Height, proposedSize.Height) ); } private int xDecompose(Composition composition, int checkSize, int imageSize, int proposedSize) { switch(composition) { case Composition.NoneCombined: return proposedSize - (checkSize + imageSize); case Composition.CheckCombined: return proposedSize - imageSize; case Composition.TextImageCombined: return proposedSize - checkSize; case Composition.AllCombined: return proposedSize; default: Debug.Fail(SR.GetString(SR.InvalidArgument, "composition", composition.ToString())); return -7109; } } private Composition GetHorizontalComposition() { BitVector32 action = new BitVector32(); // Checks reserve space horizontally if possible, so only AnyLeft/AnyRight prevents combination. action[combineCheck] = checkAlign == ContentAlignment.MiddleCenter || !LayoutUtils.IsHorizontalAlignment(checkAlign); action[combineImageText] = !LayoutUtils.IsHorizontalRelation(textImageRelation); return (Composition) action.Data; } internal Size GetPreferredSizeCore(Size proposedSize) { // Get space required for border and padding // int linearBorderAndPadding = borderSize*2 + paddingSize*2; if(growBorderBy1PxWhenDefault) { linearBorderAndPadding += 2; } Size bordersAndPadding = new Size(linearBorderAndPadding, linearBorderAndPadding); proposedSize -= bordersAndPadding; // Get space required for Check // int checkSizeLinear = FullCheckSize; Size checkSize = checkSizeLinear > 0 ? new Size(checkSizeLinear + 1, checkSizeLinear) : Size.Empty; // Get space required for Image - textImageInset compensated for by expanding image. // Size textImageInsetSize = new Size(textImageInset * 2, textImageInset * 2); Size requiredImageSize = (imageSize != Size.Empty) ? imageSize + textImageInsetSize : Size.Empty; // Pack Text into remaning space // proposedSize -= textImageInsetSize; proposedSize = Decompose(checkSize, requiredImageSize, proposedSize); Size textSize = Size.Empty; if (!string.IsNullOrEmpty(text)) { // When Button.AutoSizeMode is set to GrowOnly TableLayoutPanel expects buttons not to automatically wrap on word break. If // there's enough room for the text to word-wrap then it will happen but the layout would not be adjusted to allow text wrapping. // If someone has a carriage return in the text we'll honor that for preferred size, but we wont wrap based on constraints. // See VSW#542448,537840,515227. try { this.disableWordWrapping = true; textSize = GetTextSize(proposedSize) + textImageInsetSize; } finally { this.disableWordWrapping = false; } } // Combine pieces to get final preferred size // Size requiredSize = Compose(checkSize, imageSize, textSize); requiredSize += bordersAndPadding; return requiredSize; } private Composition GetVerticalComposition() { BitVector32 action = new BitVector32(); // Checks reserve space horizontally if possible, so only Top/Bottom prevents combination. action[combineCheck] = checkAlign == ContentAlignment.MiddleCenter || !LayoutUtils.IsVerticalAlignment(checkAlign); action[combineImageText] = !LayoutUtils.IsVerticalRelation(textImageRelation); return (Composition) action.Data; } #endregion PreferredSize private int FullBorderSize { get { int result = borderSize; if (OnePixExtraBorder) { borderSize++; } return borderSize; } } private bool OnePixExtraBorder { get { return growBorderBy1PxWhenDefault && isDefault; } } internal LayoutData Layout() { LayoutData layout = new LayoutData(this); layout.client = this.client; // subtract border size from layout area int fullBorderSize = FullBorderSize; layout.face = Rectangle.Inflate(layout.client, -fullBorderSize, -fullBorderSize); // checkBounds, checkArea, field // CalcCheckmarkRectangle(layout); // imageBounds, imageLocation, textBounds LayoutTextAndImage(layout); // focus // if (maxFocus) { layout.focus = layout.field; layout.focus.Inflate(-1, -1); // Adjust for padding. VSWhidbey #387208 layout.focus = LayoutUtils.InflateRect(layout.focus, this.padding); } else { Rectangle textAdjusted = new Rectangle(layout.textBounds.X - 1, layout.textBounds.Y - 1, layout.textBounds.Width + 2, layout.textBounds.Height + 3); if (imageSize != Size.Empty) { layout.focus = Rectangle.Union(textAdjusted, layout.imageBounds); } else { layout.focus = textAdjusted; } } if (focusOddEvenFixup) { if (layout.focus.Height % 2 == 0) { layout.focus.Y++; layout.focus.Height--; } if (layout.focus.Width % 2 == 0) { layout.focus.X++; layout.focus.Width--; } } return layout; } TextImageRelation RtlTranslateRelation(TextImageRelation relation) { // If RTL, we swap ImageBeforeText and TextBeforeImage if (layoutRTL) { switch(relation) { case TextImageRelation.ImageBeforeText: return TextImageRelation.TextBeforeImage; case TextImageRelation.TextBeforeImage: return TextImageRelation.ImageBeforeText; } } return relation; } internal ContentAlignment RtlTranslateContent(ContentAlignment align) { if (layoutRTL) { ContentAlignment[][] mapping = new ContentAlignment[3][]; mapping[0] = new ContentAlignment[2] { ContentAlignment.TopLeft, ContentAlignment.TopRight }; mapping[1] = new ContentAlignment[2] { ContentAlignment.MiddleLeft, ContentAlignment.MiddleRight }; mapping[2] = new ContentAlignment[2] { ContentAlignment.BottomLeft, ContentAlignment.BottomRight }; for(int i=0; i < 3; ++i) { if (mapping[i][0] == align) { return mapping[i][1]; } else if (mapping[i][1] == align) { return mapping[i][0]; } } } return align; } private int FullCheckSize { get { return checkSize + checkPaddingSize; } } void CalcCheckmarkRectangle(LayoutData layout) { int checkSizeFull = FullCheckSize; layout.checkBounds = new Rectangle(client.X, client.Y, checkSizeFull, checkSizeFull); // Translate checkAlign for Rtl applications ContentAlignment align = RtlTranslateContent(checkAlign); Rectangle field = Rectangle.Inflate(layout.face, -paddingSize, -paddingSize); layout.field = field; if (checkSizeFull > 0) { if ((align & LayoutUtils.AnyRight) != 0) { layout.checkBounds.X = (field.X+field.Width) - layout.checkBounds.Width; } else if ((align & LayoutUtils.AnyCenter) != 0) { layout.checkBounds.X = field.X + (field.Width - layout.checkBounds.Width)/2; } if ((align & LayoutUtils.AnyBottom) != 0) { layout.checkBounds.Y = (field.Y+field.Height)-layout.checkBounds.Height; } else if ((align & LayoutUtils.AnyTop) != 0) { layout.checkBounds.Y = field.Y + 2; // + 2: this needs to be aligned to the text (bug 87483) } else { layout.checkBounds.Y = field.Y + (field.Height - layout.checkBounds.Height)/2; } switch (align) { case ContentAlignment.TopLeft: case ContentAlignment.MiddleLeft: case ContentAlignment.BottomLeft: layout.checkArea.X = field.X; layout.checkArea.Width = checkSizeFull + 1; layout.checkArea.Y = field.Y; layout.checkArea.Height = field.Height; layout.field.X += checkSizeFull + 1; layout.field.Width -= checkSizeFull + 1; break; case ContentAlignment.TopRight: case ContentAlignment.MiddleRight: case ContentAlignment.BottomRight: layout.checkArea.X = field.X + field.Width - checkSizeFull; layout.checkArea.Width = checkSizeFull + 1; layout.checkArea.Y = field.Y; layout.checkArea.Height = field.Height; layout.field.Width -= checkSizeFull + 1; break; case ContentAlignment.TopCenter: layout.checkArea.X = field.X; layout.checkArea.Width = field.Width; layout.checkArea.Y = field.Y; layout.checkArea.Height = checkSizeFull; layout.field.Y += checkSizeFull; layout.field.Height -= checkSizeFull; break; case ContentAlignment.BottomCenter: layout.checkArea.X = field.X; layout.checkArea.Width = field.Width; layout.checkArea.Y = field.Y + field.Height - checkSizeFull; layout.checkArea.Height = checkSizeFull; layout.field.Height -= checkSizeFull; break; case ContentAlignment.MiddleCenter: layout.checkArea = layout.checkBounds; break; } layout.checkBounds.Width -= checkPaddingSize; layout.checkBounds.Height -= checkPaddingSize; } } // Maps an image align to the set of TextImageRelations that represent the same edge. // For example, imageAlign = TopLeft maps to TextImageRelations ImageAboveText (top) // and ImageBeforeText (left). private static readonly TextImageRelation[] _imageAlignToRelation = new TextImageRelation[] { /* TopLeft = */ TextImageRelation.ImageAboveText | TextImageRelation.ImageBeforeText, /* TopCenter = */ TextImageRelation.ImageAboveText, /* TopRight = */ TextImageRelation.ImageAboveText | TextImageRelation.TextBeforeImage, /* Invalid */ 0, /* MiddleLeft = */ TextImageRelation.ImageBeforeText, /* MiddleCenter = */ 0, /* MiddleRight = */ TextImageRelation.TextBeforeImage, /* Invalid */ 0, /* BottomLeft = */ TextImageRelation.TextAboveImage | TextImageRelation.ImageBeforeText, /* BottomCenter = */ TextImageRelation.TextAboveImage, /* BottomRight = */ TextImageRelation.TextAboveImage | TextImageRelation.TextBeforeImage }; private static TextImageRelation ImageAlignToRelation(ContentAlignment alignment) { return _imageAlignToRelation[LayoutUtils.ContentAlignmentToIndex(alignment)]; } private static TextImageRelation TextAlignToRelation(ContentAlignment alignment) { return LayoutUtils.GetOppositeTextImageRelation(ImageAlignToRelation(alignment)); } internal void LayoutTextAndImage(LayoutData layout) { // Translate for Rtl applications. This intentially shadows the member variables. ContentAlignment imageAlign = RtlTranslateContent(this.imageAlign); ContentAlignment textAlign = RtlTranslateContent(this.textAlign); TextImageRelation textImageRelation = RtlTranslateRelation(this.textImageRelation); // Figure out the maximum bounds for text & image Rectangle maxBounds = Rectangle.Inflate(layout.field, -textImageInset, -textImageInset); if(OnePixExtraBorder) { maxBounds.Inflate(1, 1); } // Compute the final image and text bounds. if(imageSize == Size.Empty || text == null || text.Length == 0 || textImageRelation == TextImageRelation.Overlay) { // Do not worry about text/image overlaying Size textSize = GetTextSize(maxBounds.Size); // FOR EVERETT COMPATIBILITY - DO NOT CHANGE Size size = imageSize; if (layout.options.everettButtonCompat && imageSize != Size.Empty) { size = new Size(size.Width + 1, size.Height + 1); } layout.imageBounds = LayoutUtils.Align(size, maxBounds, imageAlign); layout.textBounds = LayoutUtils.Align(textSize, maxBounds, textAlign); } else { // Rearrage text/image to prevent overlay. Pack text into maxBounds - space reserved for image Size maxTextSize = LayoutUtils.SubAlignedRegion(maxBounds.Size, imageSize, textImageRelation); Size textSize = GetTextSize(maxTextSize); Rectangle maxCombinedBounds = maxBounds; // Combine text & image into one rectangle that we center within maxBounds. Size combinedSize = LayoutUtils.AddAlignedRegion(textSize, imageSize, textImageRelation); maxCombinedBounds.Size = LayoutUtils.UnionSizes(maxCombinedBounds.Size, combinedSize); Rectangle combinedBounds = LayoutUtils.Align(combinedSize, maxCombinedBounds, ContentAlignment.MiddleCenter); // imageEdge indicates whether the combination of imageAlign and textImageRelation place // the image along the edge of the control. If so, we can increase the space for text. bool imageEdge = (AnchorStyles)(ImageAlignToRelation(imageAlign) & textImageRelation) != AnchorStyles.None; // textEdge indicates whether the combination of textAlign and textImageRelation place // the text along the edge of the control. If so, we can increase the space for image. bool textEdge = (AnchorStyles)(TextAlignToRelation(textAlign) & textImageRelation) != AnchorStyles.None; if(imageEdge) { // If imageEdge, just split imageSize off of maxCombinedBounds. LayoutUtils.SplitRegion(maxCombinedBounds, imageSize, (AnchorStyles) textImageRelation, out layout.imageBounds, out layout.textBounds); } else if(textEdge) { // Else if textEdge, just split textSize off of maxCombinedBounds. LayoutUtils.SplitRegion(maxCombinedBounds, textSize, (AnchorStyles) LayoutUtils.GetOppositeTextImageRelation(textImageRelation), out layout.textBounds, out layout.imageBounds); } else { // Expand the adjacent regions to maxCombinedBounds (centered) and split the rectangle into imageBounds and textBounds. LayoutUtils.SplitRegion(combinedBounds, imageSize, (AnchorStyles) textImageRelation, out layout.imageBounds, out layout.textBounds); LayoutUtils.ExpandRegionsToFillBounds(maxCombinedBounds, (AnchorStyles) textImageRelation, ref layout.imageBounds, ref layout.textBounds); } // align text/image within their regions. layout.imageBounds = LayoutUtils.Align(imageSize, layout.imageBounds, imageAlign); layout.textBounds = LayoutUtils.Align(textSize, layout.textBounds, textAlign); } //Don't call "layout.imageBounds = Rectangle.Intersect(layout.imageBounds, maxBounds);" // because that is a breaking change that causes images to be scaled to the dimensions of the control. //adjust textBounds so that the text is still visible even if the image is larger than the button's size //fixes Whidbey 234985 //why do we intersect with layout.field for textBounds while we intersect with maxBounds for imageBounds? //this is because there are some legacy code which squeezes the button so small that text will get clipped //if we intersect with maxBounds. Have to do this for backward compatibility. //See Whidbey 341480 if (textImageRelation == TextImageRelation.TextBeforeImage || textImageRelation == TextImageRelation.ImageBeforeText) { //adjust the vertical position of textBounds so that the text doesn't fall off the boundary of the button int textBottom = Math.Min(layout.textBounds.Bottom, layout.field.Bottom); layout.textBounds.Y = Math.Max(Math.Min(layout.textBounds.Y, layout.field.Y + (layout.field.Height - layout.textBounds.Height)/2), layout.field.Y); layout.textBounds.Height = textBottom - layout.textBounds.Y; } if (textImageRelation == TextImageRelation.TextAboveImage || textImageRelation == TextImageRelation.ImageAboveText) { //adjust the horizontal position of textBounds so that the text doesn't fall off the boundary of the button int textRight = Math.Min(layout.textBounds.Right, layout.field.Right); layout.textBounds.X = Math.Max(Math.Min(layout.textBounds.X, layout.field.X + (layout.field.Width - layout.textBounds.Width)/2), layout.field.X); layout.textBounds.Width = textRight - layout.textBounds.X; } if (textImageRelation == TextImageRelation.ImageBeforeText && layout.imageBounds.Size.Width != 0) { //squeezes imageBounds.Width so that text is visible layout.imageBounds.Width = Math.Max(0, Math.Min(maxBounds.Width - layout.textBounds.Width, layout.imageBounds.Width)); layout.textBounds.X = layout.imageBounds.X + layout.imageBounds.Width; } if (textImageRelation == TextImageRelation.ImageAboveText && layout.imageBounds.Size.Height != 0) { //squeezes imageBounds.Height so that the text is visible layout.imageBounds.Height = Math.Max(0, Math.Min(maxBounds.Height - layout.textBounds.Height, layout.imageBounds.Height)); layout.textBounds.Y = layout.imageBounds.Y + layout.imageBounds.Height; } //make sure that textBound is contained in layout.field layout.textBounds = Rectangle.Intersect(layout.textBounds, layout.field); if (hintTextUp) { layout.textBounds.Y--; } if (textOffset) { layout.textBounds.Offset(1, 1); } // FOR EVERETT COMPATIBILITY - DO NOT CHANGE if (layout.options.everettButtonCompat) { layout.imageStart = layout.imageBounds.Location; layout.imageBounds = Rectangle.Intersect(layout.imageBounds, layout.field); } else if (!Application.RenderWithVisualStyles) { // Not sure why this is here, but we can't remove it, since it might break // ToolStrips on non-themed machines layout.textBounds.X++; } // clip // int bottom; // If we are using GDI to measure text, then we can get into a situation, where // the proposed height is ignore. In this case, we want to clip it against // maxbounds. VSWhidbey #480670 if (!useCompatibleTextRendering) { bottom = Math.Min(layout.textBounds.Bottom, maxBounds.Bottom); layout.textBounds.Y = Math.Max(layout.textBounds.Y, maxBounds.Y); } else { // If we are using GDI+ (like Everett), then use the old Everett code // This ensures that we have pixel-level rendering compatibility bottom = Math.Min(layout.textBounds.Bottom, layout.field.Bottom); layout.textBounds.Y = Math.Max(layout.textBounds.Y, layout.field.Y); } layout.textBounds.Height = bottom - layout.textBounds.Y; //This causes a breaking change because images get shrunk to the new clipped size instead of clipped. //********** bottom = Math.Min(layout.imageBounds.Bottom, maxBounds.Bottom); //********** layout.imageBounds.Y = Math.Max(layout.imageBounds.Y, maxBounds.Y); //********** layout.imageBounds.Height = bottom - layout.imageBounds.Y; } protected virtual Size GetTextSize(Size proposedSize) { //set the Prefix field of TextFormatFlags proposedSize = LayoutUtils.FlipSizeIf(verticalText, proposedSize); Size textSize = Size.Empty; if (useCompatibleTextRendering) { // GDI+ text rendering. using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics()) { using ( StringFormat gdipStringFormat = this.StringFormat ) { textSize = Size.Ceiling(g.MeasureString(text, font, new SizeF(proposedSize.Width, proposedSize.Height), gdipStringFormat)); } } } else if (!string.IsNullOrEmpty(text)) { // GDI text rendering (Whidbey feature). textSize = TextRenderer.MeasureText(text, font, proposedSize, this.TextFormatFlags); } //else skip calling MeasureText, it should return 0,0 return LayoutUtils.FlipSizeIf(verticalText, textSize); } #if DEBUG public override string ToString() { return "{ client = " + client + "\n" + "OnePixExtraBorder = " + OnePixExtraBorder + "\n" + "borderSize = " + borderSize + "\n" + "paddingSize = " + paddingSize + "\n" + "maxFocus = " + maxFocus + "\n" + "font = " + font + "\n" + "text = " + text + "\n" + "imageSize = " + imageSize + "\n" + "checkSize = " + checkSize + "\n" + "checkPaddingSize = " + checkPaddingSize + "\n" + "checkAlign = " + checkAlign + "\n" + "imageAlign = " + imageAlign + "\n" + "textAlign = " + textAlign + "\n" + "textOffset = " + textOffset + "\n" + "shadowedText = " + shadowedText + "\n" + "textImageRelation = " + textImageRelation + "\n" + "layoutRTL = " + layoutRTL + " }"; } #endif } internal class LayoutData { internal Rectangle client; internal Rectangle face; internal Rectangle checkArea; internal Rectangle checkBounds; internal Rectangle textBounds; internal Rectangle field; internal Rectangle focus; internal Rectangle imageBounds; internal Point imageStart; // FOR EVERETT COMPATIBILITY - DO NOT CHANGE internal LayoutOptions options; internal LayoutData(LayoutOptions options) { Debug.Assert(options != null, "must have options"); this.options = options; } } #endregion #region Layout // used by the DataGridViewButtonCell internal static LayoutOptions CommonLayout(Rectangle clientRectangle, Padding padding, bool isDefault, Font font, string text, bool enabled, ContentAlignment textAlign, RightToLeft rtl) { LayoutOptions layout = new LayoutOptions(); layout.client = LayoutUtils.DeflateRect(clientRectangle, padding); layout.padding = padding; layout.growBorderBy1PxWhenDefault = true; layout.isDefault = isDefault; layout.borderSize = 2; layout.paddingSize = 0; layout.maxFocus = true; layout.focusOddEvenFixup = false; layout.font = font; layout.text = text; layout.imageSize = Size.Empty; layout.checkSize = 0; layout.checkPaddingSize = 0; layout.checkAlign = ContentAlignment.TopLeft; layout.imageAlign = ContentAlignment.MiddleCenter; layout.textAlign = textAlign; layout.hintTextUp = false; layout.shadowedText = !enabled; layout.layoutRTL = RightToLeft.Yes == rtl; layout.textImageRelation = TextImageRelation.Overlay; layout.useCompatibleTextRendering = false; return layout; } internal virtual LayoutOptions CommonLayout() { LayoutOptions layout = new LayoutOptions(); layout.client = LayoutUtils.DeflateRect(Control.ClientRectangle, Control.Padding); layout.padding = Control.Padding; layout.growBorderBy1PxWhenDefault = true; layout.isDefault = Control.IsDefault; layout.borderSize = 2; layout.paddingSize = 0; layout.maxFocus = true; layout.focusOddEvenFixup = false; layout.font = Control.Font; layout.text = Control.Text; layout.imageSize = (Control.Image == null) ? Size.Empty : Control.Image.Size; layout.checkSize = 0; layout.checkPaddingSize = 0; layout.checkAlign = ContentAlignment.TopLeft; layout.imageAlign = Control.ImageAlign; layout.textAlign = Control.TextAlign; layout.hintTextUp = false; layout.shadowedText = !Control.Enabled; layout.layoutRTL = RightToLeft.Yes == Control.RightToLeft; layout.textImageRelation = Control.TextImageRelation; layout.useCompatibleTextRendering = Control.UseCompatibleTextRendering; if( Control.FlatStyle != FlatStyle.System ) { if( layout.useCompatibleTextRendering ) { using( StringFormat format = Control.CreateStringFormat() ) { layout.StringFormat = format; } } else { layout.gdiTextFormatFlags = Control.CreateTextFormatFlags(); } } return layout; } // used by the DataGridViewButtonCell static ColorOptions CommonRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = new ColorOptions(g, foreColor, backColor); colors.enabled = enabled; return colors; } ColorOptions CommonRender(Graphics g) { ColorOptions colors = new ColorOptions(g, Control.ForeColor, Control.BackColor); colors.enabled = Control.Enabled; return colors; } protected ColorOptions PaintRender(Graphics g) { ColorOptions colors = CommonRender(g); return colors; } // used by the DataGridViewButtonCell internal static ColorOptions PaintFlatRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = CommonRender(g, foreColor, backColor, enabled); colors.disabledTextDim = true; return colors; } protected ColorOptions PaintFlatRender(Graphics g) { ColorOptions colors = CommonRender(g); colors.disabledTextDim = true; return colors; } // used by the DataGridViewButtonCell internal static ColorOptions PaintPopupRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = CommonRender(g, foreColor, backColor, enabled); colors.disabledTextDim = true; return colors; } protected ColorOptions PaintPopupRender(Graphics g) { ColorOptions colors = CommonRender(g); colors.disabledTextDim = true; return colors; } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms.ButtonInternal { using System; using System.Collections.Specialized; 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; ////// PLEASE READ /// ----------- /// This class is used for more than just Button: /// it's used for things that derive from ButtonBase, /// parts of ToolStripItem, and parts of the DataGridView. /// internal abstract class ButtonBaseAdapter { private ButtonBase control; // SystemInformation.Border3DSize + 2 pixels for focus rect protected static int buttonBorderSize = 4; internal ButtonBaseAdapter(ButtonBase control) { this.control = control; } protected ButtonBase Control { get { return this.control; } } internal void Paint(PaintEventArgs pevent) { if (Control.MouseIsDown) { PaintDown(pevent, CheckState.Unchecked); } else if (Control.MouseIsOver) { PaintOver(pevent, CheckState.Unchecked); } else { PaintUp(pevent, CheckState.Unchecked); } } internal virtual Size GetPreferredSizeCore(Size proposedSize) { // this is a shared cached graphics, therefore it does not require dispose. using (Graphics measurementGraphics = WindowsFormsUtils.CreateMeasurementGraphics()) { using (PaintEventArgs pe = new PaintEventArgs(measurementGraphics, new Rectangle())) { LayoutOptions options = Layout(pe); return options.GetPreferredSizeCore(proposedSize); } } } protected abstract LayoutOptions Layout(PaintEventArgs e); internal abstract void PaintUp(PaintEventArgs e, CheckState state); internal abstract void PaintDown(PaintEventArgs e, CheckState state); internal abstract void PaintOver(PaintEventArgs e, CheckState state); #region Drawing Helpers internal static Color MixedColor(Color color1, Color color2) { byte a1 = color1.A; byte r1 = color1.R; byte g1 = color1.G; byte b1 = color1.B; byte a2 = color2.A; byte r2 = color2.R; byte g2 = color2.G; byte b2 = color2.B; int a3 = (a1 + a2) / 2; int r3 = (r1 + r2) / 2; int g3 = (g1 + g2) / 2; int b3 = (b1 + b2) / 2; return Color.FromArgb(a3, r3, g3, b3); } internal static Brush CreateDitherBrush(Color color1, Color color2) { // Note: Don't dispose the bitmap here. The texture brush will take ownership // of the bitmap. So the bitmap will get disposed by the brush's Dispose(). using (Bitmap b = new Bitmap(2, 2)) { b.SetPixel(0, 0, color1); b.SetPixel(0, 1, color2); b.SetPixel(1, 1, color1); b.SetPixel(1, 0, color2); return new TextureBrush(b); } } ////// Get StringFormat object for rendering text using GDI+ (Graphics). /// internal virtual StringFormat CreateStringFormat() { return ControlPaint.CreateStringFormat( Control, Control.TextAlign, Control.ShowToolTip, Control.UseMnemonic ); } ////// Get TextFormatFlags flags for rendering text using GDI (TextRenderer). /// internal virtual TextFormatFlags CreateTextFormatFlags(){ return ControlPaint.CreateTextFormatFlags( Control, Control.TextAlign, Control.ShowToolTip, Control.UseMnemonic ); } internal static void DrawDitheredFill(Graphics g, Color color1, Color color2, Rectangle bounds) { using (Brush brush = CreateDitherBrush(color1, color2)) { g.FillRectangle(brush, bounds); } } protected void Draw3DBorder(Graphics g, Rectangle bounds, ColorData colors, bool raised) { if (Control.BackColor != SystemColors.Control && SystemInformation.HighContrast) { if (raised) { Draw3DBorderHighContrastRaised(g, ref bounds, colors); } else { ControlPaint.DrawBorder(g, bounds, ControlPaint.Dark(Control.BackColor), ButtonBorderStyle.Solid); } } else { if (raised) { Draw3DBorderRaised(g, ref bounds, colors); } else { Draw3DBorderNormal(g, ref bounds, colors); } } } private void Draw3DBorderHighContrastRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. WindowsPen penTopLeft = null; WindowsPen penBottomRight = null; WindowsPen insetPen = null; WindowsPen bottomRightInsetPen = null; try { // top + left penTopLeft = stockColor ? /*SystemPens.ControlLightLight*/ new WindowsPen(wg.DeviceContext, SystemColors.ControlLightLight) : new WindowsPen(wg.DeviceContext, colors.highlight); wg.DrawLine(penTopLeft, p1, p2); // top (right-left) wg.DrawLine(penTopLeft, p2, p3); // left (up-down) // bottom + right penBottomRight = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlDarkDark) : new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(penBottomRight, p3, p4); // bottom (left-right) wg.DrawLine(penBottomRight, p4, p1); // right (bottom-up ) // Draw inset if (stockColor) { if (SystemInformation.HighContrast) { insetPen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { insetPen = new WindowsPen(wg.DeviceContext, SystemColors.Control); } } else { if (SystemInformation.HighContrast) { insetPen = new WindowsPen(wg.DeviceContext, colors.highlight); } else { insetPen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } } p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); // top + left inset wg.DrawLine(insetPen, p1, p2); // top (right-left) wg.DrawLine(insetPen, p2, p3); // left( up-down) // Bottom + right inset bottomRightInsetPen = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlDark) : new WindowsPen(wg.DeviceContext, colors.buttonShadow); p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(bottomRightInsetPen, p3, p4); // bottom (left-right) wg.DrawLine(bottomRightInsetPen, p4, p1); // right (bottom-up) } finally { if (penTopLeft != null) { penTopLeft.Dispose(); } if (penBottomRight != null) { penBottomRight.Dispose(); } if (insetPen != null) { insetPen.Dispose(); } if (bottomRightInsetPen != null) { bottomRightInsetPen.Dispose(); } } } } private void Draw3DBorderNormal(Graphics g, ref Rectangle bounds, ColorData colors) { using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. // top + left WindowsPen pen = new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right pen = new WindowsPen(wg.DeviceContext, colors.highlight); try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } // Draw inset pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); // top + left inset try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right inset if (colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor()) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } } } private void Draw3DBorderRaised(Graphics g, ref Rectangle bounds, ColorData colors) { bool stockColor = colors.buttonFace.ToKnownColor() == SystemColors.Control.ToKnownColor(); using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(bounds.X + bounds.Width - 1, bounds.Y ); // upper inner right. Point p2 = new Point(bounds.X , bounds.Y ); // upper left. Point p3 = new Point(bounds.X , bounds.Y + bounds.Height - 1 ); // bottom inner left. Point p4 = new Point(bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1 ); // inner bottom right. // Draw counter-clock-wise. // top + left WindowsPen pen = stockColor ? new WindowsPen(wg.DeviceContext, SystemColors.ControlLightLight) : new WindowsPen(wg.DeviceContext, colors.highlight); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // bottom + right if (stockColor) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlDarkDark); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonShadowDark); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } // Draw inset p1.Offset(-1, 2); p2.Offset( 1, 1); p3.Offset( 1,-1); p4.Offset(-1,-1); if (stockColor) { if (SystemInformation.HighContrast) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlLight); } else { pen = new WindowsPen(wg.DeviceContext, SystemColors.Control); } } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonFace); } // top + left inset try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left(up-down) } finally { pen.Dispose(); } // Bottom + right inset if (stockColor) { pen = new WindowsPen(wg.DeviceContext, SystemColors.ControlDark); } else { pen = new WindowsPen(wg.DeviceContext, colors.buttonShadow); } try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom(left-right) wg.DrawLine(pen, p4, p1); // right (bottom-up) } finally { pen.Dispose(); } } } ////// Draws a border for the in the 3D style of the popup button. /// protected internal static void Draw3DLiteBorder(Graphics g, Rectangle r, ColorData colors, bool up) { using( WindowsGraphics wg = WindowsGraphics.FromGraphics(g) ) { // Draw counter-clock-wise. Point p1 = new Point(r.Right - 1, r.Top ); // upper inner right. Point p2 = new Point(r.Left , r.Top ); // upper left. Point p3 = new Point(r.Left , r.Bottom - 1); // bottom inner left. Point p4 = new Point(r.Right - 1, r.Bottom - 1); // inner bottom right. // top, left WindowsPen pen = up ? new WindowsPen(wg.DeviceContext, colors.highlight) : new WindowsPen(wg.DeviceContext, colors.buttonShadow); try { wg.DrawLine(pen, p1, p2); // top (right-left) wg.DrawLine(pen, p2, p3); // left (top-down) } finally { pen.Dispose(); } // bottom, right pen = up ? new WindowsPen(wg.DeviceContext, colors.buttonShadow) : new WindowsPen(wg.DeviceContext, colors.highlight); try { p1.Offset(0,-1); // need to paint last pixel too. wg.DrawLine(pen, p3, p4); // bottom (left-right) wg.DrawLine(pen, p4, p1); // right(bottom-up) } finally { pen.Dispose(); } } } internal static void DrawFlatBorder(Graphics g, Rectangle r, Color c) { ControlPaint.DrawBorder(g, r, c, ButtonBorderStyle.Solid); } ////// /// internal static void DrawFlatBorderWithSize(Graphics g, Rectangle r, Color c, int size) { bool stockBorder = c.IsSystemColor; SolidBrush brush = null; if (size > 1) { brush = new SolidBrush(c); } else { if (stockBorder) { brush = (SolidBrush)SystemBrushes.FromSystemColor(c); } else { brush = new SolidBrush(c); } } try { size = System.Math.Min(size, System.Math.Min(r.Width, r.Height)); // ...truncate pen width to button size, to avoid overflow if border size is huge! //Left Border g.FillRectangle(brush, r.X, r.Y, size, r.Height); //Right Border g.FillRectangle(brush, (r.X + r.Width - size), r.Y, size, r.Height); //Top Border g.FillRectangle(brush, (r.X + size), r.Y, (r.Width - size * 2), size); //Bottom Border g.FillRectangle(brush, (r.X + size), (r.Y + r.Height - size), (r.Width - size * 2), size); } finally { if (!stockBorder && brush != null) { brush.Dispose(); } } } internal static void DrawFlatFocus(Graphics g, Rectangle r, Color c) { using(WindowsGraphics wg = WindowsGraphics.FromGraphics(g)) { using (WindowsPen focus = new WindowsPen(wg.DeviceContext, c)) { wg.DrawRectangle(focus, r); } } } ////// Draws the flat border with specified bordersize. /// This function gets called only for Flatstyle == Flatstyle.Flat. /// ////// void DrawFocus(Graphics g, Rectangle r) { if (Control.Focused && Control.ShowFocusCues) { ControlPaint.DrawFocusRectangle(g, r, Control.ForeColor, Control.BackColor); } } ////// Draws the focus rectangle if the control has focus. /// /// ////// Draws the button's image. /// void DrawImage(Graphics graphics, LayoutData layout) { if (Control.Image != null) { //setup new clip region & draw DrawImageCore(graphics, Control.Image, layout.imageBounds, layout.imageStart, layout); } } // here for DropDownButton internal virtual void DrawImageCore(Graphics graphics, Image image, Rectangle imageBounds, Point imageStart, LayoutData layout) { Region oldClip = graphics.Clip; if (!layout.options.everettButtonCompat) { // FOR EVERETT COMPATIBILITY - DO NOT CHANGE Rectangle bounds = new Rectangle(buttonBorderSize, buttonBorderSize, this.Control.Width - (2 * buttonBorderSize), this.Control.Height - (2 * buttonBorderSize)); Region newClip = oldClip.Clone(); newClip.Intersect(bounds); // If we don't do this, DrawImageUnscaled will happily draw the entire image, even though imageBounds // is smaller than the image size. newClip.Intersect(imageBounds); graphics.Clip = newClip; } else { // FOR EVERETT COMPATIBILITY - DO NOT CHANGE imageBounds.Width += 1; imageBounds.Height +=1; imageBounds.X = imageStart.X + 1; imageBounds.Y = imageStart.Y + 1; } try { if (!Control.Enabled) // need to specify width and height ControlPaint.DrawImageDisabled(graphics, image, imageBounds, Control.BackColor, true /* unscaled image*/); else { graphics.DrawImage(image, imageBounds.X, imageBounds.Y, image.Width, image.Height); } } finally { if (!layout.options.everettButtonCompat) {// FOR EVERETT COMPATIBILITY - DO NOT CHANGE graphics.Clip = oldClip; } } } internal static void DrawDefaultBorder(Graphics g, Rectangle r, Color c, bool isDefault) { if (isDefault) { r.Inflate(1, 1); Pen pen; if (c.IsSystemColor) { pen = SystemPens.FromSystemColor(c); } else { pen = new Pen(c); } g.DrawRectangle(pen, r.X, r.Y, r.Width - 1, r.Height - 1); if (!c.IsSystemColor) { pen.Dispose(); } } } ////// Draws the button's text. /// void DrawText(Graphics g, LayoutData layout, Color c, ColorData colors) { Rectangle r = layout.textBounds; bool disabledText3D = layout.options.shadowedText; if (Control.UseCompatibleTextRendering) { // Draw text using GDI+ using (StringFormat stringFormat = CreateStringFormat()) { // DrawString doesn't seem to draw where it says it does if ((Control.TextAlign & LayoutUtils.AnyCenter) == 0) { r.X -= 1; } r.Width += 1; if (disabledText3D && !Control.Enabled) { r.Offset(1, 1); using (SolidBrush brush = new SolidBrush(colors.highlight)) { g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); r.Offset(-1, -1); brush.Color = colors.buttonShadow; g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); } } else { Brush brush; if (c.IsSystemColor) { brush = SystemBrushes.FromSystemColor(c); } else { brush = new SolidBrush(c); } g.DrawString(Control.Text, Control.Font, brush, r, stringFormat); if (!c.IsSystemColor) { brush.Dispose(); } } } } else { // Draw text using GDI (Whidbey feature). TextFormatFlags formatFlags = CreateTextFormatFlags(); if (disabledText3D && !Control.Enabled) { if (Application.RenderWithVisualStyles) { //don't draw chiseled text if themed as win32 app does. TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.buttonShadow, formatFlags); } else { r.Offset(1, 1); TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.highlight, formatFlags); r.Offset(-1, -1); TextRenderer.DrawText(g, Control.Text, Control.Font, r, colors.buttonShadow, formatFlags); } } else { TextRenderer.DrawText(g, Control.Text, Control.Font, r, c, formatFlags); } } } #endregion Drawing Helpers #region Draw Content Helpers // the DataGridViewButtonCell uses this method internal static void PaintButtonBackground(WindowsGraphics wg, Rectangle bounds, WindowsBrush background) { wg.FillRectangle(background, bounds); } internal void PaintButtonBackground(PaintEventArgs e, Rectangle bounds, Brush background) { if (background == null) { Control.PaintBackground(e, bounds); } else { e.Graphics.FillRectangle(background, bounds); } } internal void PaintField(PaintEventArgs e, LayoutData layout, ColorData colors, Color foreColor, bool drawFocus) { Graphics g = e.Graphics; Rectangle maxFocus = layout.focus; DrawText(g, layout, foreColor, colors); if (drawFocus) { DrawFocus(g, maxFocus); } } internal void PaintImage(PaintEventArgs e, LayoutData layout) { Graphics g = e.Graphics; DrawImage(g, layout); } #endregion #region Color internal class ColorOptions { internal Color backColor; internal Color foreColor; internal bool enabled; internal bool disabledTextDim; internal bool highContrast; internal Graphics graphics; internal ColorOptions(Graphics graphics, Color foreColor, Color backColor) { this.graphics = graphics; this.backColor = backColor; this.foreColor = foreColor; highContrast = SystemInformation.HighContrast; } internal static int Adjust255(float percentage, int value) { int v = (int)(percentage * value); if (v > 255) { return 255; } return v; } internal ColorData Calculate() { ColorData colors = new ColorData(this); colors.buttonFace = backColor; if (backColor == SystemColors.Control) { colors.buttonShadow = SystemColors.ControlDark; colors.buttonShadowDark = SystemColors.ControlDarkDark; colors.highlight = SystemColors.ControlLightLight; } else { if (!highContrast) { colors.buttonShadow = ControlPaint.Dark(backColor); colors.buttonShadowDark = ControlPaint.DarkDark(backColor); colors.highlight = ControlPaint.LightLight(backColor); } else { colors.buttonShadow = ControlPaint.Dark(backColor); colors.buttonShadowDark = ControlPaint.LightLight(backColor); colors.highlight = ControlPaint.LightLight(backColor); } } const float lowlight = .1f; float adjust = 1 - lowlight; if (colors.buttonFace.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } colors.lowButtonFace = Color.FromArgb(Adjust255(adjust, colors.buttonFace.R), Adjust255(adjust, colors.buttonFace.G), Adjust255(adjust, colors.buttonFace.B)); adjust = 1 - lowlight; if (colors.highlight.GetBrightness() < .5) { adjust = 1 + lowlight * 2; } colors.lowHighlight = Color.FromArgb(Adjust255(adjust, colors.highlight.R), Adjust255(adjust, colors.highlight.G), Adjust255(adjust, colors.highlight.B)); if (highContrast && backColor != SystemColors.Control) { colors.highlight = colors.lowHighlight; } colors.windowFrame = foreColor; /* debug * / colors.buttonFace = Color.Yellow; colors.buttonShadow = Color.Blue; colors.highlight = Color.Brown; colors.lowButtonFace = Color.Beige; colors.lowHighlight = Color.Cyan; colors.windowFrame = Color.Red; colors.windowText = Color.Green; / * debug */ if (colors.buttonFace.GetBrightness() < .5) { colors.constrastButtonShadow = colors.lowHighlight; } else { colors.constrastButtonShadow = colors.buttonShadow; } if (!enabled && disabledTextDim) { colors.windowText = colors.buttonShadow; } else { colors.windowText = colors.windowFrame; } IntPtr hdc = this.graphics.GetHdc(); try { using (WindowsGraphics wg = WindowsGraphics.FromHdc(hdc)) { colors.buttonFace = wg.GetNearestColor(colors.buttonFace); colors.buttonShadow = wg.GetNearestColor(colors.buttonShadow); colors.buttonShadowDark = wg.GetNearestColor(colors.buttonShadowDark); colors.constrastButtonShadow = wg.GetNearestColor(colors.constrastButtonShadow); colors.windowText = wg.GetNearestColor(colors.windowText); colors.highlight = wg.GetNearestColor(colors.highlight); colors.lowHighlight = wg.GetNearestColor(colors.lowHighlight); colors.lowButtonFace = wg.GetNearestColor(colors.lowButtonFace); colors.windowFrame = wg.GetNearestColor(colors.windowFrame); } } finally { this.graphics.ReleaseHdc(); } return colors; } } internal class ColorData { internal Color buttonFace; internal Color buttonShadow; internal Color buttonShadowDark; internal Color constrastButtonShadow; internal Color windowText; internal Color highlight; internal Color lowHighlight; internal Color lowButtonFace; internal Color windowFrame; internal ColorOptions options; internal ColorData(ColorOptions options) { this.options = options; } } #endregion #region Layout internal class LayoutOptions { internal Rectangle client; internal bool growBorderBy1PxWhenDefault; internal bool isDefault; internal int borderSize; internal int paddingSize; internal bool maxFocus; internal bool focusOddEvenFixup; internal Font font; internal string text; internal Size imageSize; internal int checkSize; internal int checkPaddingSize; internal ContentAlignment checkAlign; internal ContentAlignment imageAlign; internal ContentAlignment textAlign; internal TextImageRelation textImageRelation; internal bool hintTextUp; internal bool textOffset; internal bool shadowedText; internal bool layoutRTL; internal bool verticalText = false; internal bool useCompatibleTextRendering = false; internal bool everettButtonCompat = true; internal TextFormatFlags gdiTextFormatFlags = TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl; internal StringFormatFlags gdipFormatFlags; internal StringTrimming gdipTrimming; internal HotkeyPrefix gdipHotkeyPrefix; internal StringAlignment gdipAlignment; // horizontal alignment. internal StringAlignment gdipLineAlignment; // vertical alignment. private bool disableWordWrapping; ////// We don't cache the StringFormat itself because we don't have a deterministic way of disposing it, instead /// we cache the flags that make it up and create it on demand so it can be disposed by calling code. /// public StringFormat StringFormat { get { StringFormat format = new StringFormat(); format.FormatFlags = this.gdipFormatFlags; format.Trimming = this.gdipTrimming; format.HotkeyPrefix = this.gdipHotkeyPrefix; format.Alignment = this.gdipAlignment; format.LineAlignment = this.gdipLineAlignment; if (disableWordWrapping) { format.FormatFlags |= StringFormatFlags.NoWrap; } return format; } set { this.gdipFormatFlags = value.FormatFlags; this.gdipTrimming = value.Trimming; this.gdipHotkeyPrefix = value.HotkeyPrefix; this.gdipAlignment = value.Alignment; this.gdipLineAlignment = value.LineAlignment; } } ////// public TextFormatFlags TextFormatFlags { get { if (disableWordWrapping) { return gdiTextFormatFlags & ~TextFormatFlags.WordBreak; } return gdiTextFormatFlags; } //set { // this.gdiTextFormatFlags = value; //} } // textImageInset compensates for two factors: 3d text when the button is disabled, // and moving text on 3d-look buttons. These factors make the text require a couple // more pixels of space. We inset image by the same amount so they line up. internal int textImageInset = 2; internal Padding padding; #region PreferredSize private static readonly int combineCheck = BitVector32.CreateMask(); private static readonly int combineImageText = BitVector32.CreateMask(combineCheck); private enum Composition { NoneCombined = 0x00, CheckCombined = 0x01, TextImageCombined = 0x02, AllCombined = 0x03 } // Uses checkAlign, imageAlign, and textAlign to figure out how to compose // checkSize, imageSize, and textSize into the preferredSize. private Size Compose(Size checkSize, Size imageSize, Size textSize) { Composition hComposition = GetHorizontalComposition(); Composition vComposition = GetVerticalComposition(); return new Size( xCompose(hComposition, checkSize.Width, imageSize.Width, textSize.Width), xCompose(vComposition, checkSize.Height, imageSize.Height, textSize.Height) ); } private int xCompose(Composition composition, int checkSize, int imageSize, int textSize) { switch(composition) { case Composition.NoneCombined: return checkSize + imageSize + textSize; case Composition.CheckCombined: return Math.Max(checkSize, imageSize + textSize); case Composition.TextImageCombined: return Math.Max(imageSize, textSize) + checkSize; case Composition.AllCombined: return Math.Max(Math.Max(checkSize, imageSize), textSize); default: Debug.Fail(SR.GetString(SR.InvalidArgument, "composition", composition.ToString())); return -7107; } } // Uses checkAlign, imageAlign, and textAlign to figure out how to decompose // proposedSize into just the space left over for text. private Size Decompose(Size checkSize, Size imageSize, Size proposedSize) { Composition hComposition = GetHorizontalComposition(); Composition vComposition = GetVerticalComposition(); return new Size( xDecompose(hComposition, checkSize.Width, imageSize.Width, proposedSize.Width), xDecompose(vComposition, checkSize.Height, imageSize.Height, proposedSize.Height) ); } private int xDecompose(Composition composition, int checkSize, int imageSize, int proposedSize) { switch(composition) { case Composition.NoneCombined: return proposedSize - (checkSize + imageSize); case Composition.CheckCombined: return proposedSize - imageSize; case Composition.TextImageCombined: return proposedSize - checkSize; case Composition.AllCombined: return proposedSize; default: Debug.Fail(SR.GetString(SR.InvalidArgument, "composition", composition.ToString())); return -7109; } } private Composition GetHorizontalComposition() { BitVector32 action = new BitVector32(); // Checks reserve space horizontally if possible, so only AnyLeft/AnyRight prevents combination. action[combineCheck] = checkAlign == ContentAlignment.MiddleCenter || !LayoutUtils.IsHorizontalAlignment(checkAlign); action[combineImageText] = !LayoutUtils.IsHorizontalRelation(textImageRelation); return (Composition) action.Data; } internal Size GetPreferredSizeCore(Size proposedSize) { // Get space required for border and padding // int linearBorderAndPadding = borderSize*2 + paddingSize*2; if(growBorderBy1PxWhenDefault) { linearBorderAndPadding += 2; } Size bordersAndPadding = new Size(linearBorderAndPadding, linearBorderAndPadding); proposedSize -= bordersAndPadding; // Get space required for Check // int checkSizeLinear = FullCheckSize; Size checkSize = checkSizeLinear > 0 ? new Size(checkSizeLinear + 1, checkSizeLinear) : Size.Empty; // Get space required for Image - textImageInset compensated for by expanding image. // Size textImageInsetSize = new Size(textImageInset * 2, textImageInset * 2); Size requiredImageSize = (imageSize != Size.Empty) ? imageSize + textImageInsetSize : Size.Empty; // Pack Text into remaning space // proposedSize -= textImageInsetSize; proposedSize = Decompose(checkSize, requiredImageSize, proposedSize); Size textSize = Size.Empty; if (!string.IsNullOrEmpty(text)) { // When Button.AutoSizeMode is set to GrowOnly TableLayoutPanel expects buttons not to automatically wrap on word break. If // there's enough room for the text to word-wrap then it will happen but the layout would not be adjusted to allow text wrapping. // If someone has a carriage return in the text we'll honor that for preferred size, but we wont wrap based on constraints. // See VSW#542448,537840,515227. try { this.disableWordWrapping = true; textSize = GetTextSize(proposedSize) + textImageInsetSize; } finally { this.disableWordWrapping = false; } } // Combine pieces to get final preferred size // Size requiredSize = Compose(checkSize, imageSize, textSize); requiredSize += bordersAndPadding; return requiredSize; } private Composition GetVerticalComposition() { BitVector32 action = new BitVector32(); // Checks reserve space horizontally if possible, so only Top/Bottom prevents combination. action[combineCheck] = checkAlign == ContentAlignment.MiddleCenter || !LayoutUtils.IsVerticalAlignment(checkAlign); action[combineImageText] = !LayoutUtils.IsVerticalRelation(textImageRelation); return (Composition) action.Data; } #endregion PreferredSize private int FullBorderSize { get { int result = borderSize; if (OnePixExtraBorder) { borderSize++; } return borderSize; } } private bool OnePixExtraBorder { get { return growBorderBy1PxWhenDefault && isDefault; } } internal LayoutData Layout() { LayoutData layout = new LayoutData(this); layout.client = this.client; // subtract border size from layout area int fullBorderSize = FullBorderSize; layout.face = Rectangle.Inflate(layout.client, -fullBorderSize, -fullBorderSize); // checkBounds, checkArea, field // CalcCheckmarkRectangle(layout); // imageBounds, imageLocation, textBounds LayoutTextAndImage(layout); // focus // if (maxFocus) { layout.focus = layout.field; layout.focus.Inflate(-1, -1); // Adjust for padding. VSWhidbey #387208 layout.focus = LayoutUtils.InflateRect(layout.focus, this.padding); } else { Rectangle textAdjusted = new Rectangle(layout.textBounds.X - 1, layout.textBounds.Y - 1, layout.textBounds.Width + 2, layout.textBounds.Height + 3); if (imageSize != Size.Empty) { layout.focus = Rectangle.Union(textAdjusted, layout.imageBounds); } else { layout.focus = textAdjusted; } } if (focusOddEvenFixup) { if (layout.focus.Height % 2 == 0) { layout.focus.Y++; layout.focus.Height--; } if (layout.focus.Width % 2 == 0) { layout.focus.X++; layout.focus.Width--; } } return layout; } TextImageRelation RtlTranslateRelation(TextImageRelation relation) { // If RTL, we swap ImageBeforeText and TextBeforeImage if (layoutRTL) { switch(relation) { case TextImageRelation.ImageBeforeText: return TextImageRelation.TextBeforeImage; case TextImageRelation.TextBeforeImage: return TextImageRelation.ImageBeforeText; } } return relation; } internal ContentAlignment RtlTranslateContent(ContentAlignment align) { if (layoutRTL) { ContentAlignment[][] mapping = new ContentAlignment[3][]; mapping[0] = new ContentAlignment[2] { ContentAlignment.TopLeft, ContentAlignment.TopRight }; mapping[1] = new ContentAlignment[2] { ContentAlignment.MiddleLeft, ContentAlignment.MiddleRight }; mapping[2] = new ContentAlignment[2] { ContentAlignment.BottomLeft, ContentAlignment.BottomRight }; for(int i=0; i < 3; ++i) { if (mapping[i][0] == align) { return mapping[i][1]; } else if (mapping[i][1] == align) { return mapping[i][0]; } } } return align; } private int FullCheckSize { get { return checkSize + checkPaddingSize; } } void CalcCheckmarkRectangle(LayoutData layout) { int checkSizeFull = FullCheckSize; layout.checkBounds = new Rectangle(client.X, client.Y, checkSizeFull, checkSizeFull); // Translate checkAlign for Rtl applications ContentAlignment align = RtlTranslateContent(checkAlign); Rectangle field = Rectangle.Inflate(layout.face, -paddingSize, -paddingSize); layout.field = field; if (checkSizeFull > 0) { if ((align & LayoutUtils.AnyRight) != 0) { layout.checkBounds.X = (field.X+field.Width) - layout.checkBounds.Width; } else if ((align & LayoutUtils.AnyCenter) != 0) { layout.checkBounds.X = field.X + (field.Width - layout.checkBounds.Width)/2; } if ((align & LayoutUtils.AnyBottom) != 0) { layout.checkBounds.Y = (field.Y+field.Height)-layout.checkBounds.Height; } else if ((align & LayoutUtils.AnyTop) != 0) { layout.checkBounds.Y = field.Y + 2; // + 2: this needs to be aligned to the text (bug 87483) } else { layout.checkBounds.Y = field.Y + (field.Height - layout.checkBounds.Height)/2; } switch (align) { case ContentAlignment.TopLeft: case ContentAlignment.MiddleLeft: case ContentAlignment.BottomLeft: layout.checkArea.X = field.X; layout.checkArea.Width = checkSizeFull + 1; layout.checkArea.Y = field.Y; layout.checkArea.Height = field.Height; layout.field.X += checkSizeFull + 1; layout.field.Width -= checkSizeFull + 1; break; case ContentAlignment.TopRight: case ContentAlignment.MiddleRight: case ContentAlignment.BottomRight: layout.checkArea.X = field.X + field.Width - checkSizeFull; layout.checkArea.Width = checkSizeFull + 1; layout.checkArea.Y = field.Y; layout.checkArea.Height = field.Height; layout.field.Width -= checkSizeFull + 1; break; case ContentAlignment.TopCenter: layout.checkArea.X = field.X; layout.checkArea.Width = field.Width; layout.checkArea.Y = field.Y; layout.checkArea.Height = checkSizeFull; layout.field.Y += checkSizeFull; layout.field.Height -= checkSizeFull; break; case ContentAlignment.BottomCenter: layout.checkArea.X = field.X; layout.checkArea.Width = field.Width; layout.checkArea.Y = field.Y + field.Height - checkSizeFull; layout.checkArea.Height = checkSizeFull; layout.field.Height -= checkSizeFull; break; case ContentAlignment.MiddleCenter: layout.checkArea = layout.checkBounds; break; } layout.checkBounds.Width -= checkPaddingSize; layout.checkBounds.Height -= checkPaddingSize; } } // Maps an image align to the set of TextImageRelations that represent the same edge. // For example, imageAlign = TopLeft maps to TextImageRelations ImageAboveText (top) // and ImageBeforeText (left). private static readonly TextImageRelation[] _imageAlignToRelation = new TextImageRelation[] { /* TopLeft = */ TextImageRelation.ImageAboveText | TextImageRelation.ImageBeforeText, /* TopCenter = */ TextImageRelation.ImageAboveText, /* TopRight = */ TextImageRelation.ImageAboveText | TextImageRelation.TextBeforeImage, /* Invalid */ 0, /* MiddleLeft = */ TextImageRelation.ImageBeforeText, /* MiddleCenter = */ 0, /* MiddleRight = */ TextImageRelation.TextBeforeImage, /* Invalid */ 0, /* BottomLeft = */ TextImageRelation.TextAboveImage | TextImageRelation.ImageBeforeText, /* BottomCenter = */ TextImageRelation.TextAboveImage, /* BottomRight = */ TextImageRelation.TextAboveImage | TextImageRelation.TextBeforeImage }; private static TextImageRelation ImageAlignToRelation(ContentAlignment alignment) { return _imageAlignToRelation[LayoutUtils.ContentAlignmentToIndex(alignment)]; } private static TextImageRelation TextAlignToRelation(ContentAlignment alignment) { return LayoutUtils.GetOppositeTextImageRelation(ImageAlignToRelation(alignment)); } internal void LayoutTextAndImage(LayoutData layout) { // Translate for Rtl applications. This intentially shadows the member variables. ContentAlignment imageAlign = RtlTranslateContent(this.imageAlign); ContentAlignment textAlign = RtlTranslateContent(this.textAlign); TextImageRelation textImageRelation = RtlTranslateRelation(this.textImageRelation); // Figure out the maximum bounds for text & image Rectangle maxBounds = Rectangle.Inflate(layout.field, -textImageInset, -textImageInset); if(OnePixExtraBorder) { maxBounds.Inflate(1, 1); } // Compute the final image and text bounds. if(imageSize == Size.Empty || text == null || text.Length == 0 || textImageRelation == TextImageRelation.Overlay) { // Do not worry about text/image overlaying Size textSize = GetTextSize(maxBounds.Size); // FOR EVERETT COMPATIBILITY - DO NOT CHANGE Size size = imageSize; if (layout.options.everettButtonCompat && imageSize != Size.Empty) { size = new Size(size.Width + 1, size.Height + 1); } layout.imageBounds = LayoutUtils.Align(size, maxBounds, imageAlign); layout.textBounds = LayoutUtils.Align(textSize, maxBounds, textAlign); } else { // Rearrage text/image to prevent overlay. Pack text into maxBounds - space reserved for image Size maxTextSize = LayoutUtils.SubAlignedRegion(maxBounds.Size, imageSize, textImageRelation); Size textSize = GetTextSize(maxTextSize); Rectangle maxCombinedBounds = maxBounds; // Combine text & image into one rectangle that we center within maxBounds. Size combinedSize = LayoutUtils.AddAlignedRegion(textSize, imageSize, textImageRelation); maxCombinedBounds.Size = LayoutUtils.UnionSizes(maxCombinedBounds.Size, combinedSize); Rectangle combinedBounds = LayoutUtils.Align(combinedSize, maxCombinedBounds, ContentAlignment.MiddleCenter); // imageEdge indicates whether the combination of imageAlign and textImageRelation place // the image along the edge of the control. If so, we can increase the space for text. bool imageEdge = (AnchorStyles)(ImageAlignToRelation(imageAlign) & textImageRelation) != AnchorStyles.None; // textEdge indicates whether the combination of textAlign and textImageRelation place // the text along the edge of the control. If so, we can increase the space for image. bool textEdge = (AnchorStyles)(TextAlignToRelation(textAlign) & textImageRelation) != AnchorStyles.None; if(imageEdge) { // If imageEdge, just split imageSize off of maxCombinedBounds. LayoutUtils.SplitRegion(maxCombinedBounds, imageSize, (AnchorStyles) textImageRelation, out layout.imageBounds, out layout.textBounds); } else if(textEdge) { // Else if textEdge, just split textSize off of maxCombinedBounds. LayoutUtils.SplitRegion(maxCombinedBounds, textSize, (AnchorStyles) LayoutUtils.GetOppositeTextImageRelation(textImageRelation), out layout.textBounds, out layout.imageBounds); } else { // Expand the adjacent regions to maxCombinedBounds (centered) and split the rectangle into imageBounds and textBounds. LayoutUtils.SplitRegion(combinedBounds, imageSize, (AnchorStyles) textImageRelation, out layout.imageBounds, out layout.textBounds); LayoutUtils.ExpandRegionsToFillBounds(maxCombinedBounds, (AnchorStyles) textImageRelation, ref layout.imageBounds, ref layout.textBounds); } // align text/image within their regions. layout.imageBounds = LayoutUtils.Align(imageSize, layout.imageBounds, imageAlign); layout.textBounds = LayoutUtils.Align(textSize, layout.textBounds, textAlign); } //Don't call "layout.imageBounds = Rectangle.Intersect(layout.imageBounds, maxBounds);" // because that is a breaking change that causes images to be scaled to the dimensions of the control. //adjust textBounds so that the text is still visible even if the image is larger than the button's size //fixes Whidbey 234985 //why do we intersect with layout.field for textBounds while we intersect with maxBounds for imageBounds? //this is because there are some legacy code which squeezes the button so small that text will get clipped //if we intersect with maxBounds. Have to do this for backward compatibility. //See Whidbey 341480 if (textImageRelation == TextImageRelation.TextBeforeImage || textImageRelation == TextImageRelation.ImageBeforeText) { //adjust the vertical position of textBounds so that the text doesn't fall off the boundary of the button int textBottom = Math.Min(layout.textBounds.Bottom, layout.field.Bottom); layout.textBounds.Y = Math.Max(Math.Min(layout.textBounds.Y, layout.field.Y + (layout.field.Height - layout.textBounds.Height)/2), layout.field.Y); layout.textBounds.Height = textBottom - layout.textBounds.Y; } if (textImageRelation == TextImageRelation.TextAboveImage || textImageRelation == TextImageRelation.ImageAboveText) { //adjust the horizontal position of textBounds so that the text doesn't fall off the boundary of the button int textRight = Math.Min(layout.textBounds.Right, layout.field.Right); layout.textBounds.X = Math.Max(Math.Min(layout.textBounds.X, layout.field.X + (layout.field.Width - layout.textBounds.Width)/2), layout.field.X); layout.textBounds.Width = textRight - layout.textBounds.X; } if (textImageRelation == TextImageRelation.ImageBeforeText && layout.imageBounds.Size.Width != 0) { //squeezes imageBounds.Width so that text is visible layout.imageBounds.Width = Math.Max(0, Math.Min(maxBounds.Width - layout.textBounds.Width, layout.imageBounds.Width)); layout.textBounds.X = layout.imageBounds.X + layout.imageBounds.Width; } if (textImageRelation == TextImageRelation.ImageAboveText && layout.imageBounds.Size.Height != 0) { //squeezes imageBounds.Height so that the text is visible layout.imageBounds.Height = Math.Max(0, Math.Min(maxBounds.Height - layout.textBounds.Height, layout.imageBounds.Height)); layout.textBounds.Y = layout.imageBounds.Y + layout.imageBounds.Height; } //make sure that textBound is contained in layout.field layout.textBounds = Rectangle.Intersect(layout.textBounds, layout.field); if (hintTextUp) { layout.textBounds.Y--; } if (textOffset) { layout.textBounds.Offset(1, 1); } // FOR EVERETT COMPATIBILITY - DO NOT CHANGE if (layout.options.everettButtonCompat) { layout.imageStart = layout.imageBounds.Location; layout.imageBounds = Rectangle.Intersect(layout.imageBounds, layout.field); } else if (!Application.RenderWithVisualStyles) { // Not sure why this is here, but we can't remove it, since it might break // ToolStrips on non-themed machines layout.textBounds.X++; } // clip // int bottom; // If we are using GDI to measure text, then we can get into a situation, where // the proposed height is ignore. In this case, we want to clip it against // maxbounds. VSWhidbey #480670 if (!useCompatibleTextRendering) { bottom = Math.Min(layout.textBounds.Bottom, maxBounds.Bottom); layout.textBounds.Y = Math.Max(layout.textBounds.Y, maxBounds.Y); } else { // If we are using GDI+ (like Everett), then use the old Everett code // This ensures that we have pixel-level rendering compatibility bottom = Math.Min(layout.textBounds.Bottom, layout.field.Bottom); layout.textBounds.Y = Math.Max(layout.textBounds.Y, layout.field.Y); } layout.textBounds.Height = bottom - layout.textBounds.Y; //This causes a breaking change because images get shrunk to the new clipped size instead of clipped. //********** bottom = Math.Min(layout.imageBounds.Bottom, maxBounds.Bottom); //********** layout.imageBounds.Y = Math.Max(layout.imageBounds.Y, maxBounds.Y); //********** layout.imageBounds.Height = bottom - layout.imageBounds.Y; } protected virtual Size GetTextSize(Size proposedSize) { //set the Prefix field of TextFormatFlags proposedSize = LayoutUtils.FlipSizeIf(verticalText, proposedSize); Size textSize = Size.Empty; if (useCompatibleTextRendering) { // GDI+ text rendering. using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics()) { using ( StringFormat gdipStringFormat = this.StringFormat ) { textSize = Size.Ceiling(g.MeasureString(text, font, new SizeF(proposedSize.Width, proposedSize.Height), gdipStringFormat)); } } } else if (!string.IsNullOrEmpty(text)) { // GDI text rendering (Whidbey feature). textSize = TextRenderer.MeasureText(text, font, proposedSize, this.TextFormatFlags); } //else skip calling MeasureText, it should return 0,0 return LayoutUtils.FlipSizeIf(verticalText, textSize); } #if DEBUG public override string ToString() { return "{ client = " + client + "\n" + "OnePixExtraBorder = " + OnePixExtraBorder + "\n" + "borderSize = " + borderSize + "\n" + "paddingSize = " + paddingSize + "\n" + "maxFocus = " + maxFocus + "\n" + "font = " + font + "\n" + "text = " + text + "\n" + "imageSize = " + imageSize + "\n" + "checkSize = " + checkSize + "\n" + "checkPaddingSize = " + checkPaddingSize + "\n" + "checkAlign = " + checkAlign + "\n" + "imageAlign = " + imageAlign + "\n" + "textAlign = " + textAlign + "\n" + "textOffset = " + textOffset + "\n" + "shadowedText = " + shadowedText + "\n" + "textImageRelation = " + textImageRelation + "\n" + "layoutRTL = " + layoutRTL + " }"; } #endif } internal class LayoutData { internal Rectangle client; internal Rectangle face; internal Rectangle checkArea; internal Rectangle checkBounds; internal Rectangle textBounds; internal Rectangle field; internal Rectangle focus; internal Rectangle imageBounds; internal Point imageStart; // FOR EVERETT COMPATIBILITY - DO NOT CHANGE internal LayoutOptions options; internal LayoutData(LayoutOptions options) { Debug.Assert(options != null, "must have options"); this.options = options; } } #endregion #region Layout // used by the DataGridViewButtonCell internal static LayoutOptions CommonLayout(Rectangle clientRectangle, Padding padding, bool isDefault, Font font, string text, bool enabled, ContentAlignment textAlign, RightToLeft rtl) { LayoutOptions layout = new LayoutOptions(); layout.client = LayoutUtils.DeflateRect(clientRectangle, padding); layout.padding = padding; layout.growBorderBy1PxWhenDefault = true; layout.isDefault = isDefault; layout.borderSize = 2; layout.paddingSize = 0; layout.maxFocus = true; layout.focusOddEvenFixup = false; layout.font = font; layout.text = text; layout.imageSize = Size.Empty; layout.checkSize = 0; layout.checkPaddingSize = 0; layout.checkAlign = ContentAlignment.TopLeft; layout.imageAlign = ContentAlignment.MiddleCenter; layout.textAlign = textAlign; layout.hintTextUp = false; layout.shadowedText = !enabled; layout.layoutRTL = RightToLeft.Yes == rtl; layout.textImageRelation = TextImageRelation.Overlay; layout.useCompatibleTextRendering = false; return layout; } internal virtual LayoutOptions CommonLayout() { LayoutOptions layout = new LayoutOptions(); layout.client = LayoutUtils.DeflateRect(Control.ClientRectangle, Control.Padding); layout.padding = Control.Padding; layout.growBorderBy1PxWhenDefault = true; layout.isDefault = Control.IsDefault; layout.borderSize = 2; layout.paddingSize = 0; layout.maxFocus = true; layout.focusOddEvenFixup = false; layout.font = Control.Font; layout.text = Control.Text; layout.imageSize = (Control.Image == null) ? Size.Empty : Control.Image.Size; layout.checkSize = 0; layout.checkPaddingSize = 0; layout.checkAlign = ContentAlignment.TopLeft; layout.imageAlign = Control.ImageAlign; layout.textAlign = Control.TextAlign; layout.hintTextUp = false; layout.shadowedText = !Control.Enabled; layout.layoutRTL = RightToLeft.Yes == Control.RightToLeft; layout.textImageRelation = Control.TextImageRelation; layout.useCompatibleTextRendering = Control.UseCompatibleTextRendering; if( Control.FlatStyle != FlatStyle.System ) { if( layout.useCompatibleTextRendering ) { using( StringFormat format = Control.CreateStringFormat() ) { layout.StringFormat = format; } } else { layout.gdiTextFormatFlags = Control.CreateTextFormatFlags(); } } return layout; } // used by the DataGridViewButtonCell static ColorOptions CommonRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = new ColorOptions(g, foreColor, backColor); colors.enabled = enabled; return colors; } ColorOptions CommonRender(Graphics g) { ColorOptions colors = new ColorOptions(g, Control.ForeColor, Control.BackColor); colors.enabled = Control.Enabled; return colors; } protected ColorOptions PaintRender(Graphics g) { ColorOptions colors = CommonRender(g); return colors; } // used by the DataGridViewButtonCell internal static ColorOptions PaintFlatRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = CommonRender(g, foreColor, backColor, enabled); colors.disabledTextDim = true; return colors; } protected ColorOptions PaintFlatRender(Graphics g) { ColorOptions colors = CommonRender(g); colors.disabledTextDim = true; return colors; } // used by the DataGridViewButtonCell internal static ColorOptions PaintPopupRender(Graphics g, Color foreColor, Color backColor, bool enabled) { ColorOptions colors = CommonRender(g, foreColor, backColor, enabled); colors.disabledTextDim = true; return colors; } protected ColorOptions PaintPopupRender(Graphics g) { ColorOptions colors = CommonRender(g); colors.disabledTextDim = true; return colors; } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbConnectionPoolOptions.cs
- MatrixCamera.cs
- QilName.cs
- ScopedKnownTypes.cs
- DictionaryEditChange.cs
- HttpCapabilitiesEvaluator.cs
- NameHandler.cs
- AttachInfo.cs
- PermissionAttributes.cs
- RegisteredHiddenField.cs
- CultureInfo.cs
- CoreSwitches.cs
- TextRunProperties.cs
- ScrollItemPattern.cs
- WCFBuildProvider.cs
- XLinq.cs
- HistoryEventArgs.cs
- DSASignatureFormatter.cs
- PrintControllerWithStatusDialog.cs
- storagemappingitemcollection.viewdictionary.cs
- QEncodedStream.cs
- LocalizedNameDescriptionPair.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- XmlSchemaFacet.cs
- BufferBuilder.cs
- SerializationTrace.cs
- PreservationFileWriter.cs
- ConfigurationStrings.cs
- OracleConnectionStringBuilder.cs
- SourceSwitch.cs
- ConnectionStringsExpressionBuilder.cs
- CompilerParameters.cs
- UriTemplate.cs
- Queue.cs
- WindowsTokenRoleProvider.cs
- CircleHotSpot.cs
- ServiceNotStartedException.cs
- ListSurrogate.cs
- DesignerActionPropertyItem.cs
- ProfileServiceManager.cs
- cookiecontainer.cs
- _CookieModule.cs
- RelatedView.cs
- BlockCollection.cs
- FixUpCollection.cs
- ServiceReflector.cs
- LinearGradientBrush.cs
- ActivationArguments.cs
- RoutedEvent.cs
- DataConnectionHelper.cs
- OutputCacheModule.cs
- ComboBoxAutomationPeer.cs
- BitmapMetadataEnumerator.cs
- DesignerActionUI.cs
- DesignTimeData.cs
- SqlCacheDependencySection.cs
- SqlDataSourceWizardForm.cs
- ByteStream.cs
- PrintDialog.cs
- QueuedDeliveryRequirementsMode.cs
- XmlDocumentSchema.cs
- SqlProviderUtilities.cs
- UnsafeNativeMethods.cs
- NumberFormatInfo.cs
- EventSchemaTraceListener.cs
- BaseTemplateCodeDomTreeGenerator.cs
- SqlException.cs
- DataListItemCollection.cs
- _SafeNetHandles.cs
- CodeGenerationManager.cs
- ExpressionWriter.cs
- Sentence.cs
- HttpInputStream.cs
- PreservationFileReader.cs
- TableCellAutomationPeer.cs
- DataObjectMethodAttribute.cs
- elementinformation.cs
- TextureBrush.cs
- RequestNavigateEventArgs.cs
- FormsAuthenticationEventArgs.cs
- Pen.cs
- Directory.cs
- elementinformation.cs
- XmlSchemaDatatype.cs
- FixedSchema.cs
- BaseResourcesBuildProvider.cs
- BamlRecordReader.cs
- DataError.cs
- __TransparentProxy.cs
- HttpUnhandledOperationInvoker.cs
- WebAdminConfigurationHelper.cs
- ZipIOModeEnforcingStream.cs
- HttpConfigurationContext.cs
- SRGSCompiler.cs
- HelpEvent.cs
- ListViewPagedDataSource.cs
- behaviorssection.cs
- ListenerSessionConnectionReader.cs
- TdsParser.cs
- BuildResult.cs