0

有没有办法在 Windows 窗体 StatusBar 类上启用双缓冲?

我正在更新鼠标移动事件的一些地图坐标,并且闪烁/重绘非常明显。我尝试从 StatusBar 类继承并设置它DoubleBuffer = true并覆盖它的OnPaintBackground方法。我还尝试了所有者绘制的东西,但没有任何运气。

4

2 回答 2

0

The System.Windows.Forms.StatusBar is a legacy control, it might not care about the DoubleBuffered property. You can try setting it like so in the constructor of a derived class:

this.SetStyle(ControlStyles.DoubleBuffer, true);

Although I would really recommend trying the StatusStrip control. It's made for Windows Forms and not drawn by the OS while the StatusBar is.

于 2013-10-05T03:41:13.437 回答
0
//declare a renderer, but do not initialize in here,
//because if current theme is classics, it will error
VisualStyleRenderer _barRenderer;

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        //eat WM_ERASEBKGND, and in WM_PAINT draw the background
        case 0x14:
            m.Result = (IntPtr)1;
            return;

        case 0xF://WM_PAINT
            PAINTSTRUCT ps;
            var hdc = BeginPaint(m.HWnd, out ps); //see MSDN
            BufferedGraphics bg = null; //use memory graphics
            try
            {
                var rect = ClientRectangle;
                bg = BufferedGraphicsManager.Current.Allocate(hdc, rect);

                //draw background
                if (Application.RenderWithVisualStyles)
                {
                    //just initialize renderer once
                    if (_barRenderer == null)
                    {
                        _barRenderer = new VisualStyleRenderer(VisualStyleElement.Status.Bar.Normal);
                    }
                    _barRenderer.DrawBackground(bg.Graphics, rect);
                }
                else
                {
                    bg.Graphics.SetClip(rect); //not essential
                    bg.Graphics.Clear(SystemColors.Control);
                }

                //let system draw foreground, include texts, icons, separators etc
                m.WParam = bg.Graphics.GetHdc(); //required, GetHdc() is not only obtain a dc handle, 
                base.WndProc(ref m);             //it open a context for the dc, and let system draw on this context
                bg.Graphics.ReleaseHdc();        //timely release

                bg.Render();
                return;
            }
            finally
            {
                if (bg != null) { bg.Dispose(); }
                EndPaint(m.HWnd, ref ps); //see MSDN
            }
    }
    base.WndProc(ref m);
}

#region Win32 API

[DllImport("user32.dll")]
private static extern IntPtr BeginPaint(IntPtr hWnd, out PAINTSTRUCT lpPaint);

[DllImport("user32.dll")]
private static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint);

[StructLayout(LayoutKind.Sequential)]
private struct PAINTSTRUCT
{
    public IntPtr hdc;
    public bool fErase;
    public RECT rcPaint;
    public bool fRestore;
    public bool fIncUpdate;
    public int reserved1;
    public int reserved2;
    public int reserved3;
    public int reserved4;
    public int reserved5;
    public int reserved6;
    public int reserved7;
    public int reserved8;
}

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

#endregion
于 2017-03-22T12:32:30.310 回答