C# 在绘图程序中保存位图

C# 在绘图程序中保存位图,c#,winforms,bitmap,C#,Winforms,Bitmap,我正在开发一个完全用c#编写的类似MS paint的程序。这很基本,但我偶然发现了一个问题。所以我看到了另一篇关于MS绘画模型的So帖子。它是关于如何将最终结果保存为.bmp文件。我试着使用提供的解决方案和答案,效果很好 文件已保存。然而,当它保存时,它只保存了空白面板(IM制作一个表单应用程序)。我只看到过一篇关于这个问题的文章,但我无法将其合并以允许用户进行交互。以下是我的代码: using System; using System.Collections.Generic; using Sy

我正在开发一个完全用c#编写的类似MS paint的程序。这很基本,但我偶然发现了一个问题。所以我看到了另一篇关于MS绘画模型的So帖子。它是关于如何将最终结果保存为.bmp文件。我试着使用提供的解决方案和答案,效果很好

文件已保存。然而,当它保存时,它只保存了空白面板(IM制作一个表单应用程序)。我只看到过一篇关于这个问题的文章,但我无法将其合并以允许用户进行交互。以下是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

    namespace Paint
    {
    public partial class Form1 : Form
    {
    Graphics g;
    Pen p = new Pen(Color.Black, 1);
    Point sp = new Point(0, 0);
    Point ep = new Point(0, 0);
    int k = 0;

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox2_Click(object sender, EventArgs e)
    {
        p.Color = red.BackColor;
        default1.BackColor = red.BackColor;


    }

    private void blue_Click(object sender, EventArgs e)
    {
        p.Color = blue.BackColor;
        default1.BackColor = blue.BackColor;
    }

    private void green_Click(object sender, EventArgs e)
    {
        p.Color = green.BackColor;
        default1.BackColor = green.BackColor;
    }



    private void panel2_MouseDown(object sender, MouseEventArgs e)
    {
        sp = e.Location;
        if (e.Button == MouseButtons.Left)
            k = 1;
    }

    private void panel2_MouseUp(object sender, MouseEventArgs e)
    {
        k = 0;
    }

    private void panel2_MouseMove(object sender, MouseEventArgs e)
    {
        if (k == 1)
        {
            ep = e.Location;
            g = panel2.CreateGraphics();
            g.DrawLine(p, sp, ep);

        }
        sp = ep;
    }



    private void panel2_MouseLeave(object sender, EventArgs e)
    {
        k = 0;        }

    private void panel2_Paint(object sender, PaintEventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
        SaveFileDialog dialog = new SaveFileDialog();
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            int width = Convert.ToInt32(panel2.Width);
            int height = Convert.ToInt32(panel2.Height);
            Bitmap bmp = new Bitmap(width, height);
            panel2.DrawToBitmap(bmp, new Rectangle(0, 0, width, height));
            bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
        }
    }
}
}
所以我的问题是。。。如何在我的c#forms应用程序中成功保存.bmp图像,如如何不将其保存为空白。提前感谢:)

编辑 因此,我尝试了第一个答案,也尝试了个人在评论中提出的想法和一些方法,而不仅仅是保存一张空白画布。应用程序实际上只是保存一个黑色图像。这是我最后得到的代码。我哪里出错了

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks; 
using System.Windows.Forms;

namespace Paint
{
public partial class Form1 : Form
{
    Graphics g;
    Graphics h;
    Pen p = new Pen(Color.Black, 1);
    Point sp = new Point(0, 0);
    Point ep = new Point(0, 0);
    int k = 0;
    Bitmap bmp =null;

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox2_Click(object sender, EventArgs e)
    {
        p.Color = red.BackColor;
        default1.BackColor = red.BackColor;


    }

    private void blue_Click(object sender, EventArgs e)
    {
        p.Color = blue.BackColor;
        default1.BackColor = blue.BackColor;
    }

    private void green_Click(object sender, EventArgs e)
    {
        p.Color = green.BackColor;
        default1.BackColor = green.BackColor;
    }



    private void panel2_MouseDown(object sender, MouseEventArgs e)
    {
        sp = e.Location;
        if (e.Button == MouseButtons.Left)
            k = 1;
    }

    private void panel2_MouseUp(object sender, MouseEventArgs e)
    {
        k = 0;
    }

    private void panel2_MouseMove(object sender, MouseEventArgs e)
    {
        if (k == 1)
        {
            ep = e.Location;
            int width = Convert.ToInt32(panel2.Width);
            int height = Convert.ToInt32(panel2.Height);
            Bitmap bmp = new Bitmap(width, height);

            g = Graphics.FromImage(bmp);
            g.DrawLine(p, sp, ep);
            h = panel2.CreateGraphics();
            h.DrawLine(p, sp, ep);
        }
        sp = ep;
    }



    private void panel2_MouseLeave(object sender, EventArgs e)
    {
        k = 0;        }

    private void panel2_Paint(object sender, PaintEventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
        SaveFileDialog dialog = new SaveFileDialog();
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            /*
            Bitmap bmp = Bitmap.FromHbitmap(panel2.CreateGraphics().GetHdc());
            panel2.DrawToBitmap(bmp, new Rectangle(0, 0, width, height));*/
            int width = panel2.Width;
            int height = Convert.ToInt32(panel2.Height);
            if (bmp == null)

                bmp = new Bitmap(width, height);
            bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
        }
    }
}
}

按如下方式使用并保存:

Bitmap bitMap = Bitmap.FromHbitmap(g.GetHdc());
bitMap.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Bmp);

这是一个修订版,与我在评论中告诉你的差不多

public partial class Form2 : Form
{
    Graphics g;
    Graphics h;
    Pen p = new Pen(Color.Black, 1);
    Point sp = new Point(0, 0);
    Point ep = new Point(0, 0);
    int k = 0;
    Bitmap bmp =null;

    public Form2()
    {
        InitializeComponent();
        bmp = new Bitmap(panel2.ClientSize.Width, panel2.ClientSize.Height);
        g = Graphics.FromImage(bmp);
        g.Clear(panel2.BackColor);
    }

    private void pictureBox2_Click(object sender, EventArgs e)
    {
        p.Color = red.BackColor;
        default1.BackColor = red.BackColor;
     }

    private void color_Click(object sender, EventArgs e)
    {
        Control ctl = sender as Control;
        p.Color = ctl.BackColor;
        default1.BackColor = ctl.BackColor;
    }

    private void panel2_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            ep = e.Location;
            g.DrawLine(p, sp, ep);
            h = panel2.CreateGraphics();
            h.DrawLine(p, sp, ep);
        }
        sp = ep;
    }

    private void panel2_MouseDown(object sender, MouseEventArgs e)
    {
        sp = e.Location;
    }


    private void button1_Click(object sender, EventArgs e)
    {
        SaveFileDialog dialog = new SaveFileDialog();
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
        }
    }
}
请注意:

  • 我将调色板控件的所有单击映射为一个
  • 通过在移动中进行按钮测试,我消除了标志
    k
  • 我保留了缓存的图形
    g
    ;这通常是不推荐的,但当我们继续绘制成一个位图时,相同的位图是可以的
  • 我已删除位图的所有重复声明
    bmp
  • 我不知道picturebox是做什么的,所以我没碰密码
soution的缺点:

  • 既然你没有跟踪所有的动作,你就不能很好地撤销
  • 由于所有线都是单独绘制的,因此使用更宽和/或半透明的笔无法获得良好的效果,因为重叠端点看起来很糟糕

关于简单涂鸦的更好解决方案,请参见,在您研究了它之后,您可以处理更好的解决方案,它将允许您使用各种绘图工具。

我已经重写了我的函数:`if(dialog.ShowDialog()==DialogResult.OK){int width=Convert.ToInt32(panel2.width);int height=Convert.ToInt32(panel2.height);Bitmap-Bitmap=Bitmap.FromHbitmap(g.GetHdc());Bitmap.Save(dialog.FileName,System.Drawing.Imaging.ImageFormat.Bmp);}`并且System.Drawing.dll错误中出现“System.InvalidOperationException”。它表示该对象(即g)正在其他地方使用,请尝试以下操作:
Bitmap Bitmap=Bitmap.FromHbitmap(panel2.CreateGraphics())它给了我一个错误,无法将System.drawing.graphics转换为System.IntPtrOh。很抱歉,这是打字错误。尝试使用
Bitmap Bitmap=Bitmap.FromHbitmap(panel2.CreateGraphics().GetHdc())
g=panel2.CreateGraphics();Winforms graphics基本规则#1:切勿使用
控件。CreateGraphics
!切勿尝试缓存
图形
对象!使用
Graphics g=Graphics.FromImage(bmp)
或在控件的
Paint
事件中,使用
e.Graphics
参数将bmp绘制到
位图中您可以将该代码用于临时内容,但用于真实、持久的内容,这些内容将用于在Paint事件中绘制的DrawToBitmap及其e.Graphics obejct中。要这样做,请收集您在列表中绘制的每个元素。好的,那么,我将如何实现您的第一个建议:
Graphics g=Graphics.FromImage(bmp)
到我的代码中。我是新手,所以如果我在考验你的耐心,我很抱歉。(我的意思是,我把它放在代码中的什么地方,我还需要修改什么)您可以简单地替换
g=panel2.CreateGraphics()
by
g=Graphics.FromImage(bmp)在类级别创建位图bmp后。这是可以的,但不允许你实现撤销,这对于一个绘画应用程序来说太好了。。。因此,最好采用更大的解决方案/重写。是一大堆的例子。当我替换它时,它说bmp在当前上下文中不存在。这是因为我还没有定义它,所以我要向上移动它,或者我该如何使用按钮单击功能是的,将其定义为类级别并在表单加载中创建它。或者在条件下使用它之前(
如果(bmp==null)bmp=new Bitmap(,w,h);
)一个快速问题(ps感谢您的回答):现在保存到黑色背景。如何将其保存到白色背景?
g.Clear(panel2.BackColor)实际上它保存到面板的背景色。请注意,默认情况下,面板是透明的,而且许多查看器(例如Irfanview)无法显示透明度。(IrfanView将其显示为黑色!)因此,您看到的可能实际上是透明的??您可以将面板更改为白色,也可以将面板更改为清晰的颜色。白色。。