C#OnPaint mouse移动高CPU使用率

时间:2009-10-15 06:14:24

标签: c# .net graphics gdi

我编写了一个自定义控件来渲染一些图形。渲染图形本身相当昂贵,但一旦渲染它很少改变。我遇到的问题是,如果你在图形表面上快速移动鼠标,它会一直调用控件的重写Paint方法,这会导致高CPU损失:

private void UserControl1_Paint(object sender,PaintEventArgs e)

可以使用哪些技术来避免这种情况或最小化任何不必要的重绘,因为鼠标指针下面的图形/图像实际上没有变化?

6 个答案:

答案 0 :(得分:3)

编辑:在看到您的编辑后,我可以向您保证,当鼠标移动到控件上时,默认情况下不会调用OnPaint。代码中的某些东西肯定会导致重新绘制,你只是还没有看到它。也许发布一些代码可以帮助我们找到问题。

您是否在MouseMove上使控件无效?这可能是一个坏主意,如果你真的需要这样做(即,你正在制作一个图形编辑器或其他东西),你必须聪明一个区域实际重新绘制的大小。所以,解决方案;不要在MouseMove中绘制控件。

否则,当鼠标移动到控件上时,我不希望OnPaint触发。您也可以只生成一次图像,然后将其blt到Graphics对象,直到需要重新生成。

答案 1 :(得分:2)

您可以使用缓冲图像在更改内容时绘制,在Paint方法中只需复制屏幕上的图像。应该很快。您还可以使用剪辑区域仅复制需要更新的部分。这应该会降低CPU使用率。

如果需要,您还可以使用IsDirty标志来了解何时更新缓冲区图像(即完全重绘)。

答案 2 :(得分:2)

您不应直接致电Paint

相反,请致电InvalidateControl.Invalidate)。这需要重新绘制,Windows将自己处理调用。这样,一次调用Paint就可以为很多快速失效(重新绘制请求)提供服务。

答案 3 :(得分:1)

在Paint方法中可能导致高CPU负载的一个原因是不正确(非托管)资源释放。确保你使用Dispose()所有的笔,画笔等(可能所有的System.Drawing类实例都有一些绑定到它们的非托管资源)。 基本上你应该在完成对象后立即Dispose()。不要缓存或任何东西 - GDI +资源是系统资源,应该尽快返回系统。获取它们(例如创建新的Brush类实例)应该非常快,但我现在没有任何东西支持这个声明。

答案 4 :(得分:0)

同时检查Clip Rectange in the PaintArgs event argument,这样您只需重新绘制需要更新的区域,而不是重新绘制整个图像。

答案 5 :(得分:-1)

您可以使用此代码来抑制和恢复重绘控件:] 祝你好运。

   using System;
    using System.Windows.Forms;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;

namespace pl.emag.audiopc.gui {
    // ************************************************************************
//`enter code here`
    // ************************************************************************
    public class PaintingHelper {
        // ********************************************************************
//
        // ********************************************************************
        public static void SuspendDrawing(Control parent) {
            SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
        }
        // ********************************************************************
//
        // ********************************************************************
        public static void ResumeDrawing(Control parent) {
            SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
            parent.Refresh();
        }
        // ********************************************************************
//
        // ********************************************************************
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, 
            bool wParam, Int32 lParam);
        // ********************************************************************
        //
        // ********************************************************************
        private const int WM_SETREDRAW = 11;
    }
}