Foreach循环创建100个按钮,同时绘制所有按钮以防止闪烁

在我的扫雷游戏中,我需要动态创建控件,以便在easy – medium – hard之间切换。 让我们说,为了问题,硬包含100个按钮。

这就是我创建它们的方式:

this.SuspendLayout(); //Creating so many things that I assume it would be faster to suspend and resume. foreach (string i in playingField) { Button button = new Button(); button.Name = i; button.FlatStyle = System.Windows.Forms.FlatStyle.Popup; button.Margin = new Padding(0); button.TabIndex = 0; button.Location = new System.Drawing.Point(3, 3); button.Size = new System.Drawing.Size(25, 25); button.BackgroundImage = blockImage; //##// button.MouseDown += new System.Windows.Forms.MouseEventHandler(this.GetUnderSide); button.UseVisualStyleBackColor = false; minesPanel.Controls.Add(button); //Adding the controls to the container } this.ResumeLayout(); //Refer to above. Correct me if I'm wrong please. 

正如您所看到的,我通过for循环创建所有控件,然后添加它们。 它导致每个按钮一次被绘制一次。 我也尝试过name.Controls.AddRange(arrayButtons) ,它仍然导致了同样的问题。 个人绘画。

我需要的是一种创建所有项目的方法,然后将它们绘制成ALL,就像使用DoubleBuffered绘制单个位图DoubleBuffered ,但是唉,这也不起作用。

此外,我试过这个:

  protected override CreateParams CreateParams { get { // Activate double buffering at the form level. All child controls will be double buffered as well. CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED return cp; } } 

哪种作品。 它仅适用于应用程序启动。 但是,考虑到我将在运行时更改网格大小并添加更多控件,这不是一个可行的选择。

我被告知它就像使用Graphics类中的方法一样简单。 问题是,我不知道从哪里开始。

如果有人可以提供一些帮助我同时绘制所有控件,那就太好了。

可悲的是,WinForms不喜欢有太多的控件,特别是当你进入数百个时。 由于每个控件都会向窗口发送自己的绘制消息,因此您永远不能同时拥有每个控件。

我认为接近像MineSweeper这样的游戏板的最佳方法是使用一个控件并绘制按钮网格。

简单的矿类:

 public class Mine { public Rectangle Bounds { get; set; } public bool IsBomb { get; set; } public bool IsRevealed { get; set; } } 

然后创建一个新控件,从Panel控件inheritance并设置DoubleBuffered属性以防止任何闪烁:

 public class MineSweeperControl : Panel { private int columns = 16; private int rows = 12; private Mine[,] mines; public MineSweeperControl() { this.DoubleBuffered = true; this.ResizeRedraw = true; // initialize mine field: mines = new Mine[columns, rows]; for (int y = 0; y < rows; ++y) { for (int x = 0; x < columns; ++x) { mines[x, y] = new Mine(); } } } // adjust each column and row to fit entire client area: protected override void OnResize(EventArgs e) { int top = 0; for (int y = 0; y < rows; ++y) { int left = 0; int height = (this.ClientSize.Height - top) / (rows - y); for (int x = 0; x < columns; ++x) { int width = (this.ClientSize.Width - left) / (columns - x); mines[x, y].Bounds = new Rectangle(left, top, width, height); left += width; } top += height; } base.OnResize(e); } protected override void OnPaint(PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; for (int y = 0; y < rows; ++y) { for (int x = 0; x < columns; ++x) { if (mines[x, y].IsRevealed) { e.Graphics.FillRectangle(Brushes.DarkGray, mines[x, y].Bounds); } else { ControlPaint.DrawButton(e.Graphics, mines[x, y].Bounds, ButtonState.Normal); } } } base.OnPaint(e); } // determine which button the user pressed: protected override void OnMouseDown(MouseEventArgs e) { for (int y = 0; y < rows; ++y) { for (int x = 0; x < columns; ++x) { if (mines[x, y].Bounds.Contains(e.Location)) { mines[x, y].IsRevealed = true; this.Invalidate(); MessageBox.Show( string.Format("You pressed on button ({0}, {1})", x.ToString(), y.ToString()) ); } } } base.OnMouseDown(e); } } 

在此处输入图像描述

隐藏minesPanel ,绘制你的按钮,显示minesPanel