Line object not showing up in Windows Forms application - c#

I need to create some shape object like Circle, Line etc in Windows Forms using C#.
Added reference to PresentationFramework from .Net tab and using System.Windows.Shapes.
But after creating Line object it is not showing in Windows Form.
Please see below sample code :
code in load event of form :
Line myline = new Line();
myline.X1 = 100;
myline.X2 = 300;
myline.Y1 = 300;
myline.Y2 = 300;
myline.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myline.StrokeThickness = 2;
Please let me know wrong I'm doing in it.

you forgot to update the drawing request, you are just defining the line without drawing it actually
Edited:
public void drawmyline()
{
System.Drawing.Graphics example;
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// Create points that define line.
Point point1 = new Point(100, 100);
Point point2 = new Point(400, 400);
example = this.CreateGraphics();
// Draw line to screen.
example.DrawLine(blackPen, point1, point2);
//e.Graphics.DrawLine(blackPen, point1, point2);
}
then, you call your function from any place you want, for example a button click
private void button4_Click_1(object sender, EventArgs e)
{
drawmyline();
}
please mark as accepted if it helped you

Related

Draw circle in new position without removing previous circle?

In fact , I want to draw circle in new position each time double-click and without remove before circle ,It should be noted that, I used PictureBox.
public Point postionCursor { get; set; }
List<Point> points = new List<Point>();
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
postionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25));
points.Add(postionCursor);
pictureBox1.Invalidate();
pictureBox1.Paint += new PaintEventHandler(pic_Paint);
}
private void pic_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Point pt in points)
{
Pen p = new Pen(Color.Tomato, 2);
SolidBrush myb = new SolidBrush(Color.White);
g.DrawEllipse(p, postionCursor.X, postionCursor.Y, 20, 20);
g.FillEllipse(myb, postionCursor.X, postionCursor.Y, 20, 20);
p.Dispose();
}
}
You're not using the pt variable in the foreach loop.
foreach (Point pt in points)
{
using(Pen p = new Pen(Color.Tomato, 2))
using(SolidBrush myb = new SolidBrush(Color.White))
{
g.FillEllipse(myb, pt.X, pt.Y, 20, 20);
g.DrawEllipse(p, pt.X, pt.Y, 20, 20);
}
}
In your code, you were just overwriting the circle in the same location for every Point in the points list.
Also, as Reza mentioned in the comments, you don't need to attach the PaintEventHandler event hanlder every time the PictureBox is clicked, you just need to do it once.
So I got to thinking, and then Visual Studio-ing, that perhaps we don't even need the foreach loop. I still maintain a List so we know where the user has clicked, but there's no need to loop through it and redraw everything every time.
I realize this doesn't handle the case where the underlying list is modified, but nor does the original sample. Here's my entire Form1 class:
public partial class Form1 : Form
{
private const int CircleDiameter = 20;
private const int PenWidth = 2;
private readonly List<Point> _points = new List<Point>();
public Form1()
{
InitializeComponent();
pictureBox1.Paint += (sender, args) =>
{
_points.ForEach(p => DrawPoint(p, args.Graphics));
};
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
var cursorLocation = pictureBox1.PointToClient(Cursor.Position);
_points.Add(cursorLocation);
var circleArea = new Rectangle(
cursorLocation.X - CircleDiameter/2 - PenWidth,
cursorLocation.Y - CircleDiameter/2 - PenWidth,
CircleDiameter + PenWidth*2,
CircleDiameter + PenWidth*2);
pictureBox1.Invalidate(circleArea);
}
private static void DrawPoint(Point point, Graphics graphics)
{
point.X -= CircleDiameter / 2;
point.Y -= CircleDiameter / 2;
using (var pen = new Pen(Color.Tomato, PenWidth))
using (var brush = new SolidBrush(Color.White))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawEllipse(pen, point.X, point.Y, CircleDiameter, CircleDiameter);
graphics.FillEllipse(brush, point.X, point.Y, CircleDiameter, CircleDiameter);
}
}
}
Update 1:
So I updated the code to use the Paint event which has the foreach loop. However, I don't Invalidate (and Paint) every time a circle is added - there's no need for that. Just adding a circle by drawing means the control only invalidates and re-paints the region where the new circle was added.
Try setting a breakpoint on the DrawAllPoints method. You'll see it only happens during full invalidation operations such as minimizing and restoring.
Update 2:
After further chat, I agree the Invalidate method is superior. Code updated to use Invalidate with a rectangle to invalidate.
And now it's looking very much like the OP :)

Drawing a new circle bitmap at the click location while preserving previously drawn circles

I am trying to draw circles using Bitmap.
Each time I click the mouse, the circle I previously drew is moved to the new position.
What I want to happen is: Each time I click the mouse, a new circle is created/drawn at the position I clicked and all previously drawn circles remain without moving.
I am working with the following code:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace multirectangle
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
Bitmap background;
Graphics scG;
Rectangle rectangleObj;
private Point clickCurrent = Point.Empty;
private Point clickPrev = Point.Empty;
private void Form1_Load(object sender, EventArgs e)
{
background = new Bitmap(Width, Height);
rectangleObj = new Rectangle(10, 10, 30, 30);
scG = Graphics.FromImage(background);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
if (clickPrev == Point.Empty) return;
rectangleObj.X = clickPrev.X - rectangleObj.Height / 2;// +radius;
rectangleObj.Y = clickPrev.Y - rectangleObj.Width / 2;
Refresh();
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.DrawImage(Draw(), 0, 0);
}
public Bitmap Draw()
{
Graphics scG = Graphics.FromImage(background);
Pen myPen = new Pen(System.Drawing.Color.Red, 3);
scG.Clear(SystemColors.Control);
scG.DrawEllipse(myPen, rectangleObj);
return background;
}
}
}
Your English was a little confusing. If I'm understanding your problem correctly, right now the only thing that's being drawn is the new circle where the click was, and you want all the old ones to persist as well? In which case, there are two options:
Don't clear the bitmap before you draw. scG.Clear(SystemColors.Control); will clear the bitmap you just drew. If you remove that line and don't clear the bitmap, then the next time you click, it will then draw the new ellipse right on top of the last bitmap.
If you want a fresh drawing/bitmap everytime, you would need a list of your rectangleObj . Each time you click, you add that point to your rectangleObj collection. Then in your draw method, you would iterate through the collection and draw all of them.
I notice a few things. First, in Form1_MouseDown(), you have this:
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
You are overwriting the old position (clickPrev) before you even save it. If you want to keep both positions, you should put them in a simple structure, like a List. When you get a new point, just Add() it to the list. Then, in your Draw() routine, loop over all the elements in the list and draw them all.
If you just want two positions--and only two--just swap your statements like this:
clickPrev = clickCurrent;
clickCurrent = PointToClient(Cursor.Position);
And you'll have to allocate another rectangle object for the drawing, although it would make more sense to take care of this in the Draw() routine.
Swap the position of the following statements
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
I think you are assigning the clickCurrent to clickPrevious after you initialize clickCurrent. It needs to be the other way.
Please try this
Rectangle rectangleObj;
Bitmap background;
Graphics scG;
Pen myPen;
private void Form1_Load(object sender, EventArgs e)
{
rectangleObj = new Rectangle(10, 10, 30, 30);
background = new Bitmap(Width, Height);
scG = Graphics.FromImage(background);
myPen = new Pen(Color.Red, 3);
BackgroundImage = background;
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
var point = PointToClient(Cursor.Position);
rectangleObj.X = point.X - rectangleObj.Height / 2;
rectangleObj.Y = point.Y - rectangleObj.Width / 2;
scG.DrawEllipse(myPen, rectangleObj);
Refresh();
}
OnPaint and Draw methods removed. As well as clickCurrent and clickPrev fields.
When you change the form size (for example, maximize it), Bitmap and Graphics remain the same, so you get this effect. To avoid this, you need to add the event handler
private void Form1_SizeChanged(object sender, EventArgs e)
{
background = new Bitmap(Width, Height);
scG = Graphics.FromImage(background);
BackgroundImage = background;
}
Note that each time you resize the form, all previously drawn is erased. If this is undesirable, a different approach is needed for drawing. Let me know, I will give another example.

How to make a simple magnifier in C#

I followed the following in post on"Creating a screen magnifier".
Therefore I have this code.
It is not copy & pasted from the post. I have also added a timer so the form is not blank.
However I have found some problems.
It doesn't zoom in very much. I would like to have a larger zoom. An adjustable zoom setting will be optimal, but I can make that myself if I know how to zoom in more.
The center of the form is not always the tip of the cursor like I want it would be. Is there anyway I can Fix this?
Here is the code I have got now.
Graphics g;
Bitmap bmp;
private void Timer1_Tick(object sender, EventArgs e)
{
bmp = new Bitmap(250, 200);
g = this.CreateGraphics();
g = Graphics.FromImage(bmp);
g.CopyFromScreen(MousePosition.X , MousePosition.Y , 0, 0, new Size(300, 300));
pictureBox1.Image = bmp;
}
The results seem to be exactly the same to this software that I found during my research.the link, It takes you to a Japanese webpage.
You're going to have to play around with the various numbers in the example in order to see what effect they have on the output. It'll help to turn them into variables so you can play with them more easily. Here is a good start, no promises that it works, but it'll give you a good place to start experimenting until you get what you want.
Graphics g;
Bitmap bmp;
private void Timer1_Tick(object sender, EventArgs e)
{
var endWidth = 300;
var endHeight = 300;
var scaleFactor = 2; //perhaps get this value from a const, or an on screen slider
var startWidth = endWidth / scaleFactor;
var startHeight = endHeight / scaleFactor;
bmp = new Bitmap(startWidth, startHeight);
g = this.CreateGraphics();
g = Graphics.FromImage(bmp);
var xPos = Math.Max(0, MousePosition.X - (startWidth/2)); // divide by two in order to center
var yPos = Math.Max(0, MousePosition.Y - (startHeight/2));
g.CopyFromScreen(xPos, yPos, 0, 0, new Size(endWidth, endWidth));
pictureBox1.Image = bmp;
}

How to instantiate images upon user click in windows forms

I have small Image for a circle and I want to make the following:
Whenever some place on my form is clicked, I want to add a new instance of that circle in that place if there is no other circle there already.
I was thinking about a list of Circles and when that click happens i check the list to see if none of its circles is overlapping before adding the new one but I don't have any experience with forms so i don't know what would be the best approach for that.
You can build up a GraphicsPath and check if the clicked point is inside any of its parts with the IsVisible method.
This code also builds up a list of the points and to draws the image to each of it in the Paint event. If you let the GraphicsPath do the drawing you uncomment the DrawPath line and delete these //** list related lines.
GraphicsPath GP = new GraphicsPath();
List<Point> PL = new List<Point>(); //**
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
int diameter = 22; // put in the size of your circle
Size s = new Size(diameter, diameter);
if (!GP.IsVisible(e.Location))
{
Point middle = new Point(e.X - diameter / 2, e.Y - diameter / 2);
GP.AddEllipse(new Rectangle(middle, s));
PL.Add(middle); //**
}
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// e.Graphics.DrawPath(Pens.Firebrick, GP);
Image img = new Bitmap("D:\\circle22.png"); //**
foreach(Point pt in PL) e.Graphics.DrawImage(img, pt); //**
img.Dispose(); //**
}

Erase loaded image part by part in Windows Phone 7

I want to erase image loaded on canvas on mouse move and display the background image in wp7.
in C# MakeTransparent method is available.
But in windows phone no such method is available.
what to do ?
Canvas.Opacity = 0; //This will make the control transparent
Also you can use .Opacity function almost every visual user control (Image, Grid, Lists etc.)
Cleverly, you can use canvas_MouseMove event for an eraser effect.
Just subscribe to canvas mousemove event like in see the example below
//Canvas MouseMove Event
private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
{
currentPoint = e.GetPosition(this.canvas);
//Initialize line according to currentpoint position.
Line line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = oldPoint.X, Y2 = oldPoint.Y };
line.StrokeDashCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeThickness = 10;
line.Stroke = new SolidColorBrush(Colors.White) ;
////////////////////////////////
//Set color & thickness of line.
//Line add in canvas children to draw image & assign oldpoint.
this.canvas.Children.Add(line);
oldPoint = currentPoint;
}
Not too sure with it but still, I hope it helps.

Categories

Resources