关于Form.Paint事件绘制缓慢问题

pywepe 2012-04-03 04:44:30
先上代码:

private void Screenshot() {

Image myImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(myImg);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);
//SendKeys.Send("{PRTSC}");

//Form form = new MyForm();
Form form = new Form();
form.FormBorderStyle = FormBorderStyle.None;
form.BackgroundImage = myImg; // 截取的图片作为Form的背景图片
form.Size = new System.Drawing.Size(myImg.Size.Width, myImg.Size.Height);

form.Paint += new PaintEventHandler(delegate(object sender,PaintEventArgs args){
Graphics gg = args.Graphics;

Image offsetScr = new Bitmap(args.ClipRectangle.Width, args.ClipRectangle.Height);
Graphics srcG = Graphics.FromImage(offsetScr);

Color c = Color.FromArgb(150, 0, 0, 0);
Brush brush = new SolidBrush(c);
srcG.FillRectangle(brush, args.ClipRectangle);
brush.Dispose();
srcG.Dispose();

gg.DrawImage(offsetScr, args.ClipRectangle);
offsetScr.Dispose();

Console.WriteLine("OnPaint");
});

form.KeyDown += new KeyEventHandler(delegate(object sender, KeyEventArgs args)
{
if (args.KeyCode == Keys.Escape)
{
form.Hide();
form.Dispose();
}
else if (args.KeyCode == Keys.S && args.Control) {
SaveFileDialog sd = new SaveFileDialog();
sd.InitialDirectory = ".";
sd.Filter = "PNG图片|*.png";
DialogResult r = sd.ShowDialog();
if (r == DialogResult.OK)
{
myImg.Save(sd.FileName, System.Drawing.Imaging.ImageFormat.Png);

}
}
});

form.Show();

/*
Panel p = new Panel();
p.Dock = DockStyle.Fill;
p.BackColor = Color.FromArgb(150, 0, 0, 0);
p.Paint += new PaintEventHandler(delegate(object sender,PaintEventArgs args){
Console.WriteLine("on paint");
});
form.Controls.Add(p);
*/

}


主要是这一段代码:
form.Paint += new PaintEventHandler(delegate(object sender,PaintEventArgs args){
Graphics gg = args.Graphics;
// 这里有一个双缓冲,不用又缓冲效果也是一样的

Image offsetScr = new Bitmap(args.ClipRectangle.Width, args.ClipRectangle.Height);
Graphics srcG = Graphics.FromImage(offsetScr);

Color c = Color.FromArgb(150, 0, 0, 0);
Brush brush = new SolidBrush(c);
srcG.FillRectangle(brush, args.ClipRectangle);
brush.Dispose();
srcG.Dispose();

gg.DrawImage(offsetScr, args.ClipRectangle);
offsetScr.Dispose();

Console.WriteLine("OnPaint");
});

截取的图片作为Form的背景图片,然后再在背景图片之上绘制一个半透明的矩形,以达到类似QQ截图的效果.

可是,当程序显示这个Form时,半透明的矩形是从上到下慢慢绘制的,并不是一次性完全显示.
上一个图说明这个过程:








可以确定的是这个Paint事件在Form显示的时候只触发了一次,因数只打印了一次OnPaint.
为什么矩形不是一次性绘制完成的呢?
怎么样才能达到一次性绘制完成的效果呢?

请大家不吝赐教


...全文
233 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
pywepe 2012-04-03
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

C# code

private void Screenshot()
{
new MyScreenCapturer().ShowDialog();
}
class MyScreenCapturer : Form
{
Bitmap myImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.……
[/Quote]

同样有问题
orochiheart 2012-04-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
问题已得到解决,谢谢大家.
是没有双缓冲导致的,Form.DoubleBuffered = true 就没问题了
[/Quote]
留个痕迹
gomoku 2012-04-03
  • 打赏
  • 举报
回复

private void Screenshot()
{
new MyScreenCapturer().ShowDialog();
}
class MyScreenCapturer : Form
{
Bitmap myImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
public MyScreenCapturer()
{
using (Graphics g = Graphics.FromImage(myImg))
{
g.CopyFromScreen(Point.Empty, Point.Empty, Screen.PrimaryScreen.Bounds.Size);
}
this.FormBorderStyle = FormBorderStyle.None;
this.Size = Screen.PrimaryScreen.Bounds.Size;
}
protected override void OnPaintBackground(PaintEventArgs e){/* do nothing */}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImageUnscaled(myImg, Point.Empty);
using (Brush brush = new SolidBrush(Color.FromArgb(150, 0, 0, 0)))
{
Region mask = new Region(this.Bounds); mask.Exclude(this.GetSelection());
e.Graphics.Clip = mask;
e.Graphics.FillRectangle(brush, 0, 0, myImg.Width, myImg.Height);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
this.mouseDown = this.mouseMove = e.Location;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (this.Capture)
{
Rectangle last = GetSelection();
mouseMove = e.Location;
this.Invalidate(Rectangle.Union(last, GetSelection()));
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
Rectangle rect = this.GetSelection();
if (rect.Size != Size.Empty)
{
SaveFileDialog sd = new SaveFileDialog() {Filter = "PNG图片|*.png"};
if (sd.ShowDialog() == DialogResult.OK)
{
myImg.Clone(rect, myImg.PixelFormat).Save(sd.FileName, System.Drawing.Imaging.ImageFormat.Png);
}
this.Close();
}
}
private Rectangle GetSelection()
{
Point location = new Point(Math.Min(mouseDown.X, mouseMove.X), Math.Min(mouseDown.Y, mouseMove.Y));
Size size = new Size(Math.Abs(mouseDown.X - mouseMove.X), Math.Abs(mouseDown.Y - mouseMove.Y));
return new Rectangle(location, size);
}
Point mouseDown, mouseMove;
}
pywepe 2012-04-03
  • 打赏
  • 举报
回复
问题已得到解决,谢谢大家.
是没有双缓冲导致的,Form.DoubleBuffered = true 就没问题了
足球中国 2012-04-03
  • 打赏
  • 举报
回复
java代码书写方式弄到c#里看着特别。
args.ClipRectangle.Width, args.ClipRectangle.Height 应该这个地方有问题。
bdmh 2012-04-03
  • 打赏
  • 举报
回复
你在什么时候触发的OnPaint事件,或许跟你的触发条件有关系,如果矩形是逐步形成的,那肯定会多次调用OnPaint,你看看ClipRectangle这个东西是怎样的

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧