我有一个自定义文本的显示器,当用户自定义它时,我希望显示文本。其中一个可用的自定义是一个“x-out”,它应该在文本的所有5个字符上绘制一个大的“X”。因此,当复选框“X-Out”被选中时,它应该从以下内容更新文本:
对此:
该框本身是一个包含在Panel中的RichTextBox。我尝试在面板中使用Paint事件,但它将其绘制在RichTextBox下面(即角落上的小红线)。我还尝试使用自定义RichTextBox控件,如at this website。这段代码可以工作,但前提是我没有在RichTextBox中设置文本和颜色。如果我设置文本和颜色,然后选中复选框,则不会调用WndProc方法。如何使用Message.msg15触发WndProc方法?代码如下:
形式
public partial class ButtonDataForm : Form
{
CustomRichTextBox button1;
public ButtonDataForm()
{
InitializeComponent()
}
void OnFormLoad(object sender, EventArgs e)
{
cstmRichTextBox = new CustomRichTextBox(richTextBox1);
}
void OnXOutChecked()
{
cstmRichTextBox.IsChecked = xoutCheckbox.Checked;
cstmRichTextBox.ParentTex.Refresh(); // This does not trigger the WndProc message on cstmRichTextBox
}
}
自定义RichTextBox
public class CustomRichTextBox : NativeWindow
{
public RichTextBox ParentTextBox { get; private set; }
Graphics textBoxGraphics;
public bool IsChecked { get; set; }
public CustomRichTextBox(RichTextBox tb)
{
ParentTextBox = tb;
textBoxGraphics = Graphics.FromHwnd(tb.Handle);
AssignHandle(ParentTextBox.Handle);
}
protected override void WndProc(ref Message m}
{
switch(m.Msg)
{
case 15:
parentTextBox.Invalidate();
base.WndProc(ref m);
DrawXOut();
break;
default:
base.WndProc(ref m);
break;
}
}
void DrawXOut()
{
if (IsChecked)
{
Pen xpen = new Pen(ParentTextBox.ForeColor, 3);
Point topLeft = ParentTextBox.Location;
int x1 = topLeft.X + ParentTextBox.Width;
int y1 = topLeft.Y + ParentTextBox.Height;
Point topRight = new Point(x1, topLeft.Y);
Point bottomLeft = new Point(topLeft.X, y1);
Point bottomRight = new Point(x1, y1);
textBoxGraphics.DrawLine(xpen, topLeft, bottomRight);
textBoxGraphics.DrawLine(xpen, bottomLeft, topRight);
}
}
}
编辑:
我尝试在底部面板上放置一个透明面板,并在Paint事件触发时在其中进行绘制。事件触发,但面板中没有显示任何内容。我算错位置了吗?
void OnXOutChecked()
{
panel1.Refresh();
}
void OnPanel1Paint(object sender, PaintEventArgs e)
{
Pen xpen = new Pen(Color.Red, 3);
Point topLeft = panel1.Location;
int x1 = topLeft.X + panel1.Width;
int y1 = topLeft.Y + panel1.Height;
Point topRight = new Point(x1, topLeft.Y);
Point bottomLeft = new Point(topLeft.X, y1);
Point bottomRight = new Point(x1, y1);
e.Graphics.DrawLine(xpen, topLeft, bottomRight);
e.Graphics.DrawLine(xpen, bottomLeft, topRight);
}
3条答案
按热度按时间3htmauhk1#
我只是稍微修改了一下你的
CustomRichTextBox
:niwlg2el2#
这是一种非常不可靠的方法,在控件之上绘制并期望它在所有可能的场景中工作(可能有很多!).
你可以在文本框的顶部放置一个透明的图片框,上面有一个带有两条红色交叉线的透明位图。
gkl3eglg3#
老实说,我觉得你不想这么做你滥用了文本框,这不是它的本意。我不知道你的真实意图,但也许一个删除线可能是一个有效的解决方案?
我的经验告诉我,最好按原样使用组件,不要对它们做太多更改。
实际答案
如果你真的想,你可以这样做:(根据尼克的回答)