我编写了一个自定义控件来渲染一些图形。渲染图形本身相当昂贵,但一旦渲染它很少改变。我遇到的问题是,如果你在图形表面上快速移动鼠标,它会一直调用控件的重写Paint方法,这会导致高CPU损失:
private void UserControl1_Paint(object sender,PaintEventArgs e)
可以使用哪些技术来避免这种情况或最小化任何不必要的重绘,因为鼠标指针下面的图形/图像实际上没有变化?
答案 0 :(得分:3)
编辑:在看到您的编辑后,我可以向您保证,当鼠标移动到控件上时,默认情况下不会调用OnPaint。代码中的某些东西肯定会导致重新绘制,你只是还没有看到它。也许发布一些代码可以帮助我们找到问题。
您是否在MouseMove上使控件无效?这可能是一个坏主意,如果你真的需要这样做(即,你正在制作一个图形编辑器或其他东西),你必须聪明一个区域实际重新绘制的大小。所以,解决方案;不要在MouseMove中绘制控件。
否则,当鼠标移动到控件上时,我不希望OnPaint触发。您也可以只生成一次图像,然后将其blt到Graphics对象,直到需要重新生成。
答案 1 :(得分:2)
您可以使用缓冲图像在更改内容时绘制,在Paint方法中只需复制屏幕上的图像。应该很快。您还可以使用剪辑区域仅复制需要更新的部分。这应该会降低CPU使用率。
如果需要,您还可以使用IsDirty标志来了解何时更新缓冲区图像(即完全重绘)。
答案 2 :(得分:2)
您不应直接致电Paint
。
相反,请致电Invalidate
(Control.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;
}
}