I'm creating a Windows Forms application. How do I capture the size of the windows form?
Currently I have something that looks like this in my code:
PictureBox display = new PictureBox();
display.Width = 360;
display.Height = 290;
this.Controls.Add(display);
display.Image = bmp;
However, the size of my display is hard-coded to a specific value.
I know that if I want to draw a square that re-sizes I can use something like this:
private Rectangle PlotArea;
private int offset = 30;
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
//// Calculate the location and size of the plot area
//// within which we want to draw the graphics:
Rectangle ChartArea = ClientRectangle;
PlotArea = new Rectangle(ChartArea.Location, ChartArea.Size);
PlotArea.Inflate(-offset, -offset);
Draw PlotArea:
g.DrawRectangle(Pens.Black, PlotArea);
}
Is there a way for me to use method one and grab the size of the form for Height and Width?
I've tried the following code, but it doesn't work...
PictureBox display = new PictureBox();
display.Width = ClientRectangle.Y;
display.Height = ClientRectangle.X;
this.Controls.Add(display);
display.Image = bmp;
For Getting the size of a Windows Form:
int formHeight = this.Height;
int formWidth = this.Width;
PictureBox display = new PictureBox();
display.Width = ClientRectangle.Width;
display.Height = ClientRectangle.Height;
this.Controls.Add(display);
display.Image = bmp;
When you resize the window:
private void Form1_Resize(object sender, System.EventArgs e)
{
Control control = (Control)sender;
// set the PictureBox width and heigh here using control.Size.Height
// and control.Size.Width
}
You want to set Dock = DockStyle.Fill to dock the control to fill its parent.
Set it to ClientRectangle.Width.
Related
I'm creating an image viewer using C# and having a small issue with scaling (zooming) PictureBox.
I have a PictureBox inside a Panel, and I can zoom (scale) an image using the controls at the top left and using mouse wheel just fine. However, at some specific zoom scales, the image doesn't cover the whole PictureBox.
For example, SO logo (100x116 pixels) at 100% and at 200%:
Image at the right is 199x131 pixels, while the PictureBox is 200x132.
I've set the BackColor of the PictureBox to Red to make the issue noticeable.
This doesn't always happen, just at specific zoom levels. Why is that? Am I doing something wrong?
I can set the BackColor of PictureBox to the BackColor of the Panel to give the illusion that the image covers the whole PictureBox, but I rather fix the problem. If I can't, I'll apply the tricky solution.
Relevant code:
float zoom = 1;
Image image = null;
public MainForm(string[] args)
{
InitializeComponent();
image = ImageBox.Image;
this.ImageBox.MouseWheel += ImageBox_MouseWheel;
if (args.Length > 0)
{
LoadImage(args[0]);
}
}
private void ImageBox_Paint(object sender, PaintEventArgs e)
{
// disable interpolation (sharper pixels)
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
// https://msdn.microsoft.com/en-us/library/ms142046(v=vs.110).aspx
e.Graphics.DrawImage(image,
new Rectangle(0, 0, ImageBox.Width, ImageBox.Height),
0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}
private void LoadImage(string path)
{
image = Image.FromFile(path);
ImageBox.Width = (int)(image.Width * zoom);
ImageBox.Height = (int)(image.Height * zoom);
ImageBox.Image = image;
CenterImage();
}
private void ScaleImage()
{
ImageBox.Image = null;
ImageBox.Width = (int)(image.Width * zoom);
ImageBox.Height = (int)(image.Height * zoom);
ImageBox.Image = image;
CenterImage();
}
I've also created a repository, in case anyone wants to examine the app live.
You need to adjust the rectangle in ImageBox_Paint. Try this:
private void ImageBox_Paint(object sender, PaintEventArgs e)
{
int add = ImageBox.Width / 200;
// disable interpolation (sharper pixels)
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
// https://msdn.microsoft.com/en-us/library/ms142046(v=vs.110).aspx
e.Graphics.DrawImage(image,
new Rectangle(0, 0, ImageBox.Width + add, ImageBox.Height + add),
0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}
Simply set the SizeMode property of the PictureBox to Zoom. Then adapting the size of the picturebox will automatically make the image stretch to its full size.
You don't even need that Paint event listener; it's inbuilt functionality. Just change the dimensions of the PictureBox to the calculated zoomed dimensions of the image and you're done.
In a WPF User Control, I am trying to mask an Image control with a circle that can vary in position and size. The user left-drags to change the circle radius and right-drags to change the center point of the ellipse. I'm capturing all the needed values correctly and can properly set the radius of the mask. The problem is, that no matter what point I use for the center of the ellipse, it is drawn from the center of the Image control. Any ideas?
Below is the code that sets the mask:
private void SetMask(double _Radius)
{
EllipseGeometry MaskGeometry = new EllipseGeometry(CenterPos, _Radius, _Radius);
GeometryDrawing MaskDrawing = new GeometryDrawing(Brushes.Black, null, MaskGeometry);
DrawingBrush MaskBrush = new DrawingBrush(MaskDrawing);
MaskBrush.Stretch = Stretch.None;
Img.OpacityMask = MaskBrush; //Img is the Image control
}
You also have to set the ViewboxUnits, AlignmentX, and AlignmentY properties:
private void SetMask(double radius)
{
var maskGeometry = new EllipseGeometry(CenterPos, radius, radius);
var maskDrawing = new GeometryDrawing(Brushes.Black, null, maskGeometry);
var maskBrush = new DrawingBrush
{
Drawing = maskDrawing,
Stretch = Stretch.None,
ViewboxUnits = BrushMappingMode.Absolute,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top
};
Img.OpacityMask = maskBrush;
}
You need to modify the Viewport and ViewportUnits property of your DrawingBrush base tile :
private void button1_Click(object sender, RoutedEventArgs e)
{
EllipseGeometry MaskGeometry = new EllipseGeometry(CenterPos, _RadiusX, _RadiusY);
GeometryDrawing MaskDrawing = new GeometryDrawing(Brushes.Black, null, MaskGeometry);
DrawingBrush MaskBrush = new DrawingBrush(MaskDrawing);
MaskBrush.Stretch = Stretch.None;
MaskBrush.ViewportUnits = BrushMappingMode.Absolute;
MaskBrush.Viewport = MaskGeometry.Bounds;
Img.OpacityMask = MaskBrush; //Img is the Image control
}
MSDN document here gives a good explanation of how controls are painted using TileBrush.
I have a UserControl that contains a PictureBox and a Label. The Control loads three different images in PictureBox on different events (fore example onMouseEnter, OnMouseLeave). As the images can have different sizes, I neet to resize the pictureBox and
the control itself. Below is provided the control's OnPaint event but this does not work.
protected override void OnPaint(PaintEventArgs pe)
{
if (pictureBox.Image != null)
{
this.Width = this.pictureBox.Image.Size.Width;
this.Height = this.pictureBox.Image.Size.Height;
CutRoundedRectangle2(pictureBox, cornerRadius);
}
else
{
Bitmap DrawArea = new Bitmap(pictureBox.Size.Width, pictureBox.Size.Height);
Graphics g = Graphics.FromImage(DrawArea);
Pen mypen = new Pen(Color.Black);
pictureBox.Image = DrawArea;
System.Drawing.Pen pen = new Pen(new SolidBrush(this.ForeColor));
g.DrawRectangle(pen, 0, 0, this.Width-1, this.Height-1);
g.Dispose();
}
this.labelText.ocation = new Point((this.pictureBox.Width - this.labelText.Width) / 2,
(this.pictureBox.Height - this.labelText.Height) / 2);
base.OnPaint(pe);
}
The pictureBox SizeMode is set in control's constuctor:
this.pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
It was long time ago when I worked with WinForms last time, but ...
My first thought is: have you tried set value of parent control's AutoSize property to 'true' and AutoSizeMode to GrowAndShrink and call parent control's Refresh() method when new image is loaded to picture box?
#Alexey, the pictureBox resize event helped!
private void pictureBox_Resize(object sender, EventArgs e)
{
this.Width = this.pictureBox.Image.Size.Width;
this.Height = this.pictureBox.Image.Size.Height;
}
I am trying to use the graphics object to load an image in and then rotate it (either portrait or landscape) and then display it in a panel (not a picture box).
How would I load the graphics in the panel? Also what would be the simplest way to do a landscape or portrait rotation on the graphics object?
GDI must be used to rotate and work with the image, I need a way to get the Graphics object into the panel.
Use the Paint event of the Panel:
private void panel1_Paint(object sender, PaintEventArgs e)
{
int angle = 90;
Graphics g = e.Graphics;
Image i = new Bitmap(#"C:\Jellyfish.jpg");
g.TranslateTransform((float)i.Width / 2, (float)i.Height / 2);
g.RotateTransform(angle);
g.TranslateTransform(-(float)i.Width / 2, -(float)i.Height / 2);
g.DrawImage(i, new Point(0,0));
}
Since you are talking about a panel and it's C#, I will guess you are referring to WinForms.
You can rotate any Image instance using the RotateFlip method, and you can use an Image as the BackgroundImage of your panel. A working example:
Bitmap bitmap = new Bitmap(#"D:\word.png");
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
Form form = new Form() { Height = 400, Width = 600 };
Panel p = new Panel() { Height = 400, Width = 600, Left = 0, Top = 0};
form.Controls.Add(p);
p.BackgroundImage = bitmap;
form.Show();
I have an image .I want to crop 10 px from left and 10px from right of the image.I used the below code to do so
string oldImagePath="D:\\RD\\dotnet\\Images\\photo1.jpg";
Bitmap myOriginalImage = (Bitmap)Bitmap.FromFile(oldImagePath);
int newWidth = myOriginalImage.Width;
int newHeight = myOriginalImage.Height;
Rectangle cropArea = new Rectangle(10,0, newWidth-10, newHeight);
Bitmap target = new Bitmap(cropArea.Width, cropArea.Height);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(myOriginalImage,cropArea);
}
target.Save("D:\\RD\\dotnet\\Images\\test.jpg");
But this is not giving me the results which i expect. This outputs an image which has 10 px cropped from the right and a resized image.Instead of cropiing it is resizing the width i think.So the image is shrinked(by width). Can any one correct me ? Thanks in advance
Your new width should be reduced by twice the crop margin, since you'll be chopping off that amount from both sides.
Next, when drawing the image into the new one, draw it at a negative offset. This causes the area that you aren't interested in to be clipped off.
int cropX = 10;
Bitmap target = new Bitmap(myOriginalImage.Width - 2*cropX, myOriginalImage.Height);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(myOriginalImage, -cropX, 0);
}
My guess is this line
Rectangle cropArea = new Rectangle(10,0, newWidth-10, newHeight);
should be
Rectangle cropArea = new Rectangle(10,0, newWidth-20, newHeight);
Set the width of the new rectangle to be 20 less than the original - 10 for each side.
Some indication what result it is giving you would be helpful in confirming this.
Corey Ross is correct. Alternately, you can translate along the negative x axis and render at 0.0, 0.0. Should produce identical results.
using (Graphics g = Graphics.FromImage(target))
{
g.TranslateTransform(-cropX, 0.0f);
g.DrawImage(myOriginalImage, 0.0f, 0.0f);
}
You need to use the overload that has you specify both Destination Rectangle, and Source Rectangle.
Below is an interactive form of this using a picture box on a form. It allows you to drag the image around. I suggest making the picture box 100 x 100 and have a much larger image such as a full screen window you've captured with alt-prtscr.
class Form1 : Form
{
// ...
Image i = new Bitmap(#"C:\Users\jasond\Pictures\foo.bmp");
Point lastLocation = Point.Empty;
Size delta = Size.Empty;
Point drawLocation = Point.Empty;
bool dragging = false;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (!dragging)
{
lastLocation = e.Location;
dragging = true;
}
delta = new Size(lastLocation.X - e.Location.X, lastLocation.Y - e.Location.Y);
lastLocation = e.Location;
if (!delta.IsEmpty)
{
drawLocation.X += delta.Width;
drawLocation.Y += delta.Height;
pictureBox1.Invalidate();
}
}
else
{
dragging = false;
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Rectangle source = new Rectangle(drawLocation,pictureBox1.ClientRectangle.Size);
e.Graphics.DrawImage(i,pictureBox1.ClientRectangle,source, GraphicsUnit.Pixel);
}
//...
Okay, I totally fail at explaining this, but hang on:
The DrawImage function requires the location of the image, as well as it's position. You need a second position for cropping as how the old relates to the new, not vice versa.
That was entirely incomprehensible, but here is the code.
g.DrawImage(myOriginalImage, -cropArea.X, -cropArea.Y);
I hope that explains it more then I did.