c# Windows App Form - Graphics dementions not adding up - c#

I set my "panel" to 200, 200 and used the Graphics function to draw 4 boxes. Each box is 50x50 pixels and starts at the lower right corner of the last box.
It looks like stairs I guess.
If the form is 200, 200 it should mean that the boxes extend from the top left of the form to the lower right, but that is not the case. Only 2 1/2 boxes show inside the form. It is like the boxes have different size pixels than the form.
Thank you for the help
private void canvas_Paint(object sender, PaintEventArgs e)
{
Graphics gObject = canvas.CreateGraphics();
Brush red = new SolidBrush(Color.Red);
Pen redpen = new Pen(red, 10);
gObject.FillRectangle(red, 0, 0, 50, 50);
gObject.FillRectangle(red, 50, 50, 50, 50);
gObject.FillRectangle(red, 100, 100, 50, 50);
gObject.FillRectangle(red, 150, 150, 50, 50);
}

I solved this.
In windows 10 you can adjust the display in the settings(I had mine adjusted because the graphics are very small on the monitor). Windows itself recommends you set it 150% not 100%.
This will distort the graphics in Visual Studio.
Solution is to set Windows 10 display to 100% not the default 150%

Related

How to paint a certain area

I am new to drawing and paints in c# & I am trying to make a simple program it has 3 intersecting circles (A,B,C). What i want to do is paint a certain (according to result I get).
For example: If I get 1 as a result I want to fill the yellow bordered region, if I get 4 I want to fill green bordered region and so on.
My Code to draw these circles:
private void button1_Click(object sender, EventArgs e)
{
Graphics A = this.CreateGraphics();
Graphics B = this.CreateGraphics();
Graphics C = this.CreateGraphics();
Pen Bluepen = new Pen(Color.Blue, 2);
Pen RedPen = new Pen(Color.Red, 2);
Pen BlackPen = new Pen(Color.Black, 2);
A.DrawEllipse(Bluepen,100, 100, 150, 150);
B.DrawEllipse(RedPen, 195, 100, 150, 150);
C.DrawEllipse(BlackPen, 145, 190, 150, 150);
}
Since you are new to this topic I have to tell you: This is a lot harder that one would hope for.
Three solutions come to mind:
Construct a GraphicsPath you could fill from three Arcs. To calculate the arcs you need the rectangles you have but also the sweeping angle and also the starting angle. This will take quite some math..
After having drawn into a Bitmap you could floodfill the area you want to color. This will only work for bitamps from which you can extract the current color of each pixel, not for drawing onto controls..
The simplest way it still a bit involved, but only mildly so
Solution 3 (Create a Region and fill it)
You can use all sorts of set operations to combine areas called Regions. And you can construct a Region from a GraphicsPath. And you can construct a GraphicsPath by adding an ellipse. And you can clip the drawing area of a Graphics object to a Region.
Let's try:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle r1 = new Rectangle(100, 100, 150, 150);
Rectangle r2 = new Rectangle(195, 100, 150, 150);
Rectangle r3 = new Rectangle(145, 190, 150, 150);
GraphicsPath gp1 = new GraphicsPath();
GraphicsPath gp2 = new GraphicsPath();
GraphicsPath gp3 = new GraphicsPath();
gp1.AddEllipse(r1);
gp2.AddEllipse(r2);
gp3.AddEllipse(r3);
Region r_1 = new Region(gp1);
Region r_2 = new Region(gp2);
Region r_3 = new Region(gp3);
r_1.Intersect(r_2); // just two of five..
r_1.Exclude(r_3); // set operations supported!
g.SetClip(r_1, CombineMode.Replace);
g.Clear(Color.Magenta); // fill the remaining region
g.ResetClip();
g.DrawEllipse(Pens.Red, r1);
g.DrawEllipse(Pens.Blue, r2);
g.DrawEllipse(Pens.Green, r3);
// finally dispose of all Regions and GraphicsPaths!!
r_1.Dispose();
gp1.Dispose();
.....
}
Do note that the region operations change the current region; if you want to fill more areas you need to restore the changed region!
Also note that I draw where any persistent drawing belongs: In the Paint event and that I use its e.Graphics object..
GraphicsPaths as Regions are GDI objects and should be disposed off!
Notes on solution 1 (Create a GraphicsPath by Math)
The full math is rather involved. By making a few assumptions the task can be greatly simplified: Let's assume the circles have the same size. Also that we first look at two circles only, with the same y-position. Finally that the circles form a symmetrical figure. (Which btw they don't: the red circle should have x=190 and the green one y=186,45..)
Getting the two intersection points as well as the sweeping angle is not so hard.
Next one can rotate the two points twice around the center of the whole figure by 120° using a Matrix; see here for an example. Now we have six points; we still need the smaller sweeping angle, which is also found with simple math.
Finally we can construct all 12 (!) GraphicsPaths from the 12 arcs and combine them at will.
The good part is that we can both fill and draw those paths. But, the code is rather extensive..
Notes on solution 2 (floodfill)
While you can't floodfill directly on a control you can prepare the result in a bitmap and then display that image on the control with Graphics.DrawImage.
For an example of coding a floodfill see this post!

Graphics.DrawHalfCirle & Graphics.DrawPartialCircle

I'm trying to draw half and partial circles (all BLACK lines) on a bitmap.
My INTENDED result looks like this:
My CURRENT result looks like this:
I've tried so many different alternatives but it nevers looks right.
using (var b = new Bitmap(200, 100, PixelFormat.Format24bppRgb))
{
using (var g = Graphics.FromImage(b))
{
g.FillRectangle(new SolidBrush(Color.LightGray), 0, 0, 200, 100);
// RED COLOR
Rectangle rec = new Rectangle(-15, 50, 70, 100);
g.DrawRectangle(new Pen(Color.Red, 1f), rec);
g.DrawArc(new Pen(Color.Red, 3f), rec, 50, 100);
// WHITE COLOR
Rectangle rec = new Rectangle(10, 50, 70, 70);
g.DrawRectangle(new Pen(Color.White, 1f), rec);
g.DrawEllipse(new Pen(Color.White, 3f), rec);
}
}
But it always look totally wrong and after hours of playing with the numbers, I could not find a way to control the output.
Question:
Is there a simple way to design the 3 black lines on my INTENDED image in a graphic object using C# ??
The easy way to achieve this is to draw three concentric circles and let clipping take care of the fact that two of them fall outside the drawing region.
The way to achieve the arc-based drawing you want is probably to start with the concentric circles (so you know you have the rects in the right places), and then change the DrawEllipse to DrawArc, setting the start and sweep angles to the right values.
Start angle is measured in degrees from the x axis (horizontal line towards the right of the circle's centre), so for the smaller arc you will need an angle approximately 305 degrees. From there you need it to draw for about 90 degrees. The outer arc will be similar, but a smaller arc, so it might go from about 330 degrees for a sweep of about 60 degrees.
It seems the solution is to draw a rectangle outside the boundaries of the bitmap and use the graphic.DrawEllipse method to draw the curve line.
Here is a snippet of the working code:
Pen pen = new Pen(Color.White);
Rectangle rec = new Rectangle(-30, 50, 100, 100);
g.DrawEllipse(pen, rec);
rec = new Rectangle(-30, 10, 150, 150);
g.DrawEllipse(pen, rec);
rec = new Rectangle(-30, -30, 200, 200);
g.DrawEllipse(pen, rec);
Many thanks to Hans Passant to point me to this line of thinking.

GDI+ shows artifact when drawing rectangles side-by-side with scale factor

Using GDI+ to draw two rectangles side-by-side, if I apply a scale factor to have a zoom effect, an artifact appears between the rectangles in some scale factors.
I have the following code to show the problem:
var scale = (float)(numericUpDown1.Value)/100.0f;
var g = e.Graphics;
var b = new SolidBrush(Color.Red);
var rect1 = new Rectangle(10, 40, 100, 100);
var rect2 = new Rectangle(110, 40, 100, 100);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.ScaleTransform(scale, scale);
g.FillRectangle(b, rect1);
g.FillRectangle(b, rect2);
Using this code and setting the "numericUpDown1" to 100, I get the following:
Setting the scale to 125, I get a line between the rectangles:
Scaling to pretty much any value that is not a multiple of 10 gives this problem. Looking close on the line, it seems to be some anti-aliasing effect. I can't remove the anti-aliasing because in my real scenario the rectangles might be polygons with non-straight lines.
I've tried many things, like toggling the PixelOffsetMode, CompositingQuality, Antialiasing, but nothing works. My goal is to have something in the same level of quality of what MS PowerPoint does.

How do I fill a rectangle with the exception of a area

I am trying to fill a rectangle in a winforms application less a ellipse in the center that allows the image in the background to show through.
can anyone give me a hint on which way to go on this,
thanks.
this is what I have come up with so far:
path.AddRectangle(new Rectangle(30, 30, 100, 100));
path.AddEllipse(new Rectangle(50, 50, 60, 60));
gfx.FillPath(new SolidBrush(Color.Black), path);
protected override void OnPaint(PaintEventArgs e){
var rgn = new Region(new Rectangle(50, 50, 200, 100));
var path = new GraphicsPath();
path.AddEllipse(60, 60, 180, 80);
rgn.Exclude(path);
e.Graphics.FillRegion(Brushes.Blue, rgn);
}
The easy way:
Fill the Reacngle first
Then Fill the Ellipse (with a Transparant brush)
It isn't clear enough what kind of transparency is required there. The simple way is to invert the problem. Use a TextureBrush to draw the image with Graphics.FillEllipse().
You could try to use regions. Create a rectangle region, exclude an ellipse and then fill it.

Graphics transparency on PictureBox

First of all, this is not about making the PictureBox control transparent. It's about bitmap transparency on the fully opaque "canvas".
The PictureBox will always have the size of 300*300 with white background. No transparency is needed for the control.
What I need is the way to draw the transparent rectangle (or whatever else) onto the pictureBox, so anything that was already there will be seen "through" the rectangle.
Say I have a following code
Bitmap bmp = new Bitmap(300, 300);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(Color.White), 0, 0, 300, 300);
g.FillRectangle(new SolidBrush(Color.Red), 100, 100, 100, 100);
pictureBox.Image = bmp;
This will draw a red rectangle in the middle of the white canvas. Now, I need another (transparent) "layer" on the picture containing another rectangle, but one that is transparent.
I can try
Brush brush = new SolidBrush(Color.FromArgb(128, 0, 80, 0));
g.FillRectangle(brush, 50, 50, 200, 200);
Since I am using a color by specifying its alpha = 128, the resulting rectangle should be transparent so the first red rectangle should be seen through this other green one.
However, this does not happen correctly. I can see the red rectangle behind the new green one, but the part of the green rectangle that does not overlap the red one will remain completely opaque. However, if I set the alpha value of the color to some extremely small value (say 1-5), the whole rectangle will look transparent. This is not normal in my opinion - that 5/255 is only half transparent and that 128/255 is not transparent at all... And if there was a string drawed previously with g.DrawString(), the string is either displayed behind the green rectangle or it is not, depending on the level of transparency. For example if the Alpha is greater than or equals (around) 40, the string is not visible at all, and if it is less than 40, then it will show, more visible for smaller alpha values, down to alpha = 0.
How is this brush (when created from Argb color) applied? Am I missing something? To me it seems that setting a transparent brush makes the background "more visible" instead of setting the object "less visible".
Thanks for any replies with suggestions.
[EDIT] It seems I had a nasty bug in application logic, so the drawing routine happened in a loop, so when I accumulated certain number of transparent rectangles, they became more and more thick.
The code, when taken out of the loop, works correctly.
My bad.
alt text http://lh4.ggpht.com/_1TPOP7DzY1E/S02ivAoGgTI/AAAAAAAAC6s/ZQvZQ5GdwSU/s800/Capture4.png
is done by this code:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Bitmap bmp = new Bitmap(300, 300);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(Color.White), 0, 0, 300, 300);
g.FillEllipse(new SolidBrush(Color.Blue), 25, 25, 100, 200);
g.FillRectangle(new SolidBrush(Color.Red), 100, 100, 300, 100);
g.DrawString("this is a STRING", SystemFonts.DefaultFont,
Brushes.Black, new Point(150, 150));
pictureBox1.Image = bmp;
Brush brush = new SolidBrush(Color.FromArgb(40, 0, 80, 0));
g.DrawRectangle(Pens.Black, 50, 50, 200, 200);
g.FillRectangle(brush, 50, 50, 200, 200);
}
The green part is not opaque as you can see... The string is perfectly visible.
To me it seems that setting a transparent brush makes the background "more visible" instead of setting the object "less visible".
background "more visible" and object "less visible" are the same thing...

Categories

Resources