Question

I have embedded the code below in a project in which a want to paint with a brush OVER a picture. The problem is that if a write this code for a main panel , everything goes fine, but as I want to use it for an existing image, I can not see the brush. I suppose that the brush paints but it is a matter of foreground / background.

//the first line goes to the main form  - under the initialize component
graphics = DisplayPicturebox.CreateGraphics();

bool draw = false;
Graphics graphics;

private void DisplayPicturebox_MouseDown(object sender, MouseEventArgs e)
{
    draw = true;
}

private void DisplayPicturebox_MouseUp(object sender, MouseEventArgs e)
{
    draw = false;
}

private void DisplayPicturebox_MouseMove(object sender, MouseEventArgs e)
{
    if (draw)
    {
        //create a brush:
        SolidBrush MysolidBrush = new SolidBrush(Color.Red);
        graphics.FillEllipse(MysolidBrush, e.X, e.Y,
                      Convert.ToInt32(toolStripTextBox1.Text),
                      Convert.ToInt32(toolStripTextBox1.Text));
    }
}
Was it helpful?

Solution

A few important things to note here:

  • Graphics need to be processed in a pipeline or saved in some way so that repaints don't eliminate the changes the user had made.

  • Keeping a graphics context open indefinitely is a bad idea. You should open the context log enough to draw what you need to either to a buffer or to the screen, then close that context.

  • If you want to use an offscreen buffer you need to keep in mind the coordinate system you are working in ("Screen" versus "control", versus "buffer"). If you get these confused you may not see what you expect

Those concepts in mind, you might consider the following changes to your code:

// at the beginning of your class declare an offscreen buffer
private System.Drawing.Bitmap buffer;

// .. later create it in the constructor
public Form1() {
  InitializeComponent();

  // use the w/h of the picture box here
  buffer = new System.Drawing.Bitmap(picBox.Width, picBox.Height);
}

// in the designer add a paint event for the picture box:
private picBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e) {
   e.Graphics.DrawImageUnscaled(buffer);
}

// finally, your slightly modified painting routine...
private picBox__MouseMove(object sender, MouseEventArgs e)
{
  if (draw)
  {
    using (var context = System.Drawing.Graphics.FromImage(buffer)) {
      //create a brush:
      SolidBrush MysolidBrush = new SolidBrush(Color.Red);
      graphics.FillEllipse(MysolidBrush, e.X, e.Y,
                    Convert.ToInt32(toolStripTextBox1.Text),
                    Convert.ToInt32(toolStripTextBox1.Text));
    }
  }
}

This isn't meant to be perfect code but the general template should work and get you closer to what I think you are looking for. Hope that helps some!

OTHER TIPS

Try this one, modify the mousemove event:

private void DisplayPicturebox_MouseMove(object sender, MouseEventArgs e)
    {
        if (draw)
        {
            graphics = DisplayPicturebox.CreateGraphics();
            SolidBrush MysolidBrush = new SolidBrush(Color.Red);
            float newX = (float)DisplayPicturebox.Image.Size.Width / (float)DisplayPicturebox.Size.Width;
            float newY = (float)DisplayPicturebox.Image.Size.Height / (float)DisplayPicturebox.Size.Height;
            graphics = Graphics.FromImage(DisplayPicturebox.Image);

            graphics.FillEllipse(MysolidBrush, e.X * newX, e.Y * newY, Convert.ToInt32(toolStripTextBox1.Text), Convert.ToInt32(toolStripTextBox1.Text));
            DisplayPicturebox.Refresh();
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top