base.OnPaint顺序更改绘图位置

时间:2016-10-20 11:49:27

标签: c# winforms

我有一个奇怪的问题。我自己创建了来自UserControl的用户控件。我重写了OnPaint。现在我在OnPaint画一些东西。让我们说在0,0位置。

如果我在自定义绘图后调用base.OnPaint,一切都很好。但是如果我在绘制的东西之前调用base.OnPaint,它似乎忽略了包含控件,并且位置相对于窗体而不是相对于父控件的客户区域。因此,当我在位置(0,0)处绘制时,它将有效地绘制在负x和y处,而我只会看到它的一部分。 base.OnPaintUserControl.OnPaint。所以我不会在那里调用我的代码。

以下是一个例子:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    var rect = new System.Drawing.Rectangle(this.ClientSize.Width - 16,
            this.ClientSize.Height - 16, 16, 16);

    e.Graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.Red), rect);

    //base.OnPaint(e);
}

在这种情况下,红色矩形显示在客户区内的某处,但不显示在右下角。如果我取消注释最后一行并注释第一行,红色矩形将按预期显示在右下角。

我不明白。我做了很多次这总是有效的。所以我试图发现任何差异。我唯一发现的是我没有在设计器中添加我的控件,而是以编程方式将其添加到theContainingControl.Controls.Add(myMessedUpControl);的另一个控件中。

这也适用于我添加的每个父子级别。因此,如果我创建另一个控件(另一个类)并覆盖OnPaint,如果我将其添加到另一个用户控件,行为是相同的。

之前有没有人有这种行为?我怎样才能解决这个问题?问题是,我想首先致电base.OnPaint并且每个人都建议这样做。但正如我所说,我不能没有弄乱坐标。

一个注意事项:在DrawLineDrawImageDrawString之类的绘制调用中,调试器中的坐标实际为0,0。但结果显示在负坐标(相对于客户区)。看起来客户端坐标被解释为表单的客户端坐标。但我不知道为什么。

发现问题

在我的项目中有一个图形覆盖类,它将Paint事件处理程序连接到我的表单中的所有控件(整个层次结构)。在此处理程序中,执行转换。这种图形叠加让我多次失眠。我想我会删除它。

1 个答案:

答案 0 :(得分:1)

Graphics对象有很多可变状态。如果你搞乱这种可变状态,操作顺序就很重要 - 例如,你可以使用Transform矩阵来改变表面上渲染的所有东西的偏移量。

听起来你的上升者在其自己的OnPaint处理程序中更改其中一个而不重置它。在开始绘画之前尝试做e.Graphics.ResetTransform();。确保所有其他状态也是您想要的状态(剪辑,DPI,......)。