C#自定义图片框控件
C# custom picturebox control
我从事的项目需要不断获取位图并将其绘制在图片框上。
想法是绘制第一个初始位图,然后检索位图的其余部分并将它们绘制在初始位图之上。 (第一个仍然显示在图片框中,所以我想把它们画在第一个位图上)。
我试图设计一个自定义控件来实现 OnPaint
事件,但是第二次触发该事件时,它绘制了第二个 block
并完全隐藏了已经绘制的图像之前。
public class RapidPictureBox: PictureBox
{
public pictureBox1Control()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public Bitmap block = null;
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(block, x, y);
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = new Bitmap("3.png"); //first initial image
pictureBox1.block = new Bitmap("2.png"); //draw on the initial one.
}
我不确定代码中有什么问题。每次我需要时,我都会使用 e
EventArgs 绘制一个新块,但新绘图似乎完全隐藏了以前的位图。
您的代码存在问题,您没有将图片添加到正在替换它们的控件中。
旁注:使用您拥有的代码,您不会处理 PictureBox
es 图像中设置的 Bitmap
对象,因此这可能会导致内存泄漏。
您可以创建一个类似的控件LayeredPictureBox
。这将获取所有图像并将它们绘制在彼此之上。它的性能会很差,图像需要有透明度才能看起来有层次感,但你明白了:
public class LayeredPictureBox : PictureBox
{
public LayeredPictureBox()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public List<Bitmap> blocks = new List<Bitmap>();
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
foreach (Bitmap block in blocks)
{
e.Graphics.DrawImage(block, x, y);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.blocks.Add(new Bitmap("3.png")); //first initial image
pictureBox1.blocks.Add(new Bitmap("2.png")); //draw on the initial one.
}
另一种选择是在添加图像时将所有图像合并在一起,然后将该图像绘制到 PictureBox 中。
您应该做的是将新图像叠加在先前图像上。
假设有一个主图像(第一张图像)并且您想要在同一个主图像上打印下一个图像(重叠图像)。使用以下方法来做到这一点。
private Bitmap GetOvelappedImages(Bitmap primaryImage, Bitmap overlappingImage)
{
//create graphics from main image
using (Graphics g = Graphics.FromImage(primaryImage))
{
//draw other image on top of main Image
g.DrawImage(overlappingImage, new Point(0, 0));
}
return primaryImage;
}
然后将此新图像设置为 pictureBox1.block。
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = GetOverlappedImages(new Bitmap("3.png"),new Bitmap("2.png")); //draw on the initial one.
}
这应该适合你。
注意:图片用完后请处理掉
更新:
您需要重绘整个图像,因为只有当图片框上显示的当前图像需要重绘时才会调用 OnPaint。
每次绘制窗体时重写OnPaint方法重新绘制图像;否则图像只会持续到下一次重绘。
阅读 OnPaint 的文档 here
您可以从图片框创建一个图形对象,然后在当前图像上重新绘制它
initial =new Bitmap("test.png");
pictureBox1.Image = initial;
var graphics = pictureBox1.CreateGraphics(); //create a graphic objec
graphics.DrawImage(block, x,y);//that's the second method
我从事的项目需要不断获取位图并将其绘制在图片框上。
想法是绘制第一个初始位图,然后检索位图的其余部分并将它们绘制在初始位图之上。 (第一个仍然显示在图片框中,所以我想把它们画在第一个位图上)。
我试图设计一个自定义控件来实现 OnPaint
事件,但是第二次触发该事件时,它绘制了第二个 block
并完全隐藏了已经绘制的图像之前。
public class RapidPictureBox: PictureBox
{
public pictureBox1Control()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public Bitmap block = null;
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(block, x, y);
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = new Bitmap("3.png"); //first initial image
pictureBox1.block = new Bitmap("2.png"); //draw on the initial one.
}
我不确定代码中有什么问题。每次我需要时,我都会使用 e
EventArgs 绘制一个新块,但新绘图似乎完全隐藏了以前的位图。
您的代码存在问题,您没有将图片添加到正在替换它们的控件中。
旁注:使用您拥有的代码,您不会处理 PictureBox
es 图像中设置的 Bitmap
对象,因此这可能会导致内存泄漏。
您可以创建一个类似的控件LayeredPictureBox
。这将获取所有图像并将它们绘制在彼此之上。它的性能会很差,图像需要有透明度才能看起来有层次感,但你明白了:
public class LayeredPictureBox : PictureBox
{
public LayeredPictureBox()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public List<Bitmap> blocks = new List<Bitmap>();
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
foreach (Bitmap block in blocks)
{
e.Graphics.DrawImage(block, x, y);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.blocks.Add(new Bitmap("3.png")); //first initial image
pictureBox1.blocks.Add(new Bitmap("2.png")); //draw on the initial one.
}
另一种选择是在添加图像时将所有图像合并在一起,然后将该图像绘制到 PictureBox 中。
您应该做的是将新图像叠加在先前图像上。 假设有一个主图像(第一张图像)并且您想要在同一个主图像上打印下一个图像(重叠图像)。使用以下方法来做到这一点。
private Bitmap GetOvelappedImages(Bitmap primaryImage, Bitmap overlappingImage)
{
//create graphics from main image
using (Graphics g = Graphics.FromImage(primaryImage))
{
//draw other image on top of main Image
g.DrawImage(overlappingImage, new Point(0, 0));
}
return primaryImage;
}
然后将此新图像设置为 pictureBox1.block。
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = GetOverlappedImages(new Bitmap("3.png"),new Bitmap("2.png")); //draw on the initial one.
}
这应该适合你。
注意:图片用完后请处理掉
更新: 您需要重绘整个图像,因为只有当图片框上显示的当前图像需要重绘时才会调用 OnPaint。 每次绘制窗体时重写OnPaint方法重新绘制图像;否则图像只会持续到下一次重绘。 阅读 OnPaint 的文档 here
您可以从图片框创建一个图形对象,然后在当前图像上重新绘制它
initial =new Bitmap("test.png");
pictureBox1.Image = initial;
var graphics = pictureBox1.CreateGraphics(); //create a graphic objec
graphics.DrawImage(block, x,y);//that's the second method