C# bitmap drawing doesn't render to the screen
I am trying to write a drawing program for use with a tablet. For this I need fall-off and transparency for use with pressures. So I am using the bitmap system in C# for image construction.
I cannot seem to get my drawing code at the moment to display anything. It is being rendered to a picture box. I know there is some stuff being input to the bitmap as it shows up when I do a bitmap save.
I have had a look around an pretty much all C# drawing questions refer to using the line drawing or ellipse drawing stuff as opposed to bitmaps
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace paint1
{
public partial class Form2 : Form
{
public Bitmap m_bitmap;
public bool m_penDown;
public int m_lastX;
public int m_lastY;
public int m_currentX;
public int m_currentY;
public Form2()
{
InitializeComponent();
// Create the bitmap area
m_bitmap = new Bitmap(this.Width, this.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
m_penDown = false;
Graphics m_graphics = Graphics.FromImage(m_bitmap);
m_lastX = System.Windows.Forms.Cursor.Position.X;
m_lastY =开发者_运维知识库 System.Windows.Forms.Cursor.Position.Y;
m_currentX = System.Windows.Forms.Cursor.Position.X;
m_currentY = System.Windows.Forms.Cursor.Position.Y;
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Form2_Paint(object sender, PaintEventArgs e)
{
Graphics objGraphics;
//You can't modify e.Graphics directly.
objGraphics = e.Graphics;
// Draw the contents of the bitmap on the form.
objGraphics.DrawImage(m_bitmap, 0, 0,
m_bitmap.Width,
m_bitmap.Height);
objGraphics.Dispose();
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
m_penDown = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
m_penDown = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
m_lastX = m_currentX;
m_lastY = m_currentY;
m_currentX = System.Windows.Forms.Cursor.Position.X;
m_currentY = System.Windows.Forms.Cursor.Position.Y;
if(m_penDown)
m_bitmap.SetPixel(m_currentX, m_currentY, Color.Gray);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Form2_Paint(sender, e);
this.pictureBox1.Image = m_bitmap;
}
private void Form2_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
m_bitmap.Save(@"C:\Users\rpettefar\Documents\My Dropbox\Programming\paint1\preview.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
}
I am a bit new to c# so I am very open to any other issues or things that may come to your attention too.
You will have to assign your bitmap to the picture box.
myPictureBox.Image = m_bitmap;
You can do that after you changed the bitmap or assign it once and then invalidate your PictureBox.
myPictureBox.Invalidate();
This tells your form to refresh the picture on the screen. There is no need to override OnPaint. Draw to the bitmap using the Graphics object you created in the constructor of the form (if you want to make more complicated things than just drawing single pixels). The PictureBox will do the rest.
It looks like there's at least two ways you're trying to get the image on screen; can't say immediately what's wrong, but I would say definitely get rid of that objGraphics.Dispose();
line - you didn't create the Graphics
(you were passed it), so you shouldn't Dispose
it.
I cleaned up your code a bit. You probably shouldn't use a picturebox for this.
Here is a form with just a panel:
public partial class Form1 : Form
{
public Bitmap m_bitmap;
public Point m_lastPoint = Point.Empty;
public Form1()
{
InitializeComponent();
m_bitmap = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(m_bitmap))
g.Clear(SystemColors.Window);
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(m_bitmap, new Point(0, 0));
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
m_lastPoint = e.Location;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
using (Graphics g = Graphics.FromImage(m_bitmap))
g.DrawLine(Pens.Black, m_lastPoint, e.Location);
m_lastPoint = e.Location;
panel1.Invalidate();
}
}
}
The other posters have largely answered the question, but in my experience, I'd add that you'll likely get some flicker with this method. If you do, one thing you can do to help with this is sub-class your rendering target and enable double buffering. For a picture box, it would look something like this:
public class DoubleBufferedPictureBox : PictureBox
{
/// <summary>
/// Creates an instance of the DoubleBufferedPictureBox.
/// </summary>
public DoubleBufferedPictureBox() : base()
{
this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
}
}
精彩评论