How to create a smooth circle picture box in C#? - c#

I'm currently designing a program in "Visual Studio 2015 C#" and would like to implement circular picture boxes. In the program there are picture boxes which source image is downloaded from the web. In it's default state, the "picturebox" is square. I would like to know how I could change the shape of the "picturebox" to a circle. That way the image when loaded will be circular instead of squared or rectangular.
I already figured out how to downscale the image and keep it's quality and center it, but I do not know how to change the "picturebox" into a circle.
I found a couple ways to do it, but unfortunately with this methods the circle is not smooth, instead it is pixelated.
This is an example of what I would like: http://i.imgur.com/kaOfTFU.png

You create a path (that is a circle, or whatever shape you want), and set the picturebox region to that path. Here's an example with a circle:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddEllipse(0, 0, pictureBox1.Width, pictureBox1.Height);
pictureBox1.Region = new Region(path);
}
}
This StackExchange post has how to make any path smooth for a picturebox:
Possible to have anti-aliasing when drawing a clipped image?

Related

How can I make the transparency from a PictureBox work properly when it's over another PictureBox?

I was doing a game project in Windows Forms and really loved how it turned out, except for one thing that was bugging me: the new picturebox's I am adding are "eating" away from the one behind it, showind the background of its parent and not showing the image behind him, as I thought it will. Apparently that's how transparency works in Windows Forms, it copies the colors behind him, basically.
This is how it looks, and I want the animals to be seen fully.
I also tried this from another post here, but it turned out like this.
There might be no solution to this, I have other things in this little game I made. There is another picturebox with other buttons and stuff, that represents the shop. And also you can see in both images that there is a pannel in the bottom section with some details. In that case, I would leave it as it is and maybe try another time to move it to WPF.
=================== EDIT ===================
The accepted answer helped me switch from a game with overlaying PictureBoxes to a game where I "paint" each frame of the game on the background. Check that answer's comment for more details about this :) This is how it turned out.
This is specifically for my code, where I have a static Resources class. Yours could look a lot cleaner, maybe you have this Render function where you have every other rectangle and image. I hope this helps everyone that visits this page :)
// ================ SOLUTION ================
public static void Render()
{
//draw the background again. This is efficient enough, maybe because the pixels that did not changed won't be redrawn
grp.DrawImage(Resources.gameBackground, 0, 0);
//draw the squirrel image on the position and length of the "squirrel" Rectangle
grp.DrawImage(Resources.currentSquirrelImage, Resources.squirrel.X, Resources.squirrel.Y, Resources.squirrel.Width, Resources.squirrel.Height);
//after that, draw each projectile (acorns, wallnuts) the same way
foreach (Projectile projectile in Resources.projectiles)
{
grp.DrawImage(projectile.image, projectile.rect.X, projectile.rect.Y, projectile.rect.Width, projectile.rect.Height);
}
//then draw each animal
foreach (Enemy animal in Resources.enemies)
{
grp.DrawImage(animal.image, animal.rect.X, animal.rect.Y, animal.rect.Width, animal.rect.Height);
}
//and finally, the image that shows where the squirrel is shooting
grp.DrawImage(Resources.selectionImge, Resources.selection.X, Resources.selection.Y, Resources.Selection.Width, Resources.Selection.Height);
//update the image of the game picturebox
form.TheGame.Image = bmp;
}
As you have noticed .net control transparency is not real transparency, it copies it's parent background, so if you have other sibiling controls the one with the higher Z index will occlude the others.
If you want to create a game avoid the usage of picture boxes, there are many options: use a game engine like Unity or roll your own.
Something easy to do is to create a Bitmap, render your game in it and then present it in your form, but beware, that can be slow.
EDIT: As you requested here is an example on how to use the Intersect function of the Rectangle struct to determine which parts of two rectangles overlap.
Rectangle R1 = new Rectangle (0,0,32,32);
Rectangle R2 = new Rectangle (16,16,32,32);
//To test if a rectangle intersects with another...
bool intersects = R1.IntersectsWith(R2); //If does not intersect then there's nothing to update
//To determine the area that two rectangles intersect
Rectangle intersection = Rectangle.Intersect(R1, R2); //In this example that would return a rectangle with (16,16,16,16).

Rectangle Selection Like Tool MS Paint C#

I have been working on creating a program similar to MS Paint. I have several of the features it has down but the one which is currently giving me trouble is the rectangular selection tool. My program currently draws everything on the panel and saves it all in an ArrayList so each shape can be redrawn in Paint().
Like MS paint I would like the user to be able to select a section of the drawing on the panel and either copy it, move it, re-size it, or even delete it. I was thinking about having the user draw a rectangle & saving the information for it. Then taking that information for the rectangle, passing them to create a new Bitmap. I would then paint a new rectangle in the background color to give the appearance that the selected area was "removed" when the selected portion is moved. It sounded okay until I realized that I couldn't use the Graphics.FromImage() on the PaintEventArgs variable passed to Paint() which made my idea useless. Not sure if that makes sense so my apologies if it's a confusing mess.
I've been searching the internet for some assistance and I haven't found much to help so either this is very easy to do, very difficult, or "rectangle selection tool" is not the proper term. Any help or pointers would be greatly appreciated!!! Thank you for your time! :)
I understand that you actually have the Rectangle and now would like to copy an area from your painted Panel.
This is possible, assuming you have, as you should, placed all the painting in the Paint event of the Panel.
Then you can, use DrawToBitmap to ask the Panel to draw itself onto a new Bitmap; from there you can DrawImage the Rectangle onto your Panel.
Note: For this to integrate with your list of 'Paint-Actions' you will have to either now store that Bitmap or store the Rectangle and redo the whole operation.
using (Graphics G = panelCanvas.CreateGraphics() )
{
Rectangle R0 = new Rectangle(22,22,55,55); // your Rectangle!
using (Bitmap bmp = new
Bitmap(panelCanvas.ClientSize.Width, panelCanvas.ClientSize.Height))
{ panelCanvas.DrawToBitmap(bmp, panelCanvas.ClientRectangle);
G.DrawImage(bmp, 111f, 111f, R0, GraphicsUnit.Pixel);
}
}
Aside: Please do replace the ArrayList, which is depracated by the new List<T>, e.g. a List<PaintAction> or whatever name your class has!
If you simply want to extract a rectanglular area from the Panel Control you can use thsi function:
public Bitmap getAreaFrom(Control ctl, Rectangle area)
{
Bitmap bmp2 = new Bitmap(area.Width, area.Height);
using (Graphics G = ctl.CreateGraphics())
using (Bitmap bmp = new Bitmap(ctl.ClientSize.Width, ctl.ClientSize.Height))
{
ctl.DrawToBitmap(bmp, ctl.ClientRectangle);
using (Graphics G2 = Graphics.FromImage(bmp2))
G2.DrawImage(bmp, 0f, 0f, area, GraphicsUnit.Pixel);
}
return bmp2;
}

Coloring area of an image on mouse click over picturebox

I would like to be able to fill any given area of an image with a given color, much like you can use paint to fill a rectangle, circle or any other shape delimited by a color.
To make this simpler I already have made the picture box source image to have the same size as the picture box itself, which should make things a bit easier.
How can I do this given that I have a picture box with an image and an already defined color and the user only has to click over the picture box to fill in any area with such color.
void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
// The color to be used
Color color = Color.Red;
// Image has same dimensions as picturebox to make things easier
Image img = pictureBox1.Image;
// Where it was clicked.
Point clickCoords = new Point(e.X, e.Y);
// Coloring that area clicked much like Paint does. How?
...
// After coloring show the result in the picture box again
pictureBox1.Image = img;
}
Thanks.
EDIT: Example of my desired behavior.
To make my goal obvious, let me add this small example.
You know MS Paint right?
You selected the pencil tool and start doing anything on the canvas, doesn't matter form or shape or even if the points your are doing with the pencil are connected or not.
Now you select the bucket tool and start clicking on the canvas. What will it do? Fill in the selected area according to the color you clicked over and how far she goes without changing with the color you have selected on the color pallet.
This is the behavior I want to emulate on my picture box mouse click event.
What you are looking for is a flood-fill algorithm. This should do the trick just fine.
The algorithm recursively searched for neighboring uncolored pixels, until it hits a wall.
You can use the code from here:
// Load the image (probably from your stream)
Image image = Image.FromFile( imagePath );
using (Graphics g = Graphics.FromImage(image))
{
Color customColor = Color.FromArgb(50, Color.Gray);
SolidBrush shadowBrush = new SolidBrush(customColor);
g.FillRectangles(shadowBrush, new RectangleF[] { rectFToFill });
}
image.Save( imageNewPath );
, but there is a one thing you missed - a rectFToFill, which you should define according your click event. There are a lot of strategies you can use, I suggest you to handle a Drag event or something like that, save the event start point and end point, after that define the rectangular you must fill:
You should examine the event points and after that create the Rectangle(F) structure using some of its constructors.
The Graphics class has a dozen methods you can use to draw some shapes or lines on your Image.

Take screenshot at specified coordinates

In a Windows Forms application, how do I take a "screenshot" of certain coordinates?
In the picture below, you see a Window and inside that window is a little gray box, somewhere near the center.
Where every I might place that box, how can I take a "screenshot" of it (including whatever content is inside it) programmatically?
Simple way
Simple, use Graphics.CopyFromScreen
private Bitmap bitmap;
private Graphics graph;
graph.CopyFromScreen(X, Y, 0, 0, Size, CopyPixelOperation.SourceCopy);
Now you can use bitmap, that contains a source copy of the area.
Hacky way
SendKeys.Send("%{PRTSC}"); //Alt + PrtSc to screenshot just the active window.
Bitmap clipboardImage = Clipboard.GetImage(); //Get image from the clipboard
//Here you crop the image using Bitmap.Clone();
//Be happy and question yourself why you are doing this way.

C# drawing in layers

I have an idea and maybe you guys can give me a good start or an idea in which path might be correct.
I have a picturebox right now loading a specific bmp file. What I want to do is load this bmp file into the picturebox and then load another picture on top of it. The kicker to this all is the 2nd picture must be drawn. The 2nd picture is just a fill in black box. This black box must also overlay on the first image exactly right, the black box has cordinates from paint on it (yes we have the # of the cordaints).
Still think the picturebox is the way to go, or is there a way to load paint into this, and then paint on top of the paint image?
1) Need to load an image
2) Need to read a specific file that has cords
3) Need to draw a black rectangle that matches those coords (Those cords were created in paint).
What do you think the best way to approach this is? A Picture box with code to draw in the cords of the redacted image
Here's a code sample that should do what you're after:
//Load in an image
pbTest.Image = Image.FromFile("c:\\Chrysanthemum.jpg");
//Create the graphics surface to draw on
using (Graphics g = Graphics.FromImage(pbTest.Image))
{
using (SolidBrush brush = new SolidBrush(Color.Black))
{
//Draw a black rectangle at some coordinates
g.FillRectangle(brush, new Rectangle(0, 0, 20, 10));
//Or alternatively, given some points
//I'm manually creating the array here to prove the point, you'll want to create your array from your datasource.
Point[] somePoints = new Point[] { new Point(1,1), new Point(20,25), new Point(35, 50), new Point(90, 100) };
g.FillPolygon(brush, somePoints);
}
}
The finished article:
This answer is written to apply to both web and non-web uses of C# (why I did not give specific examples.)
GDI and other graphics libs all have functions that will paint a filled rectangle on top of an image. This is the way to go. If you use two images there is a good chance for a standard user and a great chance for a hacker they will be able to view just the original image, exposing the information you are trying to hide.
If you only send an image with the areas redacted, you will never have to worry about them being seen.

Categories

Resources