我的应用程序中有两个windows窗体。在主窗体上,我单击一个按钮,打开带有面板的第二个窗口。在面板上的表格中,我画了一些东西,并把它读到一个图片框中。
这是我主要表单的编码。
Bitmap retBmp;
FrmDrawing frmDrawing = new FrmDrawing();
var result = frmDrawing.ShowDialog();
if (result == DialogResult.OK)
{
retBmp = frmDrawing.bmpNew;
pbDesign.Image = retBmp;
}
这就是我在第二张表格上的绘图方式。
public FrmDrawing()
{
InitializeComponent();
g = pnlDraw.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
pen = new Pen(Color.Black, 5);
pen.StartCap = pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void pbRed_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender;
pen.Color = p.BackColor;
}
private void pnlDraw_MouseDown(object sender, MouseEventArgs e)
{
moving = true;
x = e.X;
y = e.Y;
pnlDraw.Cursor = Cursors.Cross;
}
private void pnlDraw_MouseMove(object sender, MouseEventArgs e)
{
if (moving && x!=-1 && y!=-1 )
{
g.DrawLine(pen, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
private void pnlDraw_MouseUp(object sender, MouseEventArgs e)
{
moving = false;
x = -1;
y = -1;
pnlDraw.Cursor = Cursors.Default;
}
private void btnClear_Click(object sender, EventArgs e)
{
g.Clear(Color.White);
pnlDraw.Invalidate();
}
private void btnAccept_Click(object sender, EventArgs e)
{
bmpNew = new Bitmap(pnlDraw.Width, pnlDraw.Height);
this.pnlDraw.DrawToBitmap(bmpNew, new Rectangle(0, 0, this.pnlDraw.Width, this.pnlDraw.Height));
this.DialogResult = DialogResult.OK;
this.Close();
}
在第二个表单中,我将面板上绘制的内容读取为bmp,然后单击按钮将其传递给表单。这段代码运行得几乎很好,只是它只通过了面板,而不是在面板上绘制的内容。如果我在我绘制的面板上再放置两个彩色图片框控件,则显示的图像会与这些彩色图片框一起出现,但不会与我在面板上绘制的内容一起出现。当我把我在面板上画的东西读到位图时,我做错了什么?或者应该更正什么,以便将我在面板上绘制的内容转换为位图。
首先,正如您在MSDN上所读到的:
通过
CreateGraphics
方法检索的Graphics
对象通常不应在处理完当前Windows消息后保留,因为用该对象绘制的任何内容都将在下一条WM_PAINT
消息中擦除。因此,除了使用像Graphics.MeasureString
这样的非可视化方法外,不能缓存Graphics
对象以供重用。相反,每次要使用Graphics
对象时都必须调用CreateGraphics
,然后在使用完Dispose
后再调用它。
(强调矿(
因此,您不应该在表单构造函数中创建Graphics
对象,而应该在事件处理程序中动态创建和处理它。
但这对你没有任何帮助。尝试将表单从屏幕上移开并移回来,您会注意到,所有自定义绘图都会消失。这是因为你没有保留它们——它们只是一次性渲染的。
使用PictureBox
并直接在其Bitmap
上绘制线,而不是使用面板。
pnlDraw
现在是PictureBox
,而不是Panel
:
public FrmDrawing()
{
InitializeComponent();
pnlDraw.Image = new Bitmap(pnlDraw.Width, pnlDraw.Height);
}
private void pnlDraw_MouseMove(object sender, MouseEventArgs e)
{
if (moving && x!=-1 && y!=-1 )
{
// Create Graphics object dynamically
using (var g = Graphics.FromImage(pnlDraw.Image))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.Black, 5))
{
pen.StartCap = pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
g.DrawLine(pen, new Point(x, y), e.Location);
}
}
// This is necessary; otherwise, we won't see the changes until
// the picture box is repainted by the OS
pnlDraw.Invalidate();
x = e.X;
y = e.Y;
}
}