Im using winforms and GMap.NET in order to learn how to use it.
I have a mouse click action on the Gmap controller and when the user
clicks on some place on the map i'm getting the x y coordinates,
converting them to latitude and longtitude and then draw the marker
on the map.
But the marker is not placed in the real mouse cursor location,
it looks like the marker has a default place and that's it.
I tried to move the mouse to another place and when I clicked the marker
was also created at wrong place (it was the same as the first marker)
I tried to use gmap.Overlays.clear() before getting the coordinates
and place the marker but this wasn't helpful.
private void gmap_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
double lat = gmap.FromLocalToLatLng(e.X, e.Y).Lat;
double lng = gmap.FromLocalToLatLng(e.X, e.Y).Lng;
GMapOverlay markerOverlay = new GMapOverlay("markers");
GMarkerGoogle marker = new GMarkerGoogle(new
GMap.NET.PointLatLng(lat, lng),
GMarkerGoogleType.green_pushpin);
markerOverlay.Markers.Add(marker);
gmap.Overlays.Add(markerOverlay);
}
}
Add the overlay first, then add the marker. No need to do extra operations.
gmap.Overlays.Add(markerOverlay);
markerOverlay.Markers.Add(marker);
By switching around the statements you'll achieve the right positioning. The guess about a default position is somewhat true, I guess. The overlay has not been "hooked" to the map and gets a marker positioned in it beforehand. That's why the position is usually off initially.
Just use this code:
myMap.UpdateMarkerLocalPosition(marker)
This is how i do it and it works fine. The Obj.defaultOrigin is just LatLong location.
gm = new GoogleMap(Obj.defaultOrigin);
overlay = new GMapOverlay(gm, "mapIcon");
marker = new GoogleMap.GMapMarkerImage(Obj.defaultOrigin, Image.FromFile(Obj.path + #"\resources\images\mapIcon.png"));
overlay.Markers.Add(marker);
gm.Overlays.Add(overlay);
gm.MouseClick += (s, e) =>
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
GMap.NET.PointLatLng point = gm.FromLocalToLatLng(e.X, e.Y);
marker.Position = point;
}
};
You should declare overlay outside mouseclick event:
GMapOverlay markersOverlay = new GMapOverlay("markers");
private void gmap_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
double lat = gmap.FromLocalToLatLng(e.X, e.Y).Lat;
double lng = gmap.FromLocalToLatLng(e.X, e.Y).Lng;
// GMapOverlay markerOverlay = new GMapOverlay("markers"); Your code here
GMarkerGoogle marker = new GMarkerGoogle(new
GMap.NET.PointLatLng(lat, lng),
GMarkerGoogleType.green_pushpin);
gmap.Overlays.Add(markerOverlay); //Change position of this line first
markerOverlay.Markers.Add(marker);
}
}
Related
so I have this Window Application that simulates mouse movement, I made a few tests and managed to "record" mouse movement and play it once recorded. Now I wanna make a Viewlist with 2 columns ("X" and "Y) containing the coords of the route I want my mouse to follow. Coordinates can be added throught "ycoord" and "xcoord" textlabels and can be added with "button1" button to the viewlist. There's also a "button2" that works as a "toggle" button to turn it on and off. So, I want is that, every time I press left click form mouse (LButton) the movement runs as long as I hold this button, and, if I hold it again it starts over again. I already managed the textlabels to place content into the viewlist, but I don't know how to read the viewlist and convert them into mouse movement coords.
Thanks in advance for the help!
You have to save the X,Y coords in a List, so you can create a list of points, then you have to iterate it and use it with:
Look at the object Cursor here
Also you have the code:
private void MoveCursor()
{
// Set the Current cursor, move the cursor's Position,
// and set its clipping rectangle to the form.
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X - 50, Cursor.Position.Y - 50);
Cursor.Clip = new Rectangle(this.Location, this.Size);
}
Try this:
public partial class Form1 : Form
{
private List<Point> _points = null;
public Form1()
{
InitializeComponent();
_points = new List<Point>();
this.MouseMove += Form1_MouseMove;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
//Save the point
_points.Add(new Point(e.X, e.Y));
}
private void PerformRecord()
{
foreach (var point in _points)
{
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(point.X, point.Y);
}
}
private void button1_Click(object sender, EventArgs e)
{
PerformRecord();
}
}
I have an X-Y plot in a .NET 4.0 WinForms chart control. I am trying to implement rubber-band selection, so that the user could click and drag the mouse to create a rectangle on the plot, thus selecting all the points that lie within this rectangle.
While I was able to code up the drawing of the rectangle, I am now trying to identify the Datapoints that lie within this rectangle. Here is the relevant code:
public partial class Form1 : Form
{
System.Drawing.Point _fromPosition;
Rectangle _selectionRectangle;
public Form1()
{
InitializeComponent();
}
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
// As the mouse moves, update the dimensions of the rectangle
if (e.Button == MouseButtons.Left)
{
Point p = e.Location;
int x = Math.Min(_fromPosition.X, p.X);
int y = Math.Min(_fromPosition.Y, p.Y);
int w = Math.Abs(p.X - _fromPosition.X);
int h = Math.Abs(p.Y - _fromPosition.Y);
_selectionRectangle = new Rectangle(x, y, w, h);
// Reset Data Point Attributes
foreach (DataPoint point in chart1.Series[0].Points)
{
point.BackSecondaryColor = Color.Black;
point.BackHatchStyle = ChartHatchStyle.None;
point.BorderWidth = 1;
}
this.Invalidate();
}
}
private void chart1_MouseDown(object sender, MouseEventArgs e)
{
// This is the starting position of the rectangle
_fromPosition = e.Location;
}
private void chart1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(new Pen(Color.Blue, 2), _selectionRectangle);
foreach (DataPoint point in chart1.Series[0].Points)
{
// Check if the data point lies within the rectangle
if (_selectionRectangle.Contains(???))))
{
// How do I convert DataPoint into Point?
}
}
}
}
What I am trying to do is query each DataPoint in the series and check if it lies within the Rectangle. Here, I am unable to transform each DataPoint into its corresponding Point. It seems pretty straightforward, so I am either missing something basic here or approaching the problem incorrectly.
I should also add that I referred to similar questions here and here, but they do not talk about how to actually identify DataPoints within the rectangle.
Any direction would be appreciated!
I have shown how to cheat the Chart into helping to get at the coordinates of DataPoints in the Paint event here.
But as you want to pick them up in the Paint event anyway, no cheating is needed..:
I define a List to collect the lassoed DataPoints:
List<DataPoint> dataPoints = new List<DataPoint>();
And I clear it on each new selection:
void chart1_MouseDown(object sender, MouseEventArgs e)
{
_fromPosition = e.Location;
dataPoints.Clear();
}
At the end I can write out the results:
void chart1_MouseUp(object sender, MouseEventArgs e)
{
foreach(DataPoint pt in dataPoints)
Console.WriteLine("found:" + pt.ToString() +
" at " + chart1.Series[0].Points.IndexOf(pt));
}
And in the Paint event we make use of the ValueToPixelPosition method of the two axes:
void chart1_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(Color.Blue, 2) // dispose of my Pen
{DashStyle = System.Drawing.Drawing2D.DashStyle.Dot})
e.Graphics.DrawRectangle(pen, _selectionRectangle);
foreach (DataPoint point in chart1.Series[0].Points)
{ // !! officially these functions are only reliable in a paint event!!
double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(point.XValue);
double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(point.YValues[0]);
PointF pt = new PointF((float)x,(float)y);
// Check if the data point lies within the rectangle
if (_selectionRectangle.Contains(Point.Round(pt)))
{
if (!dataPoints.Contains(point)) dataPoints.Add(point);
}
}
}
I'm fiddling around with GMap.NET. I have a gmap.net map control on my form. There is a red x (or plus sign, if you will) in the middle of the map. I added a method that will put a marker wherever I click on the map. However, the customer would rather have a "pushpin" button on the form that the user will click, and the marker will be added where the red X is located (which is always the center of the map control, it seems). The map is drag-able and zoom-able, so the marker will be added wherever the red x is at that time.
Right now, when my program adds a marker, it translates the lat and lng from the FromLocalToLatLng gmap method:
private void gmap_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
var lat = gmap.FromLocalToLatLng(e.X, e.Y).Lat;
var lng = gmap.FromLocalToLatLng(e.X, e.Y).Lng;
var markerOverlay = new GMapOverlay("markers");
var marker = new GMarkerGoogle(new
PointLatLng(lat, lng),
GMarkerGoogleType.green_pushpin)
{
ToolTipText = "Kevin Jennings",
ToolTipMode = MarkerTooltipMode.OnMouseOver
};
gmap.Overlays.Add(markerOverlay);
markerOverlay.Markers.Add(marker);
}
In this case, though, I'm wondering if there's a way to add the marker at the map center?
I figured it out. You can get the center of the map by using the following code:
var center = gmap.Position;
Once I had the center, all I needed to do was add a marker at that position, like this:
var marker2 = new GMarkerGoogle(new
PointLatLng(center.Lat, center.Lng),
GMarkerGoogleType.green_pushpin)
{
ToolTipText = "Kevin Jennings",
ToolTipMode = MarkerTooltipMode.OnMouseOver
};
you need to use this
map.Zoom = 10;
map.Zoom = 9;
and your markers will position on the right direction..
complete code
var lat = mapa.FromLocalToLatLng(e.X, e.Y).Lat;
var lng = mapa.FromLocalToLatLng(e.X, e.Y).Lng;
MessageBox.Show(lat + " long :" + lng);
var markerOverlay = new GMapOverlay("markers");
var marker = new GMarkerGoogle(new
PointLatLng(lat, lng),
GMarkerGoogleType.green_pushpin)
{
ToolTipText = "Ubicacion depto",
ToolTipMode = MarkerTooltipMode.OnMouseOver
};
markerOverlay.Markers.Add(marker);
map.Overlays.Add(markerOverlay);
map.Zoom = 10;
map.Zoom = 9;
}
My task is to draw a graph in chart control using mouse and retrieve the (X,Y) points from the Graph.
I tried of drawing a graph with mouse.
Here is the normal Graph looks like.
After drawing with mouse, it looks like :
The code which i used to draw graph is :
private void Form1_Load(object sender, EventArgs e)
{
chart1.ChartAreas[0].AxisX.Minimum =0170101;
chart1.ChartAreas[0].AxisX.Maximum =0175951;
chart1.ChartAreas[0].AxisY.Minimum=0780101;
chart1.ChartAreas[0].AxisY.Maximum=0785951;
double range = chart1.ChartAreas[0].AxisX.Maximum - chart1.ChartAreas[0].AxisX.Minimum;
chart1.ChartAreas[0].AxisX.Interval = range / 5;
range = chart1.ChartAreas[0].AxisY.Maximum - chart1.ChartAreas[0].AxisY.Minimum;
chart1.ChartAreas[0].AxisY.Interval = range / 5;
}
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (!(FirstPoint == null))
{
Graphics g = chart1.CreateGraphics();
Pen ErasePen = new Pen(Color.Transparent);
g.DrawLine(ErasePen, FirstPoint, TempPoint);
TempPoint = new Point(e.X, e.Y);
this.Refresh();
}
}
private void chart1_MouseDown_1(object sender, MouseEventArgs e)
{
FirstPoint = new Point(e.X, e.Y);
TempPoint = new Point(e.X, e.Y);
}
private void chart1_MouseUp_1(object sender, MouseEventArgs e)
{
LineEndPoints Line = new LineEndPoints
{
StartPoint = FirstPoint,
endPont = new Point(e.X, e.Y)
};
LinesList.Add(Line);
// FirstPoint = null;
this.Refresh();
}
private void chart1_Paint_1(object sender, PaintEventArgs e)
{
foreach (LineEndPoints line in LinesList)
{
e.Graphics.DrawLine(Pens.Green, line.StartPoint, line.endPont);
}
if (!(FirstPoint == null))
{
e.Graphics.DrawLine(Pens.Red, FirstPoint, TempPoint);
}
}
When I used to draw a graph it is moving away from the max and min values of the chart control.
Now what I need to know is:
1) My graph should not move away from the X and Y axis points of the chart control.
2) I need to know the X,Y points of the graph which is drawn with respect to chart axis but not with form axis.
I use C# VS 2010 Win-forms.
Chart uses a different coordinate system for its content than its Control surface, ie the mouse loacation; there are conversion functions but they come with a caveat: They are only guaranteed to work in the Paint events..
PixelPositionToValue
ValueToPixelPosition
Here is an example that translates the pixel points to chart point values. You can see the two graphics overlaying very nicely: The DataPoints are connected in blue lines and the pixel points by dotted red lines..:
public Form1()
{
InitializeComponent();
chart1.Series[0].ChartType = SeriesChartType.Line;
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Maximum = 500;
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Maximum = 500;
}
List<Point> points = new List<Point>();
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
points.Add(e.Location);
chart1.Invalidate();
}
private void chart1_Paint(object sender, PaintEventArgs e)
{
chart1.Series[0].Points.Clear();
foreach(Point pt in points)
{
double dx = chart1.ChartAreas[0].AxisX.PixelPositionToValue(pt.X);
double dy = chart1.ChartAreas[0].AxisY.PixelPositionToValue(pt.Y);
chart1.Series[0].Points.AddXY(dx, dy);
}
if (points.Count > 1)
using (Pen pen = new Pen(Color.Red, 2.5f))
e.Graphics.DrawLines(pen, points.ToArray());
}
Note that this will always clear the DataPoints and recreate them from the pixel points list, according to the current chart layout using the PixelPositionToValue method. The layout will always change when things like label sizes, other scaling, other minimum/maximum values etc change.
Maybe you really want to work the other way round, that is change the clicked points using the ValueToPixelPosition.
Here is the modified example that keeps the DataPoints and recalculates the pixel points:
List<Point> points = new List<Point>();
Point lastPoint = Point.Empty;
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
lastPoint = e.Location;
chart1.Invalidate();
}
private void chart1_Paint(object sender, PaintEventArgs e)
{
// if we have a new point, convert to DataPoint and add to Series.Points:
if (lastPoint != Point.Empty)
{
double dx = chart1.ChartAreas[0].AxisX.PixelPositionToValue(lastPoint.X);
double dy = chart1.ChartAreas[0].AxisY.PixelPositionToValue(lastPoint.Y);
chart1.Series[0].Points.AddXY(dx, dy);
}
lastPoint = Point.Empty;
// now recalculate all pixel points:
points.Clear();
foreach (DataPoint pt in chart1.Series[0].Points)
{
double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue);
double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]);
points.Add(new Point((int)x, (int)y));
}
if (points.Count > 1)
using (Pen pen = new Pen(Color.Red, 2.5f))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
e.Graphics.DrawLines(pen, points.ToArray());
}
}
This makes a lot more sense, since the DataPoints are always bound to the chart's scaling, so they are the 'real thing'. When you resize the Chart the DataPoints and the Graphic they make up are scaled as usual and the drawn pixel points follow perfectly:
(When you resize the first version you can see how nothing is being scaled up or down and only the chart's grid lines change..)
Note that I set up a few things to start with, so that not every point I add enforces too many layout changes. Also note that sometimes there still occurs a feedback loop when the new points change e.g. the label sizes, which enforces a layout change and the paint loop.. To fix this you should probably control the labels' formats!
Also note that both conversion methods only work (correctly) in the Paint event(s), probably because only then the current layout is being settled.
Can someone help me solve the question: How can I divide the figure into the fields, so depending on which area will be mouse click it will be carried out a specific event?
private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//if (!isDragging)
{
//creating of my user control element
NodePicture node = new NodePicture();
node.Width = 100;
node.Height = 100;
//use cursor position as the center of the figure
Point point = e.GetPosition(this);
node.SetValue(Canvas.TopProperty, point.Y - node.Height / 2);
node.SetValue(Canvas.LeftProperty, point.X - node.Width / 2);
node.MouseLeftButtonDown += controlReletionshipsLine;
LayoutRoot.Children.Add(node);
}
}
private void controlReletionshipsLine(object sender, MouseButtonEventArgs e)
{
//creating parant element of node
ParentNode parentNode = new ParentNode();
//creating connected element of the node
ConnectedNode connectedNode = new ConnectedNode();
//creating node element
NodePicture node = (NodePicture)sender;
//getting the relative position of the element
Point point = e.GetPosition(this);
You can either divide the object mathematically, using the mouse position "relative to the object" to decide where you clicked, or you can overlay a number of polygons, each with the colour alpha-channel set to 1% (so they can be hit-tested, but are not visible).
As you simply want to see which quarter of the circle you clicked in, call GetPosition on the LeftMouseButtonDown event args, passing the control itself as the parameter. This will give you back a Point object with the position relative to the top left corner of the control.
Then it is just a matter of seeing which quarter it is in:
private void ControlX_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get the relative position of the element
Point point = e.GetPosition(sender as UIElement);
if (point.X > control.Width/2)
{
if (point.Y > control.Height/2)
{
// You are in the bottom right quarter
}
else
{
// You are in the top right quarter
}
}
else
{
if (point.Y > control.Height/2)
{
// You are in the bottom left quarter
}
else
{
// You are in the top left quarter
}
}
}
In the sample code you sent me (in controlReletionshipsLine) you have:
// getting the relative position of the element
Point point = e.GetPosition(this);
It should have been:
// getting the relative position of the element
Point point = e.GetPosition(sender as UIElement);