1

In a custom control, deriving from Button, the ButtonRenderer.DrawButton() draws a button, in various states.

All is fine when the display settings in Windows are set to a color-depth of 32-bits, but once, it is set to 16-bits, the color does not match one of a regular WinForms button and it stands out in my UI, which I do not really want.

I've replicated this using a minimal example code like this.

    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);
    }

which gives this...

Rendered Buttons

I'm sure you will all notice that the two "buttons" drawn by the DrawButton methods have a slightly lighter color than the standard button, and Form background (which I didn't change and left as the default which is "Control")... If you zoom enough, you can see that it is alternating pixels of the correct background color and another brighter color...

I spotted this issue because our users are using Remote Desktop (RDP) to connect to our applications. Forcing the remote desktop settings to 32-bits resolves the problem but I think it has a performance impact, and some of our users are working overseas over relatively slow broadband links... so enforcing 32-bits is an option I would prefer to avoid. It also happens in front of a PC, by setting the display settings to 16-bits colors.

Do you please have any ideas? Is it some kind of bug with ButtonRenderer and ControlPaint classes, or is there a way around this? (I'm using .Net 4.0).

4

1 回答 1

1

ControlPaint.DrawButton 是 Win32 的DrawFrameControl的包装器。

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

如果您只是自己调用 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);
}

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

于 2012-08-23T22:19:29.927 回答