C# Drawing a Bitmap on a certain point in a PictureBox - c#

I currently have a Bitmap image. I need to place this image at a certain coordinate inside a PictureBox. Specifically, I'm looking to place it 5 pixels from the top and 5 pixels from the left. The bitmap will be of different lengths, so I want the starting point to always start drawing the Bitmap at this specific point.
As an example, here are two "Bitmaps" that both start at the coordinate 5,5, with different lengths. Imagine the Gray is the PictureBox:
I've tried something like passing in a PictureBox and using graphics to draw the bitmap:
private void setQuantity(PictureBox pb, int quantity) {
Graphics g = pb.CreateGraphics();
g.DrawImage(iqc.createQuantityImage(quantity), 0, 0);
g.Dispose();
}
iqc.createQuantityImage() returns a Bitmap
But this doesn't seem to draw anything. I have also changed the x and y and nothing changes.
I'd like to be able to specify the exact coordinate or point inside the PictureBox if possible.
Thanks for any help!

You can draw image in PictureBox at any location by adding an event handler to its Paint method as follows;
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_myBitmap, new Point(5, 5)); //Here new Point(x,y) determines location in pictureBox where you want to draw the bitmap.
}

Related

PictureBox background equal to other PictureBox while moving?

C# Beginner here.
I'm making a 2D Tanks game, and everything's working out nicely so far.
Both of my tanks are Picture Boxes, and so is my Missile.
The image of the missile and tanks in the PictureBoxes have transparent BackColour properties. The problem is, the background of the missile & tanks are not transparent while on top of the other picturebox (pbBackground). It looks like this.
I'm aware that using different PB's is an inefficient way of going about it, but I've come pretty far and I don't really know any better. Anyways, as you can see, the Missile and Tank PB backgrounds show the form colour. When I downloaded the images, the backgrounds were transparent, I'm sure of it. How do I go about making the background of my PB's truly transparent? (Matching the background of the Overlapped PB?)
I saw this but it doesn't really match my scenario and I don't understand the solution.
UPDATE: Okay, I followed Tommy's advice, is this the right way to go about moving it along pbBackground in a timer constantly changing MissileX and MissileY? Currently this does nothing.
using (Graphics drawmissile = Graphics.FromImage(pbBackground.Image))
{
drawmissile.DrawImage(pbMissile.Image, new Point(MissileX,Convert.ToInt32(MissileY)));
}
PictureBox is opaque. And PictureBox is not efficient.
For making games, you should study Paint event which directly draws on your form.
Bitmap backgroundBitmap = new Bitmap("background");
Bitmap tankBitmap = new Bitmap("tank");
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(backgroundBitmap, 0, 0);
e.Graphics.DrawImage(tankBitmap, 30, 30);
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Invalidate(); //trigger Form1_Paint to draw next frame
}
Don't layer multiple PictureBox instances on top of each other. It will get very confusing, very quickly.
Instead, use one single PictureBox and use Paint to draw your images to it. In this way, you can have much more control over the graphics operations happening.
Have a look at this
private void DrawIt()
{
System.Drawing.Graphics graphics = this.CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(
50, 50, 150, 150);
graphics.DrawEllipse(System.Drawing.Pens.Black, rectangle);
graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
In this example they demonstrate how to draw shapes directly onto a Form. You would use your PictureBox there instead. You can also draw images.
There's lots of ways to draw shapes onto a form using a System.Drawing.Graphics object. Try taking a look at this question for a comparison.
Tommy's answer is right, however, if you're dead set on using pictureboxes (a bad idea), set the overlapping picturebox backgroundcolour to Transparent and the Form's Background to whatever image. TIL the Transparent BackColour just uses the form colour / image. Tommy actually has the right answer here, but this is what I did to fix my problem (the lazy way).

Printing high resolution with temporary Bitmap

I want to print labels. If I draw to the printing contexts Graphics object, it works without problems. But if I use a temporary Bitmap all the drawn text is pixelated. I recognized that the resolution of the temp Bitmap and the printing Graphics object are different (96 dpi vs. 600 dpi). So I change the Bitmaps resolution to match the printing resolution. So all the drawn text is too big.
I need the temporary Bitmap to rotate the image before printing.
How to get this Bitmap correctly printed?
Pixalated code: (looks bad but has the temporary bitmap)
// print event handler
private void printPage(object sender, PrintPageEventArgs ev)
{
// size of the page
Size s = Form1.getPixelFromCM(Properties.Settings.Default.LabelSize);
// temporary bitmap object
Bitmap bmp = new Bitmap(s.Width, s.Height);
Graphics g = Graphics.FromImage(bmp);
// draw text
labels[printLabelsIndex].PrintLabel(g);
// draw the bitmap to the page
ev.Graphics.DrawImage(bmp, 0, 0);
}
This code produces this print:
High resolution code: (looks good but I need the temporary bitmap!)
// print event handler
private void printPage(object sender, PrintPageEventArgs ev)
{
// draw text directly to print context
labels[printLabelsIndex].PrintLabel(ev.Graphics);
}
This code produces this print:
It is a good thing that Graphics.DrawImage honors the Bitmap's resolution, although it sometimes leads to confusion, when one assumes that all pieces of the puzzle have the same resolution..
Here you need to set the resolution of the temporary Bitmap explicitly or else if simply inherits the screen resolution..:
bmp.SetResolution(600,600)
Of course now the Labels' Size will probably not be large enough..
Also note a problem with terminology: Resolution may mean size i.e. pixels or printer dots but really ought to mean density i.e. dpi or ' dots per inch' .
You want to bring up the size and also the dpi!

Drawing interactively lines over a Bitmap

I need to allow to the user to draw lines over an bitmap. Lines should be drawn interactively, I mean something performed using typical code giving to the user a visual feedback about what is drawn:
private void MainPictureBox_MouseDown( object sender, MouseEventArgs e)
{
DrawingInProgress = true ;
Origin = new Point (e.X, e.Y);
}
private void MainPictureBox_MouseUp(object sender, MouseEventArgs e)
{
DrawingInProgress = false ;
}
private void MainPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (!DrawingInProgress) return ;
End = new Point (e.X, e.Y);
using( Pen OverlayPen = new Pen( Color .Red, 1.0f))
using (Graphics g = MainPictureBox.CreateGraphics())
{
g.DrawLine(OverlayPen, Origin, End);
}
}
Of course I keep track of the points using List.Add within MainPictureBox_MouseUp in order to draw lines in the Paint event (code not shown for the sake of simplicity)
Without the background image things could be done nicely simply overwriting the previous line with the background color, something like:
g.DrawLine(BackgroundColorPen, Origin, PreviousEnd);
g.DrawLine(OverlayPen, Origin, End);
but this is not possible with a not uniform background.
Invalidating the rectangle defined by the points: Origin, PreviousEnd then using Update() makes the rendering quite messy. I am wondering how to perform this task and those are possible ways to do so i am considering:
Draw the lines over a transparent bitmap then draw the bitmap over the Picturebox. I guess that with big images this is simply unfeasible for performances reason.
Using the Picture.BackgroundImage for the bitmap then drawing on the Picture.Image but I unable to figure out how this could really saave the day
Using double buffering? How?
Stacking a different control (a panel?) over the pictureBox, making it transparent (is it possible?) then drawing over it.
Could someone give a hint in the best direction? I am really getting lost.
The solutions working for me has been the following:
Create a transparent panel;
Put it over the bitmap having them overlap completely;
Draw on the panel using proper mouse events;
There is no need to cancel the previous shape, of course: it was a misleading question. It is sufficient to distinguish permanent shapes recorded in proper lists fed to the Paint event from the transient shape previously drawn that will be not drawn again in the next Paint event;
Make absolutely sure that all drawings are performed in the Paint event using the Graphics provided by the PaintEventArgs. Thanks to #HansPassant to have stressed this in a different post.

Good looking graphics in C# window form

I need to create some simple graphics in a windows form using C#. By simple I mean lines, circles etc. However, when I draw e.g. a filled circle, the edge is not smooth (as expected when drawing a circle using square pixels), but when drawing the same circle with the same number of pixels in a vector program it looks perfect. I have been drawing in Inkscape for this example.
Maybe the vector software uses some sort of render function to smooth the colors, but is this possible in C# without creating too much code? Here is an example of the code, which is using Graphics to create a canvas to draw on.
private void StatGraphicsPanel_Paint(object sender, PaintEventArgs e)
{
Graphics canvas = e.Graphics;
Brush brush = Brushes.Aqua;
canvas.FillEllipse(brush, 0, 0, 10, 10);
}
Solution
This code does the trick:
private void StatGraphicsPanel_Paint(object sender, PaintEventArgs e)
{
Graphics canvas = e.Graphics;
canvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Brush brush = Brushes.Aqua;
canvas.FillEllipse(brush, 0, 0, 10, 10);
}
You want to use the System.Drawing.Graphics.SmoothingMode property. Before beginning to use your Graphics object, do this:
canvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
That should give you a nice anti-aliased ellipse instead of the default jaggy one.
Similarly, if you want to draw high-quality text in an image, use the System.Drawing.Graphics.TextRenderingHint property.
As others have mentioned in comments, you might want to consider using WPF instead. WinForms are dated.

How to keep the image Drawn in PictureBox

Hey everyone, a new guy here in C#.Net.
I'm trying to make an application like Ms Paint, of course much simpler, and I'm stuck.
The problem is this.
In pictureBox, I'm drawing grid lines on the PictureBox, after that I'm reading a .map(A Mapper3 file) and want to draw onto grid lines, but When I draw the map, The grid lines disappers.
I think the problem is because of the PictureBox Image becomes null while I'm drawing the map. How can I overcome this, is there any tricks?
Thanks for the replies from now on, and sorry for my bad English...
My best Regards...
Do you using winforms? If yes, you actually dont need picture box for working area. I think more appropriate would be Graphics class on form or panel. You have lost lines because of form repaint circle, put your drawing code into form paint handler and picture would be repainted when it needed. In some cases you can need to manual trigger repaint circle, for this purposes you should use Invalidate method of your form.
For example, add this code to paint handler:
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Drawing vertical lines
for (int x = 5; x < this.ClientRectangle.Width; x+=5)
{
e.Graphics.DrawLine(Pens.Gray, new Point(x, 0), new Point(x, this.ClientRectangle.Height));
}
// Drawing horisontal lines
for (int y = 5; y < this.ClientRectangle.Width; y += 5)
{
e.Graphics.DrawLine(Pens.Gray, new Point(0, y), new Point(this.ClientRectangle.Width,y));
}
}
You also may use Graphics in button click handler this way:
Graphics g = Graphics.FromHwnd(this.Handle);
g.FillEllipse(Brushes.Beige, new Rectangle(10, 10, 10, 10));
But in this case all you have drawn would be erased during form's repaint circle and you will have to repeint it in form paint handler
[EDIT]
Ok, for example you have pictureBox1 on your form, you can easly draw into it with help of Bitmap class in this way:
// Draw into bitmap
Bitmap bmp = new Bitmap(150, 150);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(Brushes.Green, new Rectangle(25, 75, 10, 30));
// Set bitmap into picture box
pictureBox1.Image = bmp;
In this case you have no need to redraw your paintings, picture box would do it for you. Dont forget to set BackColor ot picture box to Transparent if you prefer to show paintings from below of picture box.
You have to draw everything including the grid lines whenever the paint event raised, if you are concerned about performance you may detect the clipping area and only draw that portion.
Good luck.

Categories