2

I'm trying to understand the graphics, and in the Graphics.FromImage documentation, it has this as an example:

private void FromImageImage(PaintEventArgs e)
{

    // Create image.
    Image imageFile = Image.FromFile("SampImag.jpg");

    // Create graphics object for alteration.
    Graphics newGraphics = Graphics.FromImage(imageFile);

    // Alter image.
    newGraphics.FillRectangle(new SolidBrush(Color.Black), 100, 50, 100, 100);

    // Draw image to screen.
    e.Graphics.DrawImage(imageFile, new PointF(0.0F, 0.0F));

    // Dispose of graphics object.
    newGraphics.Dispose();
}

I'm new to C# and Windows Forms and am struggling to understand how this all fits together. How is this code run, say when the form first loads or when a button is pressed?

Thomas
  • 21
  • 4
  • Call `OnPaint` from your `OnLoad` method. Also, you should wrap your `Graphics` object in a `using() { }` block. You should also cache your `Image imageFile` in a field so you're not loading a file from disk every time the form paints. – Dai May 05 '19 at 18:44
  • @Dai Apologies if this is a really basic question, but in a new form would that be in the ````public Form1()```` method? And what is the actual code that goes in there? I've tried simply ````OnPaint();```` and ````FromImageImage.OnPaint();```` – Thomas May 05 '19 at 19:04
  • 1
    You could call your method in the Paint event: `FromImageImage(e);` . You can trigger the Paint event by calling Invalidate(). – TaW May 05 '19 at 19:26
  • @TaW Could you elaborate on that? – Thomas May 05 '19 at 19:44
  • Who do you want to happen when the form loads exactly? – John Alexiou May 05 '19 at 19:56
  • The example you are using is not exactly a simple situation. But it should work by first loading and then changing an image (by drawing a rectangle into it). Then that image is painted onto some control (or the form). For the latter to work it needs a valid Graphics object, which must be ontained by the Paint event. Note how two totally different Graphics obbject are used. Do read up on the difference of drawing into a bitmap or onto a control [here](https://stackoverflow.com/questions/27337825/picturebox-paintevent-with-other-method/27341797?r=SearchResults&s=2|21.0563#27341797)! – TaW May 05 '19 at 20:39
  • @TaW Thank you very much, its starting to make more sense, but [this](https://stackoverflow.com/questions/55986966/winforms-how-do-i-overlay-an-image-of-a-certain-size-with-transparency-over-an) is what I'd like to end up with, so maybe if you could explain using that example, that will help me more? Thanks again (I'm just very new to this) – Thomas May 05 '19 at 20:43
  • What is the desired result: An image or a drawing on a control? – TaW May 05 '19 at 20:46
  • @TaW To be honest I'm not sure, sorry. I was just asking about this example to gain more understanding, my actual problem is detailed [here](https://stackoverflow.com/questions/55986966/winforms-how-do-i-overlay-an-image-of-a-certain-size-with-transparency-over-an). Would you be able to recommend something having read that? – Thomas May 05 '19 at 20:54
  • OK, so you want to overlay two images and set zooms and positions independently but don't need animation, right? So I would aim at creating a 3rd image. In addition to the zoom and positioning it will be important to understand dpi resolutions (which will be honored ny DrawImage.).. – TaW May 05 '19 at 21:03
  • @TaW Yeah, the FOV outline will stay the same size but the object image should change based on the values calculated in the rest of the program (that I'm okay with). Its the actual drawing of the images that I really don't know how to go about doing. So I know I need to create a third image from the original 2, but I haven't a clue how to do so, as I am very unfamiliar with all this. Basically, what is the code for image3 = image1 over image2, and how do I implement that in my program? – Thomas May 05 '19 at 21:29
  • Glad to see you are happy. If you have questions do aks..! – TaW May 06 '19 at 07:00
  • @TaW Regarding drawing into the image, how do I get that code to run? I know the `pictureBox1_Paint` runs as an event but I'm not sure how in your answer [here](https://stackoverflow.com/questions/27337825/picturebox-paintevent-with-other-method/27341797#27341797) how the bottom one runs? – Thomas May 06 '19 at 10:41
  • The bottom code can be called directly. It modifies the bitmap. Then, just to demostrate the result is shown in the pbox whose Image was changed. he code above seems to be called from the Form.Paint event. It leaks a Bitmap and uses dispose instead to using to dispose of the newgrphics object, which is not as reliable. so the code is not exactly a good guid on how to use gdi graphics. – TaW May 06 '19 at 10:52
  • @TaW I think I'm missing something - does [this](https://stackoverflow.com/questions/56003941/winforms-how-do-i-place-png-over-another-image) make more sense? – Thomas May 06 '19 at 11:08
  • The code makes only little sense. I added a line that would make it work but it still is not sensible. Do read up my 2nd comment here and the link in it!!! – TaW May 06 '19 at 11:18

1 Answers1

1

Maybe this will help. I have an example of both drawing on Paint events but also drawing on top of an existing Image. I created a form with two picture boxes. One for each case. pictureBox1 has an event handler for the .Paint event, while pictureBox2 is only drawn when a button is pressed.

form design

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        pictureBox1.BackColor=Color.Black;
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        // The code below will draw on the surface of pictureBox1
        // It gets triggered automatically by Windows, or by
        // calling .Invalidate() or .Refresh() on the picture box.
        DrawGraphics(e.Graphics, pictureBox1.ClientRectangle);
    }

    private void toolStripButton1_Click(object sender, EventArgs e)
    {
        // The code below will draw on an existing image shown in pictureBox2
        var img = new Bitmap(pictureBox2.Image);
        var g = Graphics.FromImage(img);

        DrawGraphics(g, pictureBox2.ClientRectangle);
        pictureBox2.Image=img;
    }

    void DrawGraphics(Graphics g, Rectangle target)
    {
        // draw a red rectangle around the moon 
        g.DrawRectangle(Pens.Red, 130, 69, 8, 8);
    }
}

So when you launch the application a red rectangle appears on the left only, because the button hasn't been pressed yet.

before click

and when the button is pressed, the red rectangle appears on top of the image displayed in pictureBox2.

after click

Nothing dramatic, but it does the job. So depending on the mode of operation you need (user graphics, or image annotations) use the example code to understand how to do it.

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
  • 1
    This `private void picureBox1_Paint(sender as object, e as PaintEventArgs)` looks like a mix of C# and VB.NET. Did you mean `private void picureBox1_Paint(object sender, PaintEventArgs e)`? – Wiktor Zychla May 05 '19 at 20:17
  • Wow, what a major brain fart. I will correct. I am surprised I didn't mix in some Fortran there since I am active in it also. – John Alexiou May 05 '19 at 20:18
  • The code I pasted was an example from the [Graphics.FromImage](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.fromimage?view=netframework-4.8) documentation. I'm trying to understand how it all works, and can't run that code like a normal method, as in: ````FromImageImage();```` because of the `PaintEventArgs e` parameter, so I think I am misunderstanding how that works. Also I tried that code and nothing appeared in the picture box when I pressed the button? – Thomas May 05 '19 at 20:23
  • The `Graphics.FromImage()` method is used to generate a graphics object in order to draw into a bitmap. This is a similar, but not identical process to draw on the screen. What are you interested in? Drawing generating a bitmap or drawing on the screen? – John Alexiou May 05 '19 at 23:25
  • @Thomas - I redid my answer, although still unclear on what you are trying to achieve here. At least this might help you understand how `Graphics.FromImage()` is used. – John Alexiou May 06 '19 at 00:03
  • @ja72 That is amazing thank you so much, I understand much more now, however, there's something more going wrong. Might I be missing part of the software, because I have done exactly as you have in your example but when I press the button, no rectangle appears? – Thomas May 06 '19 at 00:20
  • 1
    @ja72 Nevermind, I was typing in the `pictureBox1_Paint` manually, had to get that from its properties instead - think I've got it sorted so thank very much – Thomas May 06 '19 at 00:40