Zedgraph: How can I cancel a Zoom from ZoomEvent? - c#

I want to allow the user to be able to click and drag on the graph to select the points in that area.
I thought a good way to do this would be to use ZoomEvent, because the newState parameter gives the area of the zoom, and I can simply select the points in that area. Is there a way I can access the values in newState and then cancel the zoom? Can I force it to go back to oldState?
private void trendGraphControl_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
{
if (newState.Type == ZoomState.StateType.Zoom) {
selectPointsInArea(newState);
// How can I disable this zoom??
}
}

Actually, the zoom area info that I needed in newState was private. The solution was to save the previous zoom values on mouse down, and then check the new zoom values in the zoom event, before resetting them to the previous values.
double last_x_max, last_x_min, last_y_max, last_y_min;
private bool trendGraphControl_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e)
{
// Save the zoom values
last_x_max = sender.GraphPane.XAxis.Scale.Max;
last_x_min = sender.GraphPane.XAxis.Scale.Min;
last_y_max = sender.GraphPane.YAxis.Scale.Max;
last_y_min = sender.GraphPane.YAxis.Scale.Min;
return false;
}
private void trendGraphControl_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
{
if (newState.Type == ZoomState.StateType.Zoom) {
double new_x_max = sender.GraphPane.XAxis.Scale.Max;
double new_x_min = sender.GraphPane.XAxis.Scale.Min;
double new_y_max = sender.GraphPane.YAxis.Scale.Max;
double new_y_min = sender.GraphPane.YAxis.Scale.Min;
selectPointsInArea(new_x_max, new_x_min, new_y_max, new_y_min);
sender.GraphPane.XAxis.Scale.Max = last_x_max;
sender.GraphPane.XAxis.Scale.Min = last_x_min;
sender.GraphPane.YAxis.Scale.Max = last_y_max;
sender.GraphPane.YAxis.Scale.Min = last_y_min;
}
}
Thanks for Ramankingdom's comment for sending me in the right direction.

Related

Click and hold on textblock while dragging mouse to make value bigger/smaller

I want the same thing as in this Question:
Click and hold on button while dragging mouse to make value bigger/smaller
The only answer there was the Slider but that was not what the Question asker meant. And nor what i meant.
I know something like this is possible in iOs, but i want to use it in a windows app, but i cant seem to figure out how to do it.
I tried doing it with pointerpressed, pointerrelease and pointermoved. And it worked in a way but i stops working when you get out of the range from the textblock so it does only work when you drag on the textblock itself, and i want to do it so that you can drag over the whole screen if necessary.
this is what i have so far:
private void TextBlock_PointerPressed(object sender, PointerRoutedEventArgs e)
{
ystart = e.GetCurrentPoint(this).Position.Y;
clicked = true;
}
private void TextBlock_PointerReleased(object sender, PointerRoutedEventArgs e)
{
clicked = false;
}
private void TextBlock_PointerMoved(object sender, PointerRoutedEventArgs e)
{
if(clicked == true)
{
yend = e.GetCurrentPoint(this).Position.Y;
double difference;
int textgetal = Convert.ToInt32(Block.Text);
difference = ystart - yend;
textgetal = textgetal + (Convert.ToInt32(difference) / 10);
Block.Text = Convert.ToString(textgetal);
}
}
and like i said this works, but only inside the range of the textblock and not the whole screen like i want it.

C# WPF Capture Keyboard and Mouse

So I have a WPF Window that captures mouse events on an image. I am doing this by the following code:
<Image Name="imgPrimaryImage" Width="512" Height="512" RenderOptions.BitmapScalingMode="NearestNeighbor" Margin="5"
Source="{Binding Path=ImageMgr.ImageSource}"
MouseLeftButtonDown="OnMouseLeftButtonDown"
MouseMove="OnMouseMove"
MouseLeftButtonUp="OnMouseLeftButtonUp"/>
Application Functionality: While the user moves the mouse left and right it changes the size of the image so long as they have the left mouse button pressed.
Question: Is is possible to also capture keyboard events while capturing the mouse move event.
End Result: I want to be able to change the mouse speed based on CTRL and SHIFT pressed. I have the code I need to change the mouse speed, I am just wondering how I can get it so that if the user is holding CTRL while they left click and drag on the image it changes the speed.
If anyone has any insight on this (i.e. articles, literature, or advice) that would be excellent. Thank you and if there is any additional information needed please let me know.
To sum up comments if you want to check state of keyboard keys you can use Keyboard class which provides IsKeyDown method
var isShift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
var isCtrl = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
var isAlt = Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt);
or use its Modifiers property
var isShift = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
var isCtrl = Keyboard.Modifiers.HasFlag(ModifierKeys.Control);
var isAlt = Keyboard.Modifiers.HasFlag(ModifierKeys.Alt);
Set boolean flags based on what keys are pressed in the key pressed event.
In the OnMouseMove record the mouse position if null. Otherwise calculate the distance traveled, and amplify it or dampen it based on the speed up or slow down flags you've set already.
To dampen or amplify, once you have the X and Y change from the last point, multiply by 2, or divide by 2... (you can choose your own numbers), now add the new YX change to the current mouse XY coordinates and set the mouse position.
Here is what the MouseMove would look like, and some of the private variables needed. In my Example you have to have Forms included as a reference. I did not include Forms in my Include statements, because it mucks up IntelliSense in WPF applications. You will still need to maintain those _speedUp and _slowDown variables with your KeyDown events
private bool entering = true;
private Point _previousPoint;
private bool _speedUp;
private bool _slowDown;
private double _speedMod = 2;
private double _slowMod = .5;
private void OnMouseMove(object sender, MouseEventArgs e)
{
Point curr = new Point(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y);
if (entering)
{
_previousPoint = curr;
entering = false;
}
if (_previousPoint == curr)
return; // The mouse hasn't really moved
Vector delta = curr - _previousPoint;
if (_slowDown && !_speedUp)
delta *= _slowMod;
else if (_speedUp && !_slowDown)
delta *= _speedMod;
else
{
_previousPoint = curr;
return; //no modifiers... lets not do anything
}
Point newPoint = _previousPoint + delta;
_previousPoint = newPoint;
//Set the point
System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)newPoint.X, (int)newPoint.Y);
}
EDIT: I put the key down events in my window definition, and it works just fine. Although as pointed out in the comments of this thread, using Keyboard.IsKeyDown is much simpler. I also edited the code above to not cause weird jumping issues
private void Window_KeyDown(object sender, KeyEventArgs e)
{
_slowDown = true;
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
_slowDown = true;
else if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
_speedUp = true;
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
_slowDown = false;
else if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
_speedUp = false;
}
private void Window_MouseLeave(object sender, MouseEventArgs e)
{
entering = true;
}

WPF Fast Click Events become a Drag-Event

I have the problem, that fast clicks become a drag-event.
I use the preventMouseButtonDown event to get the start position:
private void previewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_pointStartDrag = e.GetPosition(null);
}
The previewMouseMove-event delivers the actual position. I compare the two points to trigger my drag-event.
Vector d = _pointStartDrag - e.GetPosition(null);
if( |d.x| > minDx || |d.y| > minDy)
//here is my drag-event
Whatever minDx/y is set, it is reached by fast clicking two different poinst on my gui.
I don't know what went wrong. Any ideas?
I just answered this problem a day or two ago, but I can't find the question now, so I'll just do it again. You can use the SystemParameters.MinimumHorizontalDragDistance and SystemParameters.MinimumVerticalDragDistance properties for this purpose:
private bool IsConfirmedDrag(Point point)
{
bool horizontalMovement = Math.Abs(point.X - dragStartPosition.X) >
SystemParameters.MinimumHorizontalDragDistance;
bool verticalMovement = Math.Abs(point.Y - dragStartPosition.Y) >
SystemParameters.MinimumVerticalDragDistance;
return (horizontalMovement | verticalMovement);
}
It is used like this:
private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown && IsConfirmedDrag(e.GetPosition(sender as ListBox)))
{
isMouseDown = false;
...
// Start Drag operation
}
}

gmap c# point lat long to screen position/location

I'm working with GMap in c#. When I click on the map I whant to get the location on the screen from where I'm clicking.
I have a map controller that is called myMap. When I click on the map an event is triggered called myMap_Click(object sender, MouseEventArgs e). If I place an object, in my case a custom form, on the location e.X, e.Y it wont be placed where I click on the screen.
My goal is to desplay a form where I click on the map. I dont care if it follows coordinate if I pan the map or zoom. For now I just want a custom form on the position I click.
How can I get the screen location when I click on the map contoll?
Regards!
It's actually pretty simple!
private void myMap_Click(object sender, MouseEventArgs e)
{
using (Form customForm = new Form())
{
customForm.StartPosition = FormStartPosition.Manual;
customForm.DesktopLocation = MainMap.PointToScreen(e.Location);
customForm.ShowDialog();
}
}
Obviously replace "Form customForm" parts with your equivalents.
Well you can use this also
gMapControl1.MouseClick += new MouseEventHandler(map_mouseCLick);
private void map_mouseCLick(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
var point = gMapControl1.FromLocalToLatLng(e.X, e.Y);
double lat = point.Lat;
double lon = point.Lng;
//this the the values of latitude in double when you click
double newPointLat = lat;
//this the the values of longitude in double when you click
double newPointLong = lon;
}
}

Capture mouse movement event only when Left Click is pressed

I need to update a control only whenever the mouse moves over it with the left mouse button pressed. I would normally simply check for the e.Button property, but it is unavailable in the MouseEnter event.
void MyControl_MouseEnter(object sender, EventArgs e)
{
// MouseEventArgs needed to check this
// if (e.Button == MouseButtons.Left)
// {
// update MyControl
// }
}
How would you accomplish this?
Use the static Control.MouseButtons property. For example:
private void panel1_MouseEnter(object sender, EventArgs e) {
if (Control.MouseButtons == MouseButtons.Left) {
// etc...
}
}
This is very difficult to get going, whatever the user clicks on to get the mouse button pressed is going to capture the mouse, preventing the control's MouseEnter event from firing. It is also UI that's completely undiscoverable to the user. Do consider a better mouse trap.
Here's one (crude) way to do it. It will change the form's title text to whatever mouse button was pressed as you dragged your mouse on to button1. You can reference Control.MouseButtons to see which button is in a pressed state. Here's some more info on MSDN.
public partial class Form1 : Form
{
MouseButtons _buttons;
public Form1()
{
InitializeComponent();
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (_buttons != System.Windows.Forms.MouseButtons.None)
{
this.Text = _buttons.ToString();
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
_buttons = Control.MouseButtons;
}
}
I found the answer in another question here on SO:
How can I detect a held down mouse button over a PictureBox?
You will need to use a message filter. Implement the PreFilterMessage of the IMessageFilter interface, and assign an instance using Application.AddMessageFilter.
You will have to interpret windows messages yourself... that is not kind of difficult, but it will require some work.
The implementation may look like this:
if (m.Msg == 0x200)
{
int x, y;
x = m.LParam.ToInt32() & 0xFFFF;
y = m.LParam.ToInt32() >> 16;
if ((m.WParam.ToInt32() & 2) != 0)
{
// here, the left mouse button is pressed, and you can use the coords
// and see if the mouse is over the control you want.
}
}
I just implemented something like this today, tested only in Chrome but works rather nicely. Basic concept is that you capture mousemove only between mousedown and mouseup, as follows:
var image = document.getElementById('my_image');
image.addEventListener('mousedown', function(e) {
e.currentTarget.addEventListener('mousemove', doMyStuff);
});
image.addEventListener('mouseup', function(e) {
e.currentTarget.removeEventListener('mousemove', doMyStuff);
});
function doMyStuff(e) {
// do what you want, the mouse is moving while the user is holding the button down
}
Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles
Button1.MouseDown
If Control.MouseButtons = MouseButtons.Left Then
Label1.Text = "Left"
ElseIf Control.MouseButtons = MouseButtons.Right Then
Label1.Text = "Right"
ElseIf Control.MouseButtons = MouseButtons.Middle Then
Label1.Text = "Middle"
Else
Label1.Text = "lelse"
End If
End Sub

Categories