FlickerFree - 使用 GDI+ 创建无闪烁图形






4.25/5 (11投票s)
2002年11月15日
1分钟阅读

83013

668
演示如何使用 GDI+ 创建无闪烁图形的代码示例。
引言
首先我想说:“对不起我的拼写不好 - 但我会努力改进!”
在使用 GDI+ 创建移动对象/图形时,每次计时器滴答时都必须刷新屏幕 :-) 但这样图形就会闪烁 - 为了避免这种情况,可以使用双缓冲。在这个示例中,我将展示您需要什么才能实现无闪烁图形,以及如何使用 KeyEvent
。
使用代码
我使用了一个间隔为 40 毫秒的计时器,因为我们需要大约每秒 25 帧 (1000 毫秒 / 25 帧 = 40)。为了演示如何移动图形对象,我还内置了 KeyEvent
。
首先,您需要在类的构造函数中设置双缓冲
SetStyle(ControlStyles.DoubleBuffer, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);
然后我们使用计时器每 40 毫秒刷新一次窗体
private System.Windows.Forms.Timer t; t = new Timer(); t.Interval = 40; t.Tick += new System.EventHandler(TimerOnTick); t.Enabled = true; private void TimerOnTick(object sender, System.EventArgs e) { this.Refresh(); // #### 84: Refresh the form this.Text = DateTime.Now.ToString(); this.Text += " " + this.PlayerPosition.ToString(); }
接下来我们“监听”我们的键盘
this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyPress); private void OnKeyPress(object sender, System.Windows.Forms.KeyEventArgs e) { // #### 84: When the Left-Cursor has been pressed if(e.KeyValue == 37) { this.PlayerPosition = new Point(this.PlayerPosition.X - this.playerSize.Width, this.PlayerPosition.Y); } // #### 84: When the Up-Cursor has been pressed if(e.KeyValue == 38) { this.PlayerPosition = new Point(this.PlayerPosition.X, this.PlayerPosition.Y - this.playerSize.Width); } // #### 84: When the Right-Cursor has been pressed if(e.KeyValue == 39) { this.PlayerPosition = new Point(this.PlayerPosition.X + this.playerSize.Height, this.PlayerPosition.Y); } // #### 84: When the Down-Cursor has been pressed if(e.KeyValue == 40) { this.PlayerPosition = new Point(this.PlayerPosition.X, this.PlayerPosition.Y + this.playerSize.Height); } }
并且我们必须重写 OnPaint
事件来绘制我们的对象
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { e.Graphics.FillRectangle(new SolidBrush(Color.Red), this.PlayerPosition.X, this.PlayerPosition.Y, this.playerSize.Width, this.playerSize.Height); }
为了计算我们的图形对象的新位置是否在客户端区域内,以及如果不在该区域内该怎么办,我使用了一个属性
private Point PlayerPosition { get { return this.playerPosition; } set { if(value.X < 0) { this.playerPosition.X = this.ClientSize.Width - this.playerSize.Width; } else if(value.X + this.playerSize.Width > this.ClientSize.Width) { this.playerPosition.X = 0; } else { this.playerPosition.X = value.X; } if(value.Y < 0) { this.playerPosition.Y = this.ClientSize.Height - this.playerSize.Height; } else if(value.Y + this.playerSize.Height > this.ClientSize.Height) { this.playerPosition.Y = 0; } else { this.playerPosition.Y = value.Y; } } }
现在我们有了无闪烁的动画 ;-)
关注点
在我的示例的第一个版本中,我使用了 if()
- else if()
来处理 KeyEvent
。但那样一次只能使用一个键。使用 if()
处理每个键可以组合键以进行对角线移动。同样重要的是使用 this.Client.Width
和 this.Client.Height
而不是 this.Width
和 this.Height
- 因为图形对象只能在客户端区域内移动,因此您可以计算移动的区域。