临时变量对删除GroupBox背景的影响

时间:2018-08-17 18:06:21

标签: c# .net winforms pinvoke

上下文:

请考虑使用渐变作为背景的一部分来绘制GroupBox

示例:

Ideal <code>GroupBox</code>


让我们执行以下操作:

  • 创建一个继承class的{​​{1}}。
    • GroupBox FlatStyle设置为property
    • FlatStyle.Systemoverride方法。
    • 处理WndProc消息,在其中我们绘制渐变
    • 处理WM_ERASEBKGND消息,我们将其称为WM_PRINTCLIENTDefWndProc
      (稍后将需要。)
  • 添加一个return作为其子Label
    Control 的背景必须透明以能够看到其背后的渐变。 Label

    • 创建一个继承Text的{​​{1}}。
    • class Label方法。
    • 模拟透明度”,方法是调用override函数以在WndProc的{​​{1}}上绘制DrawThemeParentBackground的背景。< / li>

问题:

  

根据是否使用临时变量来保存GroupBox Label,最终结果会有所不同,如下面的代码示例和图片所示:

Graphics

运行上述MCVE (情况1)会产生预期的输出,如示例图片所示。

在注释掉标记为 CASE 1 的行并取消注释标记为 CASE 2 的行时,将得到以下不良输出:

Actual <code>GroupBox</code>

问题:

为什么移除临时变量会产生如此巨大的输出?

2 个答案:

答案 0 :(得分:1)

出于完整性考虑,将此作为答案发布。

  • 正如Ivan Stoev所指出的那样,没有所有权 PaintEventArgs 不会呼叫{{1}上的Dispose } Graphics
  • 这具有明显的副作用,因为Windows在object WM_PRINTCLIENT中将DC 重用,该DC发送到{{ 1}}。

Message WndProc上手动调用Dispose确认了这一点。

Graphics

答案 1 :(得分:0)

这一切可以归结为一个简单的派生类,而无需PInvoking吗? 此类从GroupBox派生,使用CreateParams CreateParams.ExStyle属性将其设置为Transparent,启用对Control.SetStyle()ControlStyles.SupportsTransparentBackColor样式的Transparent颜色的支持(通过这种方式,您可以更好地控制LinearGradientBrush的效果,并覆盖OnPaintBackground()方法以执行绘画。

这只是一个基本示例,但可以通过其他任何方式进行调整,并且仍更具便携性。
您可以在其上放置任何控件。

class GradientGroupBox : GroupBox
{
    private const int WS_EX_TRANSPARENT = 0x20;
    public GradientGroupBox() => this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        base.OnPaintBackground(e);
        Color gradFillTo = Color.FromArgb(200, SystemColors.Window);
        Color gradFillFrom = Color.FromArgb(128, this.Parent.BackColor);
        using (LinearGradientBrush gradientBrush = new LinearGradientBrush(this.ClientRectangle, gradFillFrom, gradFillTo, LinearGradientMode.Vertical))
        {
            e.Graphics.FillRectangle(gradientBrush, this.ClientRectangle);
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams parameters = base.CreateParams;
            parameters.ExStyle |= WS_EX_TRANSPARENT;
            return parameters;
        }
    }
}

GradientGroupBox