切换启用时,TextBox 的文本略有移动:字体和字体大小发生变化
TextBox's Text is moving slightly when toggling Enabled: Font and Font size changes
在我的应用程序中,我有自定义文本框控件。当我更改 Enabled
属性.
时,它的文本似乎在移动
我不明白这是什么原因。
我将更改 TextAlign
、AutoSize
、Enabled
和 Font
属性
我试过使用TextRenderer.DrawText()
:它似乎解决了一些问题,但是当我更改为特定字体和字体大小时,文本再次移动(例如,设置MS コシック,10pt)。
我搜索了网站并阅读了以下内容,但似乎没有正确理解:
Using Graphics.DrawString to Simulate TextBox rendering
How do I use DrawString without trimming?
Graphics.DrawString vs TextRenderer.DrawText?Which can Deliver Better Quality
以下是部分截图:
MS コシック, 10pt 和 TextAlign Center and e.Graphics.DrawString
↓↓ Enabled ↓↓
↓↓ Disabled ↓↓
comparison
MS コシック, 10pt 和 TextAlign Center and TextRenderer.DrawText
↓↓ Enabled ↓↓
↓↓ Disabled ↓↓
comparison (text seems to be slightly elongated when disabled)
我的代码的原始 post
https://devlights.hatenablog.com/entry/20070523/p1
这是我的自定义控件代码:
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);
}
}
}
}
测试表:
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;
}
}
更新 1
我已经根据 Jimi 提供的答案更改了我的代码
并对其进行了测试,它解决了一些问题,但是当我使用
时问题仍然存在
MS コシック, 10pt 并且发现在两个 MS UI Gothic, 10pt 和 MS コシック, 10pt 的情况下,文本在轻微移动 downward.My 应用程序使用 MS コシック 7pt~12pt.So 我必须展示10pt 正确。
我还没有测试过其他字体。
请帮助。
抱歉之前没有提供.Net framework
我正在使用
.NET Framework 3.5
BorderStyle None
测试用例
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
以下是
的屏幕截图
MS コシック, 10pt 和 TextAlign Center and BorderStyle None andTextRenderer.DrawText
MS UI 哥特式、10pt 和 TextAlign Center 和 BorderStyle None 和 TextRenderer.DrawText
更新了以下代码:
我已经在 .Net Framework 3.5 和 4.8
中对其进行了测试
自定义启用状态文本框:
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);
}
}
}
测试表:
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;
}
}
}
对文本呈现进行一些更改应该可以让您接近预期。
- 使用TextRenderer绘制文字
- 将
TextFormatFlags.TextBoxControl
和 TextFormatFlags.NoPadding
添加到 TextRenderer.DrawText()
中使用的 TextFormatFlags (请参阅有关这两个的文档)
- 覆盖
OnBorderStyleChanged()
以在自定义绘制控件时用 Fixed3D
替换 FixedSingle
样式。这就是基础 class (TextBoxBase) 所做的,否则您将获得缩小 Win32 控件的客户区域的默认内部边框。
- 当
BorderStyle = BorderStyle.Fixed3D
时,将控件的 ClientRectangle 扩大 -1
像素。
我在 SetStyle()
调用之后添加了 UpdateStyles():这会强制使用新样式并导致控件重新绘制自身。
请注意,在设置控件的文本时设置不支持所有代码点(简化:文本中的 Unicode 字符)的字体可能会导致字体回退。
实际上,系统将 select 替换控件字体的映射代理字体。这种情况透明地发生并且没有通知。
在类似情况下,不同的图形渲染器可能会以不同的方式运行。
在此处查看注释:
在 RichTextBox 控件中有些不同(.Net 基础 class 相同,但 Win32 控件完全不同):
此外,最近,所有亚洲字体渲染和 UI 表示都已修改,以更好地处理其特性。所以使用的 .Net 版本也可以改变行为。
这里的代码是用 .Net Framework 4.8
.
测试的
public partial class CustomEnabledStateTextBox : TextBox
{
public CustomEnabledStateTextBox() => this.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;
}
private TextFormatFlags flags = TextFormatFlags.TextBoxControl |
TextFormatFlags.NoPadding;
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);
flags |= alignment;
TextRenderer.DrawText(e.Graphics, Text, Font, rect, ForeColor, flags);
base.OnPaint(e);
}
}
在我的应用程序中,我有自定义文本框控件。当我更改 Enabled
属性.
我不明白这是什么原因。
我将更改
TextAlign
、AutoSize
、Enabled
和Font
属性
我试过使用TextRenderer.DrawText()
:它似乎解决了一些问题,但是当我更改为特定字体和字体大小时,文本再次移动(例如,设置MS コシック,10pt)。
我搜索了网站并阅读了以下内容,但似乎没有正确理解:
Using Graphics.DrawString to Simulate TextBox rendering
How do I use DrawString without trimming?
Graphics.DrawString vs TextRenderer.DrawText?Which can Deliver Better Quality
以下是部分截图:
MS コシック, 10pt 和 TextAlign Center and e.Graphics.DrawString
↓↓ Enabled ↓↓
↓↓ Disabled ↓↓
comparison
MS コシック, 10pt 和 TextAlign Center and TextRenderer.DrawText
↓↓ Enabled ↓↓
↓↓ Disabled ↓↓
comparison (text seems to be slightly elongated when disabled)
我的代码的原始 post https://devlights.hatenablog.com/entry/20070523/p1
这是我的自定义控件代码:
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);
}
}
}
}
测试表:
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;
}
}
更新 1
我已经根据 Jimi 提供的答案更改了我的代码
并对其进行了测试,它解决了一些问题,但是当我使用
时问题仍然存在
MS コシック, 10pt 并且发现在两个 MS UI Gothic, 10pt 和 MS コシック, 10pt 的情况下,文本在轻微移动 downward.My 应用程序使用 MS コシック 7pt~12pt.So 我必须展示10pt 正确。
我还没有测试过其他字体。
请帮助。
抱歉之前没有提供.Net framework 我正在使用
.NET Framework 3.5
BorderStyle None
测试用例
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
以下是
的屏幕截图MS コシック, 10pt 和 TextAlign Center and BorderStyle None andTextRenderer.DrawText
MS UI 哥特式、10pt 和 TextAlign Center 和 BorderStyle None 和 TextRenderer.DrawText
更新了以下代码: 我已经在 .Net Framework 3.5 和 4.8
中对其进行了测试自定义启用状态文本框:
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);
}
}
}
测试表:
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;
}
}
}
对文本呈现进行一些更改应该可以让您接近预期。
- 使用TextRenderer绘制文字
- 将
TextFormatFlags.TextBoxControl
和TextFormatFlags.NoPadding
添加到TextRenderer.DrawText()
中使用的 TextFormatFlags (请参阅有关这两个的文档) - 覆盖
OnBorderStyleChanged()
以在自定义绘制控件时用Fixed3D
替换FixedSingle
样式。这就是基础 class (TextBoxBase) 所做的,否则您将获得缩小 Win32 控件的客户区域的默认内部边框。 - 当
BorderStyle = BorderStyle.Fixed3D
时,将控件的 ClientRectangle 扩大-1
像素。
我在 SetStyle()
调用之后添加了 UpdateStyles():这会强制使用新样式并导致控件重新绘制自身。
请注意,在设置控件的文本时设置不支持所有代码点(简化:文本中的 Unicode 字符)的字体可能会导致字体回退。
实际上,系统将 select 替换控件字体的映射代理字体。这种情况透明地发生并且没有通知。
在类似情况下,不同的图形渲染器可能会以不同的方式运行。
在此处查看注释:
在 RichTextBox 控件中有些不同(.Net 基础 class 相同,但 Win32 控件完全不同):
此外,最近,所有亚洲字体渲染和 UI 表示都已修改,以更好地处理其特性。所以使用的 .Net 版本也可以改变行为。
这里的代码是用 .Net Framework 4.8
.
public partial class CustomEnabledStateTextBox : TextBox
{
public CustomEnabledStateTextBox() => this.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;
}
private TextFormatFlags flags = TextFormatFlags.TextBoxControl |
TextFormatFlags.NoPadding;
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);
flags |= alignment;
TextRenderer.DrawText(e.Graphics, Text, Font, rect, ForeColor, flags);
base.OnPaint(e);
}
}