.net ButtonRenderer使用与按钮不同的16位背景色

.net ButtonRenderer使用与按钮不同的16位背景色,.net,winforms,button,colors,.net,Winforms,Button,Colors,在从Button派生的自定义控件中,ButtonRenderer.DrawButton()以各种状态绘制按钮 当Windows中的显示设置设置为32位的颜色深度时,一切都很好,但一旦设置为16位,颜色与常规WinForms按钮的颜色不匹配,并且它在我的UI中很突出,这不是我真正想要的 我已经用这样一个最小的示例代码复制了这一点 protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e);

在从Button派生的自定义控件中,ButtonRenderer.DrawButton()以各种状态绘制按钮

当Windows中的显示设置设置为32位的颜色深度时,一切都很好,但一旦设置为16位,颜色与常规WinForms按钮的颜色不匹配,并且它在我的UI中很突出,这不是我真正想要的

我已经用这样一个最小的示例代码复制了这一点

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

        Rectangle rect = new Rectangle(10, 10, 250, 120);
        ButtonRenderer.DrawButton(e.Graphics, rect, PushButtonState.Normal);

        rect = new Rectangle(300, 300, 250, 120);
        ControlPaint.DrawButton(e.Graphics, rect, ButtonState.Normal);
    }
这就给了这个

我相信大家都会注意到,DrawButton方法绘制的两个“按钮”的颜色比标准按钮稍浅,并形成背景(我没有更改,默认为“控件”)。。。 如果你足够放大,你可以看到它是正确的背景颜色和另一个更明亮的颜色交替像素

我发现了这个问题,因为我们的用户正在使用远程桌面(RDP)连接到我们的应用程序。强制远程桌面设置为32位可以解决问题,但我认为这会影响性能,而且我们的一些用户在海外通过相对较慢的宽带链路工作。。。因此,强制执行32位是我宁愿避免的选择。 它也发生在电脑前,通过将显示设置设置为16位颜色


你有什么想法吗?这是ButtonRenderer和ControlPaint类的某种缺陷,还是有办法解决这个问题?(我使用的是.Net 4.0)。

ControlPaint.DrawButton是Win32的包装器

它渲染为位图,然后将位图绘制到图形显示上下文中。颜色抖动/近似发生在该位图层。我没有时间做进一步的实验了,但是

如果您自己只调用DrawFrameControl,则所有操作都有效:

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool DrawFrameControl(IntPtr hDC, ref RECT rect, int type, int state);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;

    public RECT(Rectangle r)
    {
        this.left = r.Left;
        this.top = r.Top;
        this.right = r.Right;
        this.bottom = r.Bottom;
    }
}

protected override void OnPaint(PaintEventArgs e)
{
    if (Application.RenderWithVisualStyles)
         ButtonRenderer.DrawButton(.....)
    else
    {
         var rect = new RECT(new Rectangle(10, 110, 100, 100));
         DrawFrameControl(e.Graphics.GetHdc(), ref rect, 4, 0x10 | (int)ButtonState.Normal);
    }

    base.OnPaint(e);
}

编辑:添加了对主题的可选调用

ControlPaint.DrawButton是Win32的包装器

它渲染为位图,然后将位图绘制到图形显示上下文中。颜色抖动/近似发生在该位图层。我没有时间做进一步的实验了,但是

如果您自己只调用DrawFrameControl,则所有操作都有效:

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool DrawFrameControl(IntPtr hDC, ref RECT rect, int type, int state);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;

    public RECT(Rectangle r)
    {
        this.left = r.Left;
        this.top = r.Top;
        this.right = r.Right;
        this.bottom = r.Bottom;
    }
}

protected override void OnPaint(PaintEventArgs e)
{
    if (Application.RenderWithVisualStyles)
         ButtonRenderer.DrawButton(.....)
    else
    {
         var rect = new RECT(new Rectangle(10, 110, 100, 100));
         DrawFrameControl(e.Graphics.GetHdc(), ref rect, 4, 0x10 | (int)ButtonState.Normal);
    }

    base.OnPaint(e);
}

编辑:添加了对主题的可选调用

只是为了简化-ButtonRenderer.DrawButton在内部调用ControlPaint.DrawButton,使它们成为等效的调用。@JohnArlen-如果用户启用了windows主题(如XP的Luna等)ButtonRenderer调用在绘制时考虑了Windows主题,而ControlPaint调用在绘制时不考虑主题(即,看起来很经典)。只是为了简化-ButtonRenderer.DrawButton在内部调用ControlPaint.DrawButton,使其调用等效。@JohnArlen-如果用户启用了Windows主题(如XP的Luna等)ButtonRenderer调用绘制时考虑了Windows主题,而ControlPaint调用绘制时不考虑主题(即看起来像经典)。谢谢。这确实有效,尽管它不支持ButtonRenderer那样的主题。事实上,颜色会抖动,即使它可以正确地显示在第一位对我来说似乎是框架中的一个错误?添加一个主题检查,并以一种或另一种方式进行…在上面的Paint上编辑一个示例。谢谢,这是一个很好的解决方法nd,虽然即使按钮是主题化的,ButtonRenderer.DrawButton按钮也会抖动,看起来不像一个普通的主题控件…你是否也认为这是有问题的.Net库中的一个bug,如果是,我可以尝试报告它?谢谢。这确实有效,尽管它不支持ButtonRenderer那样的主题。事实上即使可以正确显示,颜色也会抖动对我来说在框架中似乎是一个错误?添加主题检查并以这种或那种方式进行…使用示例在上面的Paint上进行编辑。谢谢,这是一个很好的解决方法,尽管即使按钮是主题化的,ButtonRenderer.DrawButton按钮也会抖动,看起来不一样就像一个普通的主题控件…你是否也认为这是一个有问题的.Net库中的bug,如果是,我可以尝试报告它?