Location information where mouse click on the map GMap.net - winforms

I'm working on Win Forms application along with GMap.net(a library that enables us to use Google Maps in Win Forms Application). Coming straight to the point, I be able to get the coordinates i.e (Latitude and Longitude) where my mouse click (left click).
private void gm1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
double lat = gm1.FromLocalToLatLng(e.X, e.Y).Lat;
double lng = gm1.FromLocalToLatLng(e.X, e.Y).Lng;
}
}
I did not find a way to get the location of that place i.e Country Name, city name etc.
I've searched the forum of Google maps but i did not find this issue answered.
Any

This will give you a list of the named places on the position you click on the map.
private void map_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
double lat = map.FromLocalToLatLng(e.X, e.Y).Lat;
double lng = map.FromLocalToLatLng(e.X, e.Y).Lng;
}
List<Placemark> plc = null;
var st = GMapProviders.GoogleMap.GetPlacemarks(map.FromLocalToLatLng(e.X, e.Y), out plc);
if (st == GeoCoderStatusCode.G_GEO_SUCCESS && plc != null)
{
foreach (var pl in plc)
{
if (!string.IsNullOrEmpty(pl.PostalCodeNumber))
{
Debug.WriteLine("Accuracy: " + pl.Accuracy + ", " + pl.Address + ", PostalCodeNumber: " + pl.PostalCodeNumber);
}
}
}
}

while using GMap.Net Libraries, coordinates are used for specific location using latitute and longitute. As question, even place name can be used to locate the position.
GMapControl.MapProvider = MapProviders.GoogleTerrainMapProvider.Instance
GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache
With Me.GMapControl
.Position = New GMap.NET.PointLatLng(latitute, longitute)
.SetPositionByKeywords("Nepal")
.Zoom = mp_zomlvl
.ShowCenter = False
End With
GMapControl.Refresh()
Remove code: .Position = New GMap.NET.PointLatLng(latitute, longitute)
for using .SetPositionByKeywords("Nepal")

Related

Why the GetCharIndexFromPosition() doesn't return properly for last character of textbox?

public partial class Form1 : Form
{
TextBox textBox;
public Form1()
{
InitializeComponent();
textBox = new TextBox() { Height = 30, Width = 200, Text = "Syncfusion Software", Font = new Font("Arial", 11) };
textBox.MouseMove += textBox_MouseMove;
this.Controls.Add(textBox);
}
void textBox_MouseMove(object sender, MouseEventArgs e)
{
var selectionStart = textBox.GetCharIndexFromPosition(e.Location);
textBox.SelectionStart = selectionStart;
textBox.SelectionLength = 0;
}
}
Here is my code, this is simple sample that i tried to get clear information about GetCharIndexFromPosition() method of TextBox.
In Mouse move, i get the char index position using the current mouse position of the textbox and set selection start of the textbox based on it. So that if i mouse move, then the selection start or caret position will be set based on the mouse move. But there was an issue with when mouse moved at the end of text, selection start is not set to last. it sets last but before.
For example, if a text box contains text "stack", then if mouse position is after the "k" then caret position should be at the end, but it displayed inbetween "c" and "k". GetCharIndexPosition() doesn't returns value properly for last character. Let me know solution for this
Thanks in Advance.
Regards,
Venkatesan R
This is a known documented behavior. The Remarks section of the GetCharIndexFromPosition method documentation contains the following Important note:
If the specified location is not within the client rectangle of the control, or is beyond the last character in the control, the return value is the index of the last character.
The workaround is to use the reverse method GetPositionFromCharIndex to adjust the returned index.
Something like this
void textBox_MouseMove(object sender, MouseEventArgs e)
{
var charIndex = textBox.GetCharIndexFromPosition(e.Location);
var charPosition = textBox.GetPositionFromCharIndex(charIndex);
if (e.Location.X > charPosition.X) charIndex++;
textBox.Select(charIndex, 0);
}
P.S. As a side note, I have no idea what this method is trying to achieve, but for sure it prevents the standard text selection by mouse behavior.
This ended up really bothering me, so I expanded Ivan Stoev's idea to a rather overengineered method that calculates the pixel width of the last character and divides it by two to accurately emulate the same behaviour as on the other characters.
The method was written for a drag/drop scenario, where the selection is adjusted to the drop position while hovering the mouse over.
// Cached, so it doesn't get recalculated on each moved pixel.
private Char _textBoxLastChar = '\0';
private Int32 _textBoxLastCharHalfWidth = 0;
private void TextBox_DragOver(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(DataFormats.UnicodeText))
return;
TextBox tb = sender as TextBox;
if (tb == null)
return;
Int32 textLen = tb.Text.Length;
if (textLen > 0 && _textBoxLastChar != tb.Text[textLen - 1])
{
_textBoxLastChar = tb.Text[textLen - 1];
_textBoxLastCharHalfWidth = (Int32)Math.Round(GetStringWidth(_textBoxLastChar.ToString(), tb.Font) / 2);
}
Point localPoint = tb.PointToClient(new Point(e.X, e.Y));
Int32 index = tb.GetCharIndexFromPosition(localPoint);
// fix for fact it returns the last char position when you go outside text bounds.
Int32 charPosition = tb.GetPositionFromCharIndex(index).X;
if (textLen != 0 && index == textLen - 1 && localPoint.X > charPosition + _textBoxLastCharHalfWidth)
index++;
if (!tb.Focused)
tb.Focus();
tb.SelectionStart = index;
tb.SelectionLength = 0;
}
public static Double GetStringWidth(String text, Font f)
{
//create a bmp / graphic to use MeasureString on
Single areaSize = f.Size * 20;
using (Bitmap b = new Bitmap(1, 1))
using (Graphics g = Graphics.FromImage(b))
{
SizeF sizeOfString = g.MeasureString(text, f, new SizeF(areaSize, areaSize), StringFormat.GenericTypographic);
return sizeOfString.Width;
}
}
Of course, if you ever change the font or font size of the text box, you'll have to reset _textBoxLastChar back to '\0'.

Get clicked point in Devexpress line chart without visible markers

I'm trying to get clicked point on a deveexpress 1.14 line chart in winforms. It works fine with LineSeriesView MarkerVisibility set to true, but I don't want the points to be marked like that, i want a smoth line. How can i get the Seriespoint without doing that?
private void chart_MouseClick(object sender, MouseEventArgs e) {
// Obtain the object being clicked.
ChartHitInfo hi = chart.CalcHitInfo(e.X, e.Y);
// Check whether it was a series point, and if yes -
// obtain its argument, and pass it to the detail series.
SeriesPoint point = hi.SeriesPoint; // hi.SeriesPoint IS NULL
if (point != null) {
// do stuff
}
}
The runtimeHitTesting is on for that chart
Thanks!
Hacked:
void chart_CustomDrawSeries(object sender, CustomDrawSeriesEventArgs e)
{
LineDrawOptions drawOptions = e.SeriesDrawOptions as LineDrawOptions;
if (drawOptions == null)
return;
drawOptions.Marker.Color = Color.Transparent;
drawOptions.Marker.BorderColor = Color.Transparent;
}
Remeber to set `this.chart.CacheToMemory = true; so the event don't fire all the time.

Determine if an open WPF window is visible on any monitor

Is there a way to determine if an open WPF window is currently visible in any of the desktop's connected monitors? By visible I mean that the window's bounds rectangle intersects with the desktop rectangle of any of the monitors.
I need this functionality to determine if a window needs to be repositioned because the monitor configuration (working areas bounds, monitor count) changed between restarts of my application (which saves window positions).
I have come up with the code below and it seems to work, but it has several problems:
I need to reference windows forms.
I need the desktop's DPI settings and transform the windows forms actual pixels to WPF virtual pixels.
I need an acutal Visual instance that already has been rendered to perform the transformation.
Do you know of a solution that gets rid of some or all of the 3 issues above?
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
internal static class Desktop
{
private static Size dpiFactor = new Size(1.0, 1.0);
private static bool isInitialized;
public static IEnumerable<Rect> WorkingAreas
{
get
{
return
Screen.AllScreens.Select(
screen =>
new Rect(
screen.WorkingArea.Left * dpiFactor.Width,
screen.WorkingArea.Top * dpiFactor.Height,
screen.WorkingArea.Width * dpiFactor.Width,
screen.WorkingArea.Height * dpiFactor.Height));
}
}
public static void TryInitialize(Visual visual)
{
if (isInitialized)
{
return;
}
var ps = PresentationSource.FromVisual(visual);
if (ps == null)
{
return;
}
var ct = ps.CompositionTarget;
if (ct == null)
{
return;
}
var m = ct.TransformToDevice;
dpiFactor = new Size(m.M11, m.M22);
isInitialized = true;
}
}
Usage of the (initialized) Desktop class:
private bool IsLocationValid(Rect windowRectangle)
{
foreach (var workingArea in Desktop.WorkingAreas)
{
var intersection = Rect.Intersect(windowRectangle, workingArea);
var minVisible = new Size(10.0, 10.0);
if (intersection.Width >= minVisible.Width &&
intersection.Height >= minVisible.Height)
{
return true;
}
}
return false;
}
Update
Using the virtual screen (SystemParameters.VirtualScreen*) does not work because when using multiple monitors the "desktop" is not a simple rectangle. It might be a polygon. There will be blind spots in the virtual screen because
the connected screens can have different resolutions
you can configure the position of each screen.
The code we use to do something similar uses information from SystemParameters, in particular SystemParameter.VirtualScreenLeft, Top, Width and Height.
If we have a saved Location and Size then we determine if the window is out of bounds like this:
bool outOfBounds =
(location.X <= SystemParameters.VirtualScreenLeft - size.Width) ||
(location.Y <= SystemParameters.VirtualScreenTop - size.Height) ||
(SystemParameters.VirtualScreenLeft +
SystemParameters.VirtualScreenWidth <= location.X) ||
(SystemParameters.VirtualScreenTop +
SystemParameters.VirtualScreenHeight <= location.Y);
I use this code snipped in my WPF project on startup; it's written in vb.net:
If My.Settings.RememberWindowPositionAndSize Then
If My.Settings.winMainWinState > 2 Then My.Settings.winMainWinState = WindowState.Normal
If My.Settings.winMainWinState = WindowState.Minimized Then My.Settings.winMainWinState = WindowState.Normal
Me.WindowState = My.Settings.winMainWinState
If My.Settings.winMainWinState = WindowState.Normal Then
Dim winBounds As New System.Drawing.Rectangle(CInt(My.Settings.winMainPosX), CInt(My.Settings.winMainPosY),
CInt(My.Settings.winMainSizeB), CInt(My.Settings.winMainSizeH))
For Each scr As System.Windows.Forms.Screen In System.Windows.Forms.Screen.AllScreens
If winBounds.IntersectsWith(scr.Bounds) Then
Me.Width = My.Settings.winMainSizeB
Me.Height = My.Settings.winMainSizeH
Me.Top = My.Settings.winMainPosY
Me.Left = My.Settings.winMainPosX
Exit For
End If
Next
End If
End If
and here is same (converted) code in C#
if (My.Settings.RememberWindowPositionAndSize) {
if (My.Settings.winMainWinState > 2)
My.Settings.winMainWinState = WindowState.Normal;
if (My.Settings.winMainWinState == WindowState.Minimized)
My.Settings.winMainWinState = WindowState.Normal;
this.WindowState = My.Settings.winMainWinState;
if (My.Settings.winMainWinState == WindowState.Normal) {
System.Drawing.Rectangle winBounds = new System.Drawing.Rectangle(Convert.ToInt32(My.Settings.winMainPosX), Convert.ToInt32(My.Settings.winMainPosY), Convert.ToInt32(My.Settings.winMainSizeB), Convert.ToInt32(My.Settings.winMainSizeH));
foreach (System.Windows.Forms.Screen scr in System.Windows.Forms.Screen.AllScreens) {
if (winBounds.IntersectsWith(scr.Bounds)) {
this.Width = My.Settings.winMainSizeB;
this.Height = My.Settings.winMainSizeH;
this.Top = My.Settings.winMainPosY;
this.Left = My.Settings.winMainPosX;
break;
}
}
}
}
This code checks if a window top left corner is inside the Virtual Screen box (the rectangle that includes all the available screens). It also takes care of multimonitor set ups where coordinates can be negative, for example primary monitor on the right or on the bottom.
bool valid_position =
SystemParameters.VirtualScreenLeft <= saved_location.X &&
(SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth) >= saved_location.X &&
SystemParameters.VirtualScreenTop <= saved_location.Y &&
(SystemParameters.VirtualScreenTop + SystemParameters.VirtualScreenHeight) >= saved_location.Y;

How do I change the sound file for my windows form application using combo box?

I am developing a Windows Form Application. Currently I am working on the Settings aspect for my windows form app. On the settings form, I would be able to toggle the alert tone for my application. The default sound code is as follows
public String defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\applause-2.wav";
As for the settings, I have included 2 default tones for the user to select through a combo box. The code for the combo box are as follows,
private void comboBoxSound_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxSound.SelectedIndex == 0)
{
ReportStatus("Alert tone changed to 'Beep(1)'!");
backgroundFormObject.getSetting().defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\beep-1.wav";
}
else
{
ReportStatus("Alert tone changed to 'Beep(2)'!");
backgroundFormObject.getSetting().defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\beep-2.wav";
}
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
Stream stream = File.Open(appPath + "\\setting.sd", FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, backgroundFormObject.getSetting());
stream.Close();
}
Why is it that whenever I select another tone, and I play the sound, the effect is still the same as the original alert tone which is applause. Do I have to wait for the file to load finish before I play?
managed to solve it myself using the following code
private void comboBoxSound_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxSound.SelectedIndex == 0)
{
ReportStatus("Alert tone changed to 'Beep(1)'!");
settingObject.defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\beep-1.wav";
}
else
{
ReportStatus("Alert tone changed to 'Beep(2)'!");
settingObject.defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\beep-2.wav";
}
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
Stream stream = File.Open(appPath + "\\setting.sd", FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, settingObject);
stream.Close();
}

wp7, silverlight, Why event fires twice?

In this case when user click some UIElement I want this element yo be surrounded by dashed border. If there is some other object surrounded then this code removes it first.
Everything is fine but "private void activateElem" fires twice and I have no idea why. Maybe somebody can help, I really have no more ideas.
Anybody knows some ideas to debug issues like this? Maybe there is some way to print out all events queue. There is silverlight spy but I think it doesn't work for windows phone 7.
My code:
public class ManipulationEngine
{
private Canvas sheet;
private static FrameworkElement current_active_element;
public ManipulationEngine(Canvas sheet)
{
this.sheet = sheet;
foreach (FrameworkElement elem in sheet.Children)
{
elem.MouseLeftButtonUp += new MouseButtonEventHandler(activateElem);
}
}
private void activateElem(object sender, MouseButtonEventArgs e)
{
FrameworkElement elem = sender as FrameworkElement;
if (current_active_element != null)
{
desactivateElem();
}
Grid grid = new Grid();
Rectangle recentagle = new Rectangle();
grid.SetValue(Canvas.TopProperty, (double)elem.GetValue(Canvas.TopProperty) - 10);
grid.SetValue(Canvas.LeftProperty, (double)elem.GetValue(Canvas.LeftProperty) - 10);
DoubleCollection stroke = new DoubleCollection();
stroke.Add(4);
stroke.Add(2);
recentagle.StrokeDashArray = stroke;
grid.Children.Add(recentagle);
sheet.Children.Remove(elem);
elem.Margin = new Thickness(10);
grid.Children.Add(elem);
sheet.Children.Add(grid);
current_active_element = elem;
}
private void desactivateElem()
{
if (current_active_element != null)
{
Grid grid = VisualTreeHelper.GetParent(current_active_element) as Grid;
grid.Children.Remove(current_active_element);
sheet.Children.Remove(grid);
current_active_element.SetValue(Canvas.TopProperty, (double)grid.GetValue(Canvas.TopProperty) + 10);
current_active_element.SetValue(Canvas.LeftProperty, (double)grid.GetValue(Canvas.LeftProperty) + 10);
current_active_element.Margin = new Thickness(0);
sheet.Children.Add(current_active_element);
current_active_element = null;
}
}
I'd really advise looking into the Parts and States model. You may be able to do this with a button, or perhaps a radio button.
Usually if you're coding changes to the visual tree, you're not doing it right.
Karen Corby dealt with this very clearly at MIX08, take a look!
http://archive.visitmix.com/blogs/2008Sessions/T20/
Luke

Resources