ng5*_*000 296
在我之前的工作中,我们努力让我们丰富的UI应用程序能够即时,流畅地进行绘制.我们使用标准的.Net控件,自定义控件和devexpress控件.
经过大量的谷歌搜索和反射器使用后,我遇到了WM_SETREDRAW win32消息.这实际上会在您更新它们时停止控件绘制,并且可以应用于IIRC到父/包含面板.
这是一个非常简单的类,演示如何使用此消息:
class DrawingControl
{
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
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();
}
}
Run Code Online (Sandbox Code Playgroud)
有关此问题的更全面的讨论 - 谷歌的C#和WM_SETREDRAW,例如
它可能涉及到谁,这是VB中的类似示例:
Public Module Extensions
<DllImport("user32.dll")>
Private Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Boolean, ByVal lParam As IntPtr) As Integer
End Function
Private Const WM_SETREDRAW As Integer = 11
' Extension methods for Control
<Extension()>
Public Sub ResumeDrawing(ByVal Target As Control, ByVal Redraw As Boolean)
SendMessage(Target.Handle, WM_SETREDRAW, True, 0)
If Redraw Then
Target.Refresh()
End If
End Sub
<Extension()>
Public Sub SuspendDrawing(ByVal Target As Control)
SendMessage(Target.Handle, WM_SETREDRAW, False, 0)
End Sub
<Extension()>
Public Sub ResumeDrawing(ByVal Target As Control)
ResumeDrawing(Target, True)
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
cez*_*tko 52
以下是ng5000的相同解决方案,但不使用P/Invoke.
public static class SuspendUpdate
{
private const int WM_SETREDRAW = 0x000B;
public static void Suspend(Control control)
{
Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
IntPtr.Zero);
NativeWindow window = NativeWindow.FromHandle(control.Handle);
window.DefWndProc(ref msgSuspendUpdate);
}
public static void Resume(Control control)
{
// Create a C "true" boolean as an IntPtr
IntPtr wparam = new IntPtr(1);
Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
IntPtr.Zero);
NativeWindow window = NativeWindow.FromHandle(control.Handle);
window.DefWndProc(ref msgResumeUpdate);
control.Invalidate();
}
}
Run Code Online (Sandbox Code Playgroud)
Ozg*_*tak 16
我通常使用ngLink 答案的一点修改版本.
public class MyControl : Control
{
private int suspendCounter = 0;
private void SuspendDrawing()
{
if(suspendCounter == 0)
SendMessage(this.Handle, WM_SETREDRAW, false, 0);
suspendCounter++;
}
private void ResumeDrawing()
{
suspendCounter--;
if(suspendCounter == 0)
{
SendMessage(this.Handle, WM_SETREDRAW, true, 0);
this.Refresh();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这允许挂起/恢复调用.你必须确保每个都SuspendDrawing与a 匹配ResumeDrawing.因此,公开它们可能不是一个好主意.
小智 13
为了帮助不忘记重新绘图:
public static void SuspendDrawing(Control control, Action action)
{
SendMessage(control.Handle, WM_SETREDRAW, false, 0);
action();
SendMessage(control.Handle, WM_SETREDRAW, true, 0);
control.Refresh();
}
Run Code Online (Sandbox Code Playgroud)
用法:
SuspendDrawing(myControl, () =>
{
somemethod();
});
Run Code Online (Sandbox Code Playgroud)
不使用互操作的好方案:
与往常一样,只需在CustomControl上启用DoubleBuffered = true即可.然后,如果您有任何容器,如FlowLayoutPanel或TableLayoutPanel,从这些类型和构造函数中派生类,则启用双缓冲.现在,只需使用派生的容器而不是Windows.Forms容器.
class TableLayoutPanel : System.Windows.Forms.TableLayoutPanel
{
public TableLayoutPanel()
{
DoubleBuffered = true;
}
}
class FlowLayoutPanel : System.Windows.Forms.FlowLayoutPanel
{
public FlowLayoutPanel()
{
DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
基于ng5000的答案,我喜欢使用以下扩展名:
#region Suspend
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
public static IDisposable BeginSuspendlock(this Control ctrl)
{
return new suspender(ctrl);
}
private class suspender : IDisposable
{
private Control _ctrl;
public suspender(Control ctrl)
{
this._ctrl = ctrl;
SendMessage(this._ctrl.Handle, WM_SETREDRAW, false, 0);
}
public void Dispose()
{
SendMessage(this._ctrl.Handle, WM_SETREDRAW, true, 0);
this._ctrl.Refresh();
}
}
#endregion
Run Code Online (Sandbox Code Playgroud)
使用:
using (this.BeginSuspendlock())
{
//update GUI
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100690 次 |
| 最近记录: |