我想在某些时候在按钮上显示错误提供程序图标,如下所示:
但是,如果用户在打算单击按钮时碰巧单击该图标,我也不希望该图标遮盖/阻止按钮单击,也许是因为悬停时的错误消息显示“单击此处修复”之类的内容.
ErrorProvider 没有事件(好吧,它有一个不相关的事件)。 我尝试使用本文中描述的方法,但问题是当我单击错误图标时,甚至没有出现预过滤消息。 这是我的示例代码:
public partial class Form1 : Form, IMessageFilter
{
public Form1()
{
InitializeComponent();
errorProvider1.SetIconPadding(button1, -27);
errorProvider1.SetError(button1, "error");
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
var ctrl = Control.FromHandle(m.HWnd);
var msg = m.Msg;
// the values in the "ignore" list below are all movement/paint events
if (ctrl is Button b && (!(new[] { 15, 512, 675, 280, 673 }.Any((v) => msg == v))))
{
// only gets here when un-obscured button surface is clicked.
}
// this only ever prints form and button
if (ctrl != null) System.Diagnostics.Debug.Print($"{ctrl.GetType().Name}");
return false;
}
}
有什么办法可以做到这一点吗?
ErrorProvider
来轻松伪造
ToolTip
:
public partial class FakeErrorProvider : Form
{
private static Icon _errorIcon = new ErrorProvider().Icon;
private static int _errorIconPadding = 4;
private ToolTip _toolTip;
private bool _hasError;
public FakeErrorProvider()
{
InitializeComponent();
_toolTip = new ToolTip();
button1.Click += Button1_Click;
button1.Paint += Button1_Paint;
button1.MouseMove += Button1_MouseMove;
}
private void Button1_Click(object? sender, EventArgs e)
{
// fixing the error only when the error icon is clicked
if (!_hasError || GetErrorRectangle(button1).Contains(button1.PointToClient(Cursor.Position)))
_hasError = !_hasError;
button1.Invalidate();
if (!_hasError)
_toolTip.SetToolTip(button1, String.Empty);
}
private void Button1_Paint(object? sender, PaintEventArgs e)
{
// showing the error icon
if (_hasError)
e.Graphics.DrawIcon(_errorIcon, GetErrorRectangle(button1));
}
private void Button1_MouseMove(object? sender, MouseEventArgs e)
{
// displaying the error tooltip only when the cursor is above the error icon
bool isVisible = _toolTip.GetToolTip(button1).Length > 0;
if (_hasError && !isVisible && GetErrorRectangle(button1).Contains(e.Location))
_toolTip.SetToolTip(button1, "click here to fix");
else if (isVisible && (!_hasError || !GetErrorRectangle(button1).Contains(e.Location)))
_toolTip.SetToolTip(button1, String.Empty);
}
private Rectangle GetErrorRectangle(Button button)
{
var rect = new Rectangle(Point.Empty, _errorIcon.Size);
rect.Offset(button.Width - rect.Width - _errorIconPadding, button.Height / 2 - rect.Height / 2);
return rect;
}
}
结果: