Здравствуйте, thespian, Вы писали:
T>Как получить размеры области рисования на форме. Form.Size — даёт размеры всего окна, а мне нужно только клиентской области.
T>Заранее спасибо
Здравствуйте, BLR, Вы писали:
BLR>Здравствуйте, thespian, Вы писали:
T>>Как получить размеры области рисования на форме. Form.Size — даёт размеры всего окна, а мне нужно только клиентской области.
T>>Заранее спасибо
BLR> для размера клиентской области ClientRectangle.
Как можно в памяти создать канву (много квадратиков), и отобразить её на форму?
Здравствуйте, thespian, Вы писали:
T>Здравствуйте, BLR, Вы писали:
BLR>>Здравствуйте, thespian, Вы писали:
T>>>Как получить размеры области рисования на форме. Form.Size — даёт размеры всего окна, а мне нужно только клиентской области.
T>>>Заранее спасибо
BLR>> для размера клиентской области ClientRectangle.
T>Как можно в памяти создать канву (много квадратиков), и отобразить её на форму?
Отрисовать на bitmap и потом выводи хоть на принтер хоть на экран.
Здравствуйте, thespian, Вы писали:
T>Здравствуйте, viknet, Вы писали:
V>>Отрисовать на bitmap и потом выводи хоть на принтер хоть на экран.
T>Это я понимаю и уже второй день мучаюсь. Можно небольшой примерчик рисования на битмапе в C#?
Спасибо за пример. Очень содержательный.
Я его попробовал, но всё-таки не добился цели. Как в дотнете быстро выводить графику на канву? (уж сильно мерцает).
Здравствуйте, thespian, Вы писали:
T>Здравствуйте, Ael.
T>Спасибо за пример. Очень содержательный. T>Я его попробовал, но всё-таки не добился цели. Как в дотнете быстро выводить графику на канву? (уж сильно мерцает).
А какая задача, почему надо рисовать именно на битмапе, и какой код мерцает?
Здравствуйте, Ael, Вы писали:
Ael>А какая задача, почему надо рисовать именно на битмапе, и какой код мерцает?
Я просто пробовал рисовать анимацию на C# .Net, при анимировании 20 эллипсов — началось мерцание. Я решил разрисововать это в памяти, а потом всё выводить на экран — не помогло. Каким образом это всё можно сгладить?
П.С.: вопрос по примеру, почему компилятор на GraphicsPath выдаёт ошибку? Что надо прописать в using?
Здравствуйте, 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;
T> А теоретически какие-либо методы рисования плоской анимации (игр) есть на дотнете.
Игрушки типа пасьянса и тетриса нормально будут работать на System.Drawing. Гонки и Postal 2, конечно, так не получится. Кстати, скоро в RSDN Magazine будет моя статья с игрушкой как раз вроде тетриса.
Всё работает достаточно быстро, если аккуратно реализовать. Одна из основных мыслей — рисовать только в OnPaint и только ту область, которая должна быть перерисована. А для события перерисовки использовать Invalidate. Тогда никогда не будет проблем с мельканием.
Ну и, конечно, кешировать всё по максимуму. Битмапы тех же самых карт, кисти, фонты.
T>Например, как BitBlt в Win32?
Graphics.DrawImage отлично работает. Одна беда — нельзя нарисовать картинку саму в себя. Это действительно неудобно.
P.S. В следующей версии .NET V2 кроме GDI+ будет поддерживаться и старый GDI. Теоретически он должен работать немного быстрее.
[skipped]
M>Всё работает достаточно быстро, если аккуратно реализовать. Одна из основных мыслей — рисовать только в OnPaint и только ту область, которая должна быть перерисована. А для события перерисовки использовать Invalidate. Тогда никогда не будет проблем с мельканием.
[skipped]
Знаю, это уже обсуждалось, но хотелось бы прояснить. Согласен, что лучше всегда рисовать только в OnPaint и для перерисовки вызывать Invalidate. Но — посмотрите вот эти два простых примера — сравненияздесь
Вопрос — согласны ли с тем, что в случае, когда, как в этом, перерисовка постоянно и незначительных деталей в разных местах контрола — более производительно как раз рисовать не в OnPaint-е?
Ael>Вопрос — согласны ли с тем, что в случае, когда, как в этом, перерисовка постоянно и незначительных деталей в разных местах контрола — более производительно как раз рисовать не в OnPaint-е?
Да, конечно.
К сожалению, OnPaint получает ClipRectangle, а не ClipRegion.