Clear graphics/rectangle without changing colour? - c#

I'm drawing a rectangle onto a Panel object (PanelArea) using the following code:
private void GenerateGraphic()
{
Graphics RandomArea = PanelArea.CreateGraphics();
RandomArea.Clear(Color.Beige);
SolidBrush Brush1 = new SolidBrush(Color.FromArgb(128,220,20,60));
Rectangle rect = new Rectangle();
//Offset is from the top left hand corner.
rect.X = 25;
rect.Y = 25;
rect.Width = 1;
rect.Height = 1;
rect.Inflate(XArea / 2, YArea / 2);
RandomArea.FillRectangle(Brush1, rect);
}
I'm setting the BackgroundImage of the Panel to a snippet of the screen.
I'd like to be able to keep the background image, whilst resetting the rectangle for it to be resized.
I need RandomArea.Clear(Color.Beige) to reset the graphics in order to remove the previous rectangle. The snag is though, is that this places the colour over the background image of the panel.
How can I clear the graphics area/rectangle each time, whilst still being able to view a background image for the Panel?

Related

How can I resize the width and height of a UserControl according to a child Label?

I'm coding a clone messaging app. I have a user control called "Bubble" that I use as a message bubble. And its user control layout is like this:
It contains only lblMessage, lblTime and pictureBox. lblMessage's AutoSize property off and Anchor is top-left-right. My goal is to size or wrap this according to the content. I am able to resize vertically using this code.
void SetHeight()
{
//SizeF maxSize = new Size(500, int.MaxValue);
Graphics g = CreateGraphics();
SizeF size = g.MeasureString(lblMessage.Text, lblMessage.Font, lblMessage.Width);
lblMessage.Height = int.Parse(Math.Round(size.Height + 2, 0).ToString());
lblTime.Top= lblMessage.Bottom +10;
this.Height = lblTime.Bottom + 10;
}
My result is like this:
I can resize vertically, but not horizontally at the same time. The way I resize it vertically is to use width property of lblMessage as the limit size. I want to resize user control according to size of short text. I thought about creating a maxSize for MeasureString but I can't get it to work. I'm trying to find a function that continues from a bottom line when it reaches a certain width value. I look forward to your help.
I searched all stackowerflow questions in depth but none of them worked in my case.
**Edit after Jimi comments
I tried to apply his solution to my project. I don't think I did everything right, but with a little bit of comment, something came up that worked for me at least.
private void Bubble_Paint(object sender, PaintEventArgs e)
{
float minimumWidth = lblTime.Width + pictureBox1.Width + 35;
float maximumWidth = 500;
string measureString = lblMessage.Text;
Font stringFont = new Font("Helvetica", 12.0F);
CharacterRange[] characterRanges = { new CharacterRange(0, measureString.Length) };
float layautWidth = maximumWidth - minimumWidth;
RectangleF layoutRect = new RectangleF(10, 6, layautWidth, this.Height);
StringFormat stringFormat = new StringFormat();
stringFormat.SetMeasurableCharacterRanges(characterRanges);
Color myColor = Color.FromArgb(211, 212, 212);
SolidBrush myBrush = new SolidBrush(myColor);
Region[] stringRegions = e.Graphics.MeasureCharacterRanges(measureString, stringFont, layoutRect, stringFormat);
RectangleF measureRect1 = stringRegions[0].GetBounds(e.Graphics);
//When I gave Rectangle to the DrawString, some last letter was truncated, so I used plain text printing until I got to the bottom line.
if (measureRect1.Height < 30)
e.Graphics.DrawString(measureString, stringFont, myBrush, 10, 6, stringFormat);
else e.Graphics.DrawString(measureString, stringFont, myBrush, measureRect1, stringFormat);
e.Graphics.DrawRectangle(new Pen(Color.Transparent, 0), Rectangle.Round(measureRect1));
this.Width = Convert.ToInt32(measureRect1.Width + minimumWidth);
lblTime.Top = Convert.ToInt32(measureRect1.Height) + 10;
this.Height = lblTime.Bottom + 10;
}
Result in container preview:
user control that goes down one line from the specified limit
and for one line
dynamically result inside the application

How to rotate a picturebox and keep rectangles in same position c#

I have a picturebox with SizeMode=Zoom. I have rectangles (annotations) drawn on the picturebox too.
This is the code that rotates the image in the picturebox (in click event of a button)
Image img = picZoom.Image;
img.RotateFlip(RotateFlipType.Rotate90FlipXY);
picZoom.Image = img;
RotationgAngle += 90;
This, of course, fires off the Paint event, which contains the following:
for (int i = 0; i <= Annotations.Items.Count - 1; i++)
{
Rectangle r = functions.ZoomRectangle(Annotations.Items[i].Box, picZoom, true);
using (Matrix m = new Matrix())
{
m.RotateAt(RotationgAngle, new PointF(r.Left + (r.Width / 2), r.Top + (r.Height / 2)));
e.Graphics.Transform = m;
e.Graphics.FillRectangle(new SolidBrush(c), r);
e.Graphics.ResetTransform();
}
e.Graphics.FillRectangle(new SolidBrush(c), functions.ZoomRectangle(Annotations.Items[i].Box, picZoom, true));
}
The ZoomRectangle function scales the rectangle based on the Zoom level of the picturebox and the size of the image within the PictureBox. The rectangle rotate, just not in the right position.
When I rotate the image in my picturebox, how would I rotate my filled rectangle to maintain the exact same relative position on the picturebox?

c# drawing, circle goes outside form

I am trying to draw a circle within my form.
But it is strange to me I set form width and height to a fixed number, i do the same for the circle, but the circle figure goes outside the form.
private void Form3_Paint(object sender, PaintEventArgs e)
{
this.SuspendLayout();
gr = this.CreateGraphics();
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Brush fill_circ3 = Brushes.Blue;
Pen ellipse_pen = new Pen(Color.Blue);
ellipse_pen.Width = (float)2.0;
this.Width = this.Height = 400;
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
gr.DrawEllipse(ellipse_pen, rect);
this.ResumeLayout();
}
The 3rd and 4th parameters of the Rectangle constructor defines the size in width and height of the circle.
See the circle I got
Why does the circle goes outside the form???! I have set form and circle sizes the same!!!
It's because you use the Window size, not the "client" size. Just replace your code by this:
gr.DrawEllipse(ellipse_pen, this.ClientRectangle);
The client area of a control is the bounds of the control, minus the
nonclient elements such as scroll bars, borders, title bars, and
menus.

C# WPF - Rectangle MouseEnter & MouseLeave events not working properly

I add a bunch of rectangles to my WPF Canvas like this:
Rectangle rectangle = new Rectangle
{
Width = tuple.Width,
Height = tuple.Height,
Stroke = Brushes.Black,
StrokeThickness = 1
};
rectangle.MouseEnter += (s, e) => rectangle.Stroke = Brushes.Gray;
rectangle.MouseLeave += (s, e) => rectangle.Stroke = Brushes.Black;
Canvas.SetLeft(rectangle, tuple.X);
Canvas.SetTop(rectangle, tuple.Y);
canvas.Children.Add(rectangle);
What did I expect:
Border-Color of the rectangle the mouse is entering changes to gray and it stays gray as long as the mouse is inside of the area of that rectangle
What actually happens:
The border color only changes to gray if the mouse is directly on the border but remains black if the mouse is anywhere else (even inside the rectangle).
So why is that? How can I implement my expected behaviour?
If you give the rectangle a fill, everything works as expected:
Rectangle rectangle = new Rectangle
{
Width = tuple.Width,
Height = tuple.Height,
Stroke = Brushes.DarkGray,
StrokeThickness = 1,
Fill = Brushes.Transparent
};

Always visible drawing on form

I want to draw always visible cross over picturebox on winform. I know ho to use Graphics and it's method DrawLine. But problem is that, painted cross is hidden behind the picturebox. this textbox is continually refreshed and this cross should be always visible.
Do you have some solution for this?
Here is code:
Point picBoxLocation = pictureBox.Location;
Size picBoxSize = pictureBox.Size;
Pen myPen = new Pen(System.Drawing.Color.Red, 5);
Point left = new Point(picBoxLocation.X, picBoxSize.Height/2);
Point right = new Point(picBoxLocation.X+picBoxSize.Width, picBoxSize.Height / 2);
Point up = new Point((picBoxLocation.X + picBoxSize.Width) / 2, picBoxLocation.Y);
Point bottom = new Point((picBoxLocation.X + picBoxSize.Width) / 2, (picBoxLocation.Y+picBoxSize.Height)/2);
Graphics graphics = this.CreateGraphics();
graphics.DrawLine(myPen, left, right);
graphics.DrawLine(myPen, up, bottom);
Try to get Graphics object in OnPaint callback:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawLine(...);
}

Categories