如何在 C# 中停止/暂停表单绘制?
Posted
技术标签:
【中文标题】如何在 C# 中停止/暂停表单绘制?【英文标题】:How to stop/suspend a form from painting in C#? 【发布时间】:2013-09-13 08:00:55 【问题描述】:我正在尝试弄清楚如何阻止表格在屏幕上绘画。我的意思是当我启动表单时,它不会最终绘制表单,因此不会显示界面。
我知道如何使用控件执行此操作,但我不知道如何使用表单。我正在考虑发送一条消息来阻止它进行绘制将是最好的选择,尽管我不确定哪个消息会创建初始绘制工作。
以下是如何暂停绘制控件。
using System.Runtime.InteropServices;
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();
【问题讨论】:
那么,这段代码有什么不好的地方?另外,您是否尝试过覆盖OnPaint
方法?
致电SuspendDrawing(yourForm);
就这样
感谢您的回复。我实际上已经尝试过,尽管它仍然在屏幕上绘制表单,除了控件。
【参考方案1】:
几个标准控件处理 WM_SETREDRAW。它们不会停止绘画,而是会在您添加新项目或更改文本时停止刷新窗口。
这不是其他规定的行为,每个控件都以它认为合适的方式解释该消息。 Form 和 Control 类没有内置任何改变它们绘制方式的逻辑。您必须自己实施。您不会使用消息处理程序 (WndProc) 这样做,您只需添加一个 bool 类型的公共属性。并且,例如,当 OnPaint 方法设置为 false 时,不绘制任何内容。等等。阻止父重绘自己是不行的,不清楚你为什么要考虑这个。
【讨论】:
感谢汉斯的洞察力。我尝试这样做的原因是我可以将表单绘制到缓冲区而不是屏幕上。我知道,当您将表单设置为双缓冲区时,它首先绘制到缓冲区,然后将图像从缓冲区复制到屏幕上。我希望我能找到一种方法让它绘制到缓冲区,然后阻止它绘制到屏幕上。所以我可以访问缓冲区而无需将其绘制到屏幕表面。 这已经是内置的了,只需在构造函数中将DoubleBuffered属性设置为true即可。使整个表单及其所有控件双缓冲需要一点extra magic。我不得不说,与您的问题相距甚远。 这就是我所说的,我知道.net 具有内置的双缓冲功能,这就是我想利用的功能,但是当您在构造函数中将其设置为双缓冲时,它会绘制绘制到缓冲区后屏幕上的窗口。 (就像它应该的那样,它毕竟是双缓冲。)我想阻止它在绘制到缓冲区后在屏幕上绘制表单。 这没什么意义,双缓冲是为了缓冲画面到屏幕上。如果要绘制位图,则必须使用 Control.DrawToBitmap()。 我知道双缓冲就是为了这个,但帧缓冲在其他用途中很常见。我想我可以利用内置的双缓冲功能并阻止它在屏幕上绘画。所以基本上它只是作为一个帧缓冲区。我想利用内置 Dbuffering 的原因是因为它首先绘制到虚拟/后台缓冲区,然后在屏幕上绘制。所以这意味着它首先在屏幕外绘制表单。我不知道有任何其他方法可以将屏幕外的表单绘制到缓冲区中,因此我可以从客户端类型的应用程序访问表单。【参考方案2】:我找到了问题的答案。就像发送一条消息以阻止绘画发生并将其添加到 InitializeComponent() 和 OnPaint() 一样简单。
将它添加到 InitializeComponent() 将绘制表单,但会立即暂停它。仅将其添加到 onPaint 似乎无济于事,因此两者兼而有之。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication11
public partial class Form1 : Form
public Form1()
InitializeComponent();
SuspendDrawing(this);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg,
bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
private const int WM_PAINT = 0xf;
private const int WM_CREATE = 0x1;
public static void SuspendDrawing(Form parent)
SendMessage(parent.Handle, WM_PAINT, false, 0);
public static void ResumeDrawing(Form parent)
SendMessage(parent.Handle, WM_PAINT, true, 0);
// parent.Refresh();
protected override void OnPaint(PaintEventArgs e)
SuspendDrawing((this));
【讨论】:
【参考方案3】:this.SuspendLayout
(https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.suspendlayout?view=windowsdesktop-6.0) 和 this.ResumeLayout(false)
或 this.ResumeLayout(true)
(https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.resumelayout?view=windowsdesktop-6.0#System_Windows_Forms_Control_ResumeLayout) 可能是您正在寻找的。p>
【讨论】:
以上是关于如何在 C# 中停止/暂停表单绘制?的主要内容,如果未能解决你的问题,请参考以下文章