Здравствуйте, thespian, Вы писали:
T>Здравствуйте, Ael, Вы писали:
Ael>>А какая задача, почему надо рисовать именно на битмапе, и какой код мерцает?
T>Я просто пробовал рисовать анимацию на C# .Net, при анимировании 20 эллипсов — началось мерцание. Я решил разрисововать это в памяти, а потом всё выводить на экран — не помогло. Каким образом это всё можно сгладить?
Посмотрите вот такой пример:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.ComponentModel;
public class Form1 : System.Windows.Forms.Form
{
private Bitmap _hBitmap;
private volatile Boolean _bFinish;
const Int32 iNumber=30;
public Form1()
{
Int32 _iWidth=this.Width/iNumber;
Int32 _iHeight=this.Height/iNumber;
_hBitmap=new Bitmap(_iWidth,_iHeight);
using(Graphics gr=Graphics.FromImage(_hBitmap))
{
using (SolidBrush sBrush=new SolidBrush(Color.Green))
{
gr.Clear(Color.FromArgb(0,255,255,255));
gr.FillEllipse(sBrush,0,0,_iWidth,_iHeight);
}
}
Thread t=new Thread(new ThreadStart(this.Animation));
t.IsBackground=true;
t.Start();
this.Closing+=new CancelEventHandler(Form1_Closing);
}
private void Animation()
{
Thread.Sleep(100);
Random rand=new Random(DateTime.Now.Millisecond);
Int32 cX=0,cY=0;
while (!_bFinish)
{
using (Graphics g=this.CreateGraphics())
{
using (Brush brushErase=new SolidBrush(this.BackColor))
{
for(cX=0;cX<this.Width;cX+=iNumber)
for (cY=0;cY<this.Height&&!_bFinish;cY+=iNumber)
{
if(rand.Next()%2==0)
g.DrawImage(this._hBitmap,cX,cY,iNumber,iNumber);
else
g.FillRectangle(brushErase,cX,cY,iNumber,iNumber);
}
Thread.Sleep(100);
}
}
}
}
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Closing(object sender, CancelEventArgs e)
{
this._bFinish=true;
}
}
Хотя по правилам нужно рисовать только в OnPaint. Можно переписать пример, чтобы он использовал делегат и вызывал OnPaint для выполнения в основном потоке. Это будет медленнее (появится мерцание), так что мне нравится больше
пример выше.
using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
public delegate void PaintCallback(Rectangle rectClip);
public class Form1 : System.Windows.Forms.Form
{
private Bitmap _hBitmap;
private volatile Boolean _bDraw,_bFinish;
const Int32 iNumber=30;
private PaintCallback _pc;
public Form1()
{
Int32 _iWidth=this.Width/iNumber;
Int32 _iHeight=this.Height/iNumber;
_hBitmap=new Bitmap(_iWidth,_iHeight);
using(Graphics gr=Graphics.FromImage(_hBitmap))
{
using (SolidBrush sBrush=new SolidBrush(Color.Green))
{
gr.Clear(Color.FromArgb(0,255,255,255));
gr.FillEllipse(sBrush,0,0,_iWidth,_iHeight);
}
}
this._pc=new PaintCallback(this.InvalidateUpdate);
Thread t=new Thread(new ThreadStart(this.Animation));
t.IsBackground=true;
t.Start();
this.Closing+=new CancelEventHandler(Form1_Closing);
}
private void InvalidateUpdate(Rectangle rectClip)
{
if(!this._bFinish)
{
this.Invalidate(rectClip);
this.Update();
_bDraw=false;
}
}
protected override void OnPaint(PaintEventArgs e)
{
if (_bDraw)
e.Graphics.DrawImage(_hBitmap,e.ClipRectangle);
base.OnPaint (e);
}
private void Animation()
{
Thread.Sleep(100);
Random rand=new Random(DateTime.Now.Millisecond);
Int32 cX=0,cY=0;
while (!_bFinish)
{
using (Graphics g=this.CreateGraphics())
{
using (Brush brushErase=new SolidBrush(this.BackColor))
{
for(cX=0;cX<this.Width;cX+=iNumber)
for (cY=0;cY<this.Height&&!_bFinish;cY+=iNumber)
{
if(rand.Next()%2==0)
this._bDraw=true;
this.BeginInvoke(this._pc,new Object[]{new Rectangle(cX,cY,iNumber,iNumber)});
}
Thread.Sleep(100);
}
}
}
}
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Closing(object sender, CancelEventArgs e)
{
this._bFinish=true;
}
}
Кстати, если в битмапе обычный кружок, или там кружок и линии, то быстрее будет не рисовать это в битмап, а потом выводить битмап, а рисовать фигуры заново.С битмапом выигрываешь, если в битмапе — картинка.
T>П.С.: вопрос по примеру, почему компилятор на GraphicsPath выдаёт ошибку? Что надо прописать в using?
using System.Drawing.Drawing2D;