【发布时间】:2015-03-03 11:36:00
【问题描述】:
如何保存我在图片框上绘制的画作?
我画了一个圆圈,并通过 ExtFloodFill API 填充它。 这很好用。
当我调整表单大小(或最小化它)并将其调整回原来的大小时,绘画的一部分消失了。
当我刷新图片框时,绘画将完全消失
我试图在 Paint 事件中重新绘制它,但这会导致它不断地重新绘制,因为绘画本身也触发了 Paint 事件。
请参阅下面的测试项目。
- 当您点击图片框时,绘画将被绘制出来。
- 双击图片框时会刷新。
[1 个表格和 1 个名为 pictureBox1 的图片框]
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace FloodFill
{
public partial class Form1 : Form
{
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateSolidBrush(int crColor);
[DllImport("gdi32.dll")]
public static extern bool ExtFloodFill(IntPtr hdc, int nXStart, int nYStart, int crColor, uint fuFillType);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern int GetPixel(IntPtr hdc, int x, int y);
public static uint FLOODFILLSURFACE = 1;
public Form1()
{
InitializeComponent();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
DrawCircle();
FillGreen();
}
private void DrawCircle()
{
Graphics graBox = Graphics.FromHwnd(pictureBox1.Handle);
graBox.DrawEllipse(Pens.Red, 10, 10, 100, 100);
}
private void FillGreen()
{
Graphics graBox = Graphics.FromHwnd(pictureBox1.Handle);
IntPtr ptrHdc = graBox.GetHdc();
IntPtr ptrBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Green));
SelectObject(ptrHdc, ptrBrush);
ExtFloodFill(ptrHdc, 50, 50, GetPixel(ptrHdc, 50, 50), FLOODFILLSURFACE);
DeleteObject(ptrBrush);
graBox.ReleaseHdc(ptrHdc);
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
pictureBox1.Refresh();
}
}
}
当我的表单或图片框被调整大小或以任何其他方式刷新时,我如何保存我所做的绘画?
[编辑]
我将我的 Paint 事件更改为以下内容:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
DrawCircle();
FillGreen();
}
现在圆圈在调整大小后被重新绘制,但 FloodFill 不是
(我还为图片框设置了浅蓝色背景以进行另一次测试)
[EDIT2]
我将 Paint 事件更改为使用 Graphics g,如下所示:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
DrawCircle(g);
FillGreen(g);
}
private void DrawCircle(Graphics g)
{
g.DrawEllipse(Pens.Red, 10, 10, 100, 100);
}
private void FillGreen(Graphics g)
{
IntPtr ptrHdc = g.GetHdc();
IntPtr ptrBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Green));
SelectObject(ptrHdc, ptrBrush);
ExtFloodFill(ptrHdc, 50, 50, GetPixel(ptrHdc, 50, 50), FLOODFILLSURFACE);
DeleteObject(ptrBrush);
g.ReleaseHdc(ptrHdc);
}
但是当我调整回原始大小时,会跳过 FloodFill 的某些行,尤其是当我缓慢调整大小时
【问题讨论】:
-
您需要使用来自 Paint 参数的 e.Graphics 或图片框的图像位图来绘制或从绘制事件中绘制。使用从位图创建的图形!如您所见,其他任何事情都不会持续存在。我也看不出你为什么不使用 gdi+ 绘图,假设你使用的是 winforms..
-
我来自 VB6,正在尝试将我的应用程序转换为 C# ...我编辑了我的问题以添加我尝试过的新 Paint 事件,其结果:现在正在重绘圆圈,但填充不是
-
您能解释一下如何使用 Paint 参数中的 e.Graphics 吗?与我所做的相比,gdi+ 绘图又如何呢?
-
在表单的
Resize事件中调用pictureBox1.Invalidate();可以轻松避免调整大小Paint错误! -
谢谢!这成功了:)
标签: c# refresh repaint flood-fill