请考虑以下代码:
主表单模板模型:
public partial class CustomForm : Form
{
public CustomForm()
{
InitializeComponent();
DoubleBuffered = true;
}
}
特定表单模板模型:
public partial class PopupForm : CustomForm
{
public PopupForm()
{
InitializeComponent();
BTN_Maximize.Hide();
}
}
派生形式:
public partial class SiteAccess : CustomForm
{
public SiteAccess()
{
InitializeComponent();
this.SizeGripStyle = SizeGripStyle.Show;
}
}
(主要表格)
+
public partial class Edition : PopupForm
{
public Edition()
{
InitializeComponent();
}
}
+
public partial class Preferences : PopupForm
{
public Preferences()
{
InitializeComponent();
}
}
+
public partial class About : PopupForm
{
public About()
{
InitializeComponent();
}
}
在我的表单模板模型PopupForm中,我为空面板定义了一个Paint事件处理程序,如下所示:
private void PNL_TitleBar_Paint(object sender, PaintEventArgs e)
{
Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
new Point((int)e.ClipRectangle.Right, 0),
Color.Gray,
Color.FromArgb(255, 50, 50, 50));
Pen gradientPen = new Pen(gradientBrush);
e.Graphics.DrawLine(gradientPen,
new Point((int)e.ClipRectangle.Left, (int)e.ClipRectangle.Bottom - 1),
new Point((int)e.ClipRectangle.Right, (int)e.ClipRectangle.Bottom - 1));
gradientPen.Dispose();
gradientBrush.Dispose();
}
要简化它,只需在面板底部绘制一条渐变线。
问题来自这样一个事实:每当我尝试从一个派生形式的PopupForm (版本,首选项或关于)中插入一个来自工具箱的新控件时,我收到此消息:< / p>
我之前向你展示了Paint事件处理程序的原因是因为我发现它是问题的根源,但我仍然不知道如何修复它。实际上,如果我删除了Paint事件处理程序的代码,则根本不会抛出任何异常。
顺便说一下,我必须指定一些内容:
但是,如果我重建解决方案(不执行程序)并返回到Designer,则在窗体中插入控件时会显示异常。
有关这种奇怪行为的任何想法吗?
答案 0 :(得分:6)
这是由代码中的错误引起的。底层异常是LinearGradientBrush构造函数抛出的GDI +异常。由于难以解释而臭名昭着,当它在设计时发生时会变得更糟。从技术上讲,这在运行时也可能出错,只是不太可能。您可以通过对代码进行少量更改来一致地重新调整它:
Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
new Point((int)0, 0), // <=== here
Color.Gray,
Color.FromArgb(255, 50, 50, 50));
KABOOM。使用e.ClipRectangle初始化画笔永远是正确的,你得到的渐变是高度不可预测的。 e.ClipRectangle值的变化取决于窗口的哪个部分需要重新绘制,现在你完全依赖它作为整个窗口。当您将窗口拖离屏幕边缘时,不就是这种情况。视觉神器应该非常明显。
修正:
Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
new Point(this.ClientSize.Width, 0),
Color.Gray,
Color.FromArgb(255, 50, 50, 50));
必须修复DrawLine()调用以使线条出现在一致的位置。不要担心剪辑,Windows已经自动处理它。
要小心使用e.ClipRectangle属性,非常小心,它常常是偶然的,但几乎不是你真正想要使用的。只能用它来检查是否可以跳过绘图部件,因为它们位于裁剪区域之外。哪些代码很难获得回报,在启用Aero的现代Windows版本上,这种情况并不经常发生。不要打扰。
答案 1 :(得分:3)
在Paint
处理程序中,您可以检查DesignMode
属性,并在Forms Designer中跳过绘制标题栏:
void PNL_TitleBar_Paint(object sender, PaintEventArgs e)
{
if (DesignMode)
return;
using (Brush gradientBrush = new LinearGradientBrush(new Point(0, 0),
new Point((int)e.ClipRectangle.Right, 0),
Color.Gray,
Color.FromArgb(255, 50, 50, 50)))
using (Pen gradientPen = new Pen(gradientBrush))
{
e.Graphics.DrawLine(gradientPen,
new Point((int)e.ClipRectangle.Left, (int)e.ClipRectangle.Bottom - 1),
new Point((int)e.ClipRectangle.Right, (int)e.ClipRectangle.Bottom - 1));
}
}
这适用于您的Paint
方法和大多数其他情况。有关不寻常情况的讨论,例如在构造函数中要做什么,请参阅here。
(建议使用using
语句替换对Dispose
的显式调用。)