I know how to get the cursor's position :
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
But this is relative to the screen. How do i get the coordinates relative to my Form?
Use the Control.PointToClient method. Assuming this points to the form in question:
var relativePoint = this.PointToClient(new Point(X, Y));
Or simply:
var relativePoint = this.PointToClient(Cursor.Position);
I would use PointToClient like this:
Point p = yourForm.PointToClient(Cursor.Position);
//if calling it in yourForm class, just replace yourForm with this or simply remove it.
How about trying like this using the Control.PointToClient:-
public Form()
{
InitializeComponent();
panel = new System.Windows.Forms.Panel();
panel.Location = new System.Drawing.Point(90, 150);
panel.Size = new System.Drawing.Size(200, 100);
panel.Click += new System.EventHandler(this.panel_Click);
this.Controls.Add(this.panel);
}
private void panel_Click(object sender, EventArgs e)
{
Point point = panel.PointToClient(Cursor.Position);
MessageBox.Show(point.ToString());
}
Related
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 :)
I would like to know how to set my form position. i have tried to do the following:
this.Location = Point;
or:
Form2.Left = Point.X;
Form2.Top = Point.Y;
Form2.ShowDialog();
This is does not work. What do I do wrong?
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form();
form2.StartPosition = FormStartPosition.Manual;
form2.Left = 500;
form2.Top = 500;
form2.ShowDialog();
}
to set the position programmatically , you should set StartPosition to FormStartPosition.Manual as shown below :
Form myform = new Form()
{
Size = new Size(200,200),
StartPosition = FormStartPosition.Manual,
Location = new Point(10,10) // or Cursor.Position if you want to set it to cursor position
}
Try this:
private void Form_Load(object sender, EventArgs e)
{
this.SetDesktopLocation(x, y);
}
The first approach of you works anyways.
this.Location = new Point(/*XPosition*/, /*YPosition*/);
You can set it like this:
form1.Location = new Point(4, 370);
// Point(specify location of x, specify location of y)
// with object initializer
var frmUsers = new FrmUsers
{
StartPosition = FormStartPosition.Manual,
Location = new Point(0, 0)
};
// or
var frmUsers = new FrmUsers();
frmUsers.StartPosition = FormStartPosition.Manual;
frmUsers.Location = new Point(0, 0);
Hello I have got this code:
private Label newLabel = new Label();
Int32 mouseX;
Int32 mouseY;
private void form_MouseMove(object sender, MouseEventArgs e)
{
mouseY = Cursor.Position.Y;
mouseX = Cursor.Position.X;
}
private void button1_Click(object sender, EventArgs e)
{
int txt = Int32.Parse(textBox1.Text);
for (int i = 0; i < txt; i++)
{
newLabel = new Label();
newLabel.Location = new Point(mouseY, mouseX);
newLabel.Size = new System.Drawing.Size(25, 25);
newLabel.Text = i.ToString();
newLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
newLabel.ForeColor = Color.Red;
newLabel.Font = new Font(newLabel.Font.FontFamily.Name, 10);
newLabel.Font = new Font(newLabel.Font, FontStyle.Bold);
newLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
newLabel.MouseMove += new MouseEventHandler(this.MyControl_MouseMove);
newLabel.MouseDown += new MouseEventHandler(this.MyControl_MouseDown);
this.Controls.Add(newLabel);
}
}
And I try to make it create a label according to where the mouse is, but it seems that it is creating with location within the whole display. I thought that if I assign the coordinates to form mouse move it would get coordinates within the form.
May someone help me solve this out please?
The Cursor.Position coordinate is relative to the whole screen. You need a position relative to the upper left of your form. You could simply get that info from the MouseEventArgs passed to your MouseMove event handler
private void form_MouseMove(object sender, MouseEventArgs e)
{
mouseY = e.Location.Y;
mouseX = e.Location.X;
}
The MouseEventArgs.Location property is (according to MSDN)
A Point that contains the x- and y- mouse coordinates, in pixels,
relative to the upper-left corner of the form.
Steve is correct, and in order to convert screen coordinates to control or form coordinates you can use method described here:
How to convert screen coordinates to form relative coordinates (winforms)?
In your case:
Point clientPoint = PointToClient( new Point( e.X, e.Y ) );
I'm trying to draw out pictureboxes during runtime as I can do right from the toolbox. That is, set the location at the mouselocation, resize it as I hold down the button and drag it across the form. All that I've accomplished in the code. But as I start the draw the second picturebox the first one disappears, I want to keep adding more pictureboxes to the form, if I remove the MouseMove event and move PictureBox pb1 = new PictureBox(); down to the MouseDown event it lets me add more buttons, but then I can't resize them obviously.
int cellSize = 10;
int numOfCells = 500;
PictureBox pb1 = new PictureBox();
int Mx, My;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
}
public void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Point p = new Point(e.X, e.Y);
Mx = p.X;
My = p.Y;
int xSnap = (Mx / cellSize) * cellSize;
int ySnap = (My / cellSize) * cellSize;
pb1.BackColor = (Color.Red);
if (e.Button == MouseButtons.Left)
{
pb1.Size = new Size(xSnap - pb1.Left, ySnap - pb1.Top);
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
Point p = new Point(e.X, e.Y);
Mx = p.X;
My = p.Y;
int xSnap = (Mx / cellSize) * cellSize;
int ySnap = (My / cellSize) * cellSize;
pb1.Location = new Point(xSnap, ySnap);
pictureBox1.Controls.Add(pb1);
}
You're always re-using the same PictureBox instance.
You need to create a new instance every time you want to add a new one, by writing new PictureBox().
It's been a mess to show a DialogBox at the center of its parent form. Here is a method to show a dialog.
I am positioning its parent to center but not able to center the DialogBox
private void OpenForm(Object point, Object height, Object width)
{
FormLoading frm = new FormLoading();
Point temp = (Point)point;
Point location = new Point(temp.X + (int)((int)width) / 2,
temp.Y + (int)((int)height) / 2);
frm.Location = location;
frm.ShowDialog();
}
private void btnView_Click(object sender, EventArgs e)
{
try
{
ThreadStart starter= delegate { OpenForm(currentScreenLocation,
this.Height, this.Width); };
Thread t = new Thread(starter);
t.Start();
////// Some functionality here...
t.Abort();
}
catch (Exception)
{
}
}
You might want to check the Form.StartPosition property.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.startposition.aspx
something along the lines of:
private void OpenForm(Form parent)
{
FormLoading frm = new FormLoading();
frm.Parent = parent;
frm.StartPosition = FormStartPosition.CenterParent;
frm.ShowDialog();
}
This of course requires setting the form's parent.
form1.StartPosition = FormStartPosition.CenterScreen;
See http://msdn.microsoft.com/en-us/library/system.windows.forms.form.startposition(v=vs.110).aspx
if you are making a custom MessageBox,you can simply put this:
CenterToParent();
in your custom MessageBox formload() method.
In addition, if you want to set up arbitrary location you can use this
FormLoading frm = new FormLoading();
Point location = new Point(300, 400);
frm.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
frm.Location = location;
frm.ShowDialog();
NewForm.Show();
NewForm.Top = (this.Top + (this.Height / 2)) - NewForm.Height / 2;
NewForm.Left = (this.Left + (this.Width / 2)) - NewForm.Width / 2;