In my application, I have Custom TextBox Control. Its Text seems to be moving when I change the Enabled
property.
I don't understand what cause this.
I will be changing
TextAlign
,AutoSize
,Enabled
, andFont
properties
I've tried using TextRenderer.DrawText()
: it seems to fix some issues but when I change to certain Font and Font size, the Text is moving again (for example, setting MS ゴシック, 10pt).
I have searched the site and read the following but didn't seem to understand properly:
Using Graphics.DrawString to Simulate TextBox rendering
How do I use DrawString without trimming?
Graphics.DrawString vs TextRenderer.DrawText?Which can Deliver Better Quality
Here are some screenshots:
MS ゴシック, 10pt And TextAlign Center and e.Graphics.DrawString
MS ゴシック, 10pt And TextAlign Center and TextRenderer.DrawText
comparison (text seems to be slightly elongated when disabled)
Original post of my code https://devlights.hatenablog.com/entry/20070523/p1
This is my Custom Control code do far:
using System.Drawing;
using System.Windows.Forms;
public partial class CustomEnabledStateTextBox : TextBox
{
public CustomEnabledStateTextBox()
{
InitializeComponent();
AutoSize = false;
}
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
protected override void OnEnabledChanged(EventArgs e)
{
this.SetStyle(ControlStyles.UserPaint, !this.Enabled);
this.Invalidate();
base.OnEnabledChanged(e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (StringFormat sf = new StringFormat())
{
if (this.TextAlign == HorizontalAlignment.Center)
{
sf.Alignment = StringAlignment.Center;
}
else if (this.TextAlign == HorizontalAlignment.Left)
{
sf.Alignment = StringAlignment.Near;
}
else
{
sf.Alignment = StringAlignment.Far;
}
using (SolidBrush brush = new SolidBrush(ForeColor))
{
//MS UI Gothic, 8pt --> not OK
//MS UI Gothic, 9pt --> OK
//MS UI Gothic, 10pt --> OK
//MS UI Gothic, 11pt --> OK
//MS UI Gothic, 12pt --> not OK
e.Graphics.DrawString(
base.Text, base.Font, brush, new Rectangle(-1, 1, base.Width, base.Height), sf);
//MS ゴシック, 8pt --> not OK
//MS ゴシック, 9pt --> not OK
//MS ゴシック, 10pt --> not OK
//MS ゴシック, 12pt --> not OK
//e.Graphics.DrawString(
// base.Text, base.Font, brush, new Rectangle(-1, 1, base.Width, base.Height), sf);
//MS ゴシック, 10pt --> not OK
//TextRenderer.DrawText(e.Graphics, Text, Font, new Rectangle(0, 0, Width, Height), ForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.NoPadding | TextFormatFlags.Internal);
}
if (this.BorderStyle == BorderStyle.FixedSingle)
{
e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.Width - 1, this.Height - 1);
}
}
}
}
Test Form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
customEnabledStateTextBox1.Text = "2021/04/04";
customEnabledStateTextBox1.Size = new Size(88, 20);
customEnabledStateTextBox1.BorderStyle = BorderStyle.None;
customEnabledStateTextBox1.TextAlign = HorizontalAlignment.Center;
}
private void button1_Click(object sender, EventArgs e)
{
customEnabledStateTextBox1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
customEnabledStateTextBox1.Enabled = false;
}
}
Update 1
I have Changed my code according to Answer provided by Jimi
And tested it and it fix some issues but the problem still exits when I used
MS ゴシック, 10pt And fount out that in both MS UI Gothic, 10pt AND MS ゴシック, 10pt cases , Text is moving slightly downward.My application use MS ゴシック 7pt~12pt.So I have to show 10pt correctly.
I haven't tested with other Fonts though.
Please Help.
Sorry that I didn`t provide .Net framework before I am be using
.NET Framework 3.5
BorderStyle None
Test Case
MS UI Gothic, 8pt-- > OK
MS UI Gothic, 9pt-- > OK
MS UI Gothic, 10pt-- > not OK
MS UI Gothic, 11pt-- > OK
MS UI Gothic, 12pt-- > OK
MS ゴシック, 8pt-- > OK
MS ゴシック, 9pt-- > OK
MS ゴシック, 10pt-- > not OK
MS ゴシック, 12pt-- > OK
Here are Screenshots for
MS ゴシック, 10pt And TextAlign Center and BorderStyle None andTextRenderer.DrawText
MS UI Gothic, 10pt And TextAlign Center and BorderStyle None and TextRenderer.DrawText
Updated Code below : I have tested it in both .Net Framework 3.5 And 4.8
CustomEnabledStateTextBox :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormTest1
{
public partial class CustomEnabledStateTextBox : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public CustomEnabledStateTextBox()
{
InitializeComponent();
AutoSize = false;
}
protected override void OnEnabledChanged(EventArgs e)
{
//>>>Change 1
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, !Enabled);
UpdateStyles();
//>>>Change 1
base.OnEnabledChanged(e);
}
//>>>Change 1
protected override void OnBorderStyleChanged(EventArgs e)
{
base.OnBorderStyleChanged(e);
if (BorderStyle == BorderStyle.FixedSingle)
{
BorderStyle = BorderStyle.Fixed3D;
}
}
//>>>Change 1
protected override void OnPaint(PaintEventArgs e)
{
using (StringFormat sf = new StringFormat())
{
if (this.TextAlign == HorizontalAlignment.Center)
{
sf.Alignment = StringAlignment.Center;
}
else if (this.TextAlign == HorizontalAlignment.Left)
{
sf.Alignment = StringAlignment.Near;
}
else
{
sf.Alignment = StringAlignment.Far;
}
//>>>Change 1
var rect = ClientRectangle;
if (BorderStyle != BorderStyle.None) rect.Inflate(-1, -1);
var alignment = TextAlign == HorizontalAlignment.Left
? TextFormatFlags.Left : (TextFormatFlags)((int)TextAlign ^ 3);
var flags = TextFormatFlags.TextBoxControl | TextFormatFlags.NoPadding | alignment;
//>>>Change 1
using (SolidBrush brush = new SolidBrush(ForeColor))
{
//MS UI Gothic, 8pt --> not OK
//MS UI Gothic, 9pt --> OK
//MS UI Gothic, 10pt --> OK
//MS UI Gothic, 11pt --> OK
//MS UI Gothic, 12pt --> not OK
//e.Graphics.DrawString(
// base.Text, base.Font, brush, new Rectangle(-1, 1, base.Width, base.Height), sf);
//MS ゴシック, 8pt --> not OK
//MS ゴシック, 9pt --> not OK
//MS ゴシック, 10pt --> not OK
//MS ゴシック, 12pt --> not OK
//e.Graphics.DrawString(
// base.Text, base.Font, brush, new Rectangle(-1, 1, base.Width, base.Height), sf);
//MS ゴシック, 10pt --> not OK
//TextRenderer.DrawText(e.Graphics, Text, Font, new Rectangle(0, 0, Width, Height), ForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.NoPadding | TextFormatFlags.Internal);
//TextRenderer.DrawText(e.Graphics, Text, Font, new Rectangle(0, 0, Width, Height), ForeColor, flags);
//>>>Change 1
//MS UI Gothic, 8pt --> OK
//MS UI Gothic, 9pt --> OK
//MS UI Gothic, 10pt --> not OK
//MS UI Gothic, 11pt --> OK
//MS UI Gothic, 12pt --> OK
//MS ゴシック, 8pt --> OK
//MS ゴシック, 9pt --> OK
//MS ゴシック, 10pt --> not OK
//MS ゴシック, 12pt --> OK
TextRenderer.DrawText(e.Graphics, Text, Font, rect, ForeColor, flags);
//>>>Change 1
}
if (this.BorderStyle == BorderStyle.FixedSingle)
{
e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.Width - 1, this.Height - 1);
}
//>>>Change 1
base.OnPaint(e);
//>>>Change 1
}
}
}
}
CustomEnabledStateTextBoxSO :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormTest1
{
public partial class CustomEnabledStateTextBoxSO : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public CustomEnabledStateTextBoxSO()
{
InitializeComponent();
AutoSize = false;
}
protected override void OnEnabledChanged(EventArgs e)
{
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, !Enabled);
UpdateStyles();
base.OnEnabledChanged(e);
}
protected override void OnBorderStyleChanged(EventArgs e)
{
base.OnBorderStyleChanged(e);
if (BorderStyle == BorderStyle.FixedSingle)
{
BorderStyle = BorderStyle.Fixed3D;
}
}
protected override void OnPaint(PaintEventArgs e)
{
var rect = ClientRectangle;
if (BorderStyle != BorderStyle.None) rect.Inflate(-1, -1);
var alignment = TextAlign == HorizontalAlignment.Left
? TextFormatFlags.Left : (TextFormatFlags)((int)TextAlign ^ 3);
var flags = TextFormatFlags.TextBoxControl | TextFormatFlags.NoPadding | alignment;
//MS UI Gothic, 8pt-- > OK
//MS UI Gothic, 9pt-- > OK
//MS UI Gothic, 10pt-- > not OK
//MS UI Gothic, 11pt-- > OK
//MS UI Gothic, 12pt-- > OK
//MS ゴシック, 8pt-- > OK
//MS ゴシック, 9pt-- > OK
//MS ゴシック, 10pt-- > not OK
//MS ゴシック, 12pt-- > OK
TextRenderer.DrawText(e.Graphics, Text, Font, rect, ForeColor, flags);
base.OnPaint(e);
}
}
}
Test Form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormTest1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//Left Side
customEnabledStateTextBox1.Text = "2021/04/04";
customEnabledStateTextBox1.Size = new Size(88, 20); //size will change if i set Autosize true
customEnabledStateTextBox1.BorderStyle = BorderStyle.None;
customEnabledStateTextBox1.TextAlign = HorizontalAlignment.Center;
//Right Side
customEnabledStateTextBoxSO1.Text = "2021/04/04";
customEnabledStateTextBoxSO1.Size = new Size(88, 20); //size will change if i set Autosize true
customEnabledStateTextBoxSO1.BorderStyle = BorderStyle.None;
customEnabledStateTextBoxSO1.TextAlign = HorizontalAlignment.Center;
}
private void button1_Click(object sender, EventArgs e)
{
customEnabledStateTextBox1.Enabled = true;
customEnabledStateTextBoxSO1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
customEnabledStateTextBox1.Enabled = false;
customEnabledStateTextBoxSO1.Enabled = false;
}
}
}