I need to get the [X,Y] positions of a slider.
I already tried the function "PointFromScreen" but I didn't get any result.
Anyone?
Thanks
private void SliderPosition(object sender)
{
Slider slider = (Slider)sender;
int x = (int)slider.Value;
Point x1 = Point.Parse(x);
Point slider_point = slider.PointFromScreen(x1);
}
UPDATE and more clear doubt:
I have a video going through, and a slide that is dependent of the number of frames.
Video format is 640x480, slider is defined in terms of frames!
I need to know, when the right button is pushed in the video image, the position[X,Y] of the slider so that I can draw a line in a Canvas that is beneath the video.
I think it's clear now. Going through the library, the only parameter I can find is the slider.value but that doesn't make my case.
Source code of my try:
private void Slider_position(object sender, System.Windows.Controls.Slider e, System.Windows.Input.MouseEventArgs e1)
{
if (e1.RightButton == MouseButtonState.Pressed)
{
Line line = new Line();
line.X1 = e. //something, i would get here the coordinates X,Y of slider here
// calculation from slider position to canvas position
// draw a line of the height of the canvas here after
}
}
Try using MouseClick() as this will give you the mouse positions, from the The AutoIt Window Info.
Related
I am making an application in which I load a bunch of 256x256px chunks of a map and stitch them together with magick.net to then display them in a picture box. I added a feature for slewing the image (and loading new picture chunks as I do) using mouse events on the picture box control like so:
// Set true when mouse should slew the picture in the picture box
private bool isSlewing = false;
// last position of the mouse in map space when slewing
private float lastX = 0;
private float lastY = 0;
private void Pb_MouseMove(object sender, MouseEventArgs e)
{
// slew while mouse is down.
if (isSlewing)
{
Tuple<float, float> mouseMapCoordinates = MouseToMap(e.X, e.Y);
Slew(mouseMapCoordinates.Item1 - lastX, mouseMapCoordinates.Item2 - lastY);
lastX = mouseMapCoordinates.Item1;
lastY = mouseMapCoordinates.Item2;
}
}
private void Pb_MouseDown(object sender, MouseEventArgs e)
{
isSlewing = true;
Tuple<float, float> mouseMapCoordinates = MouseToMap(e.X, e.Y);
lastX = mouseMapCoordinates.Item1;
lastY = mouseMapCoordinates.Item2;
}
private void Pb_MouseUp(object sender, MouseEventArgs e)
{
isSlewing = false;
}
// Slews map image by dx and dY
public void Slew(float dX, float dY)
{
X -= dX;
Y -= dY;
}
// Converts mouse coordinates into map coordinates
private Tuple<float,float> MouseToMap(int mouseX, int mouseY)
{
// works
}
X and Y are properties that invalidate the picture box by setting a boolean needsUpdate to true. A timer is run and every 200ms it calls the update function which builds the picture based on X and Y . There also is a zoom but that's unimportant for now and works fine.
The issue is that when I click and drag the map it works in principle but every so often the map "jumps" back to a previous mouse position.
I just don't know how to go about trying to find out what's causing it or how to fix it.
I would like the whole program to be a bit more responsive to begin with, it feels sluggish, which is why I introduced the timer to begin with, so it doesn't draw updates on every little change dozens of times per second as I move the mouse a tiny amount.
I think it has to do with some kind of race condition that sets lastX and lastY between one slew and the next with the update drawing things in between. The update function takes a few milliseconds to complete, as it loads the images from disk and composites them and finally draws them back to the picture box.
The whole code is available at github. Map data is not included, but can be downloaded with the script in Assets. For testing I recommend deleting all but one map from the json file there. All map data in total is about 3GB.
I tried putting lock() around the block inside the if statement in Pb_MouseMove, but that didn't help anything.
The issue was with converting the mouse coordinates into map space outside of slew because the map space moves with the viewport. To fix the issue you save the raw mouse position in lastX and lastY, put the raw delta for the mouse coordinate into the slew function and then multiply by a scaling factor. The scaling factor is how many map coordinate units are used per pixel.
I am writing an Android (Xamarin) application which is able to zoom and pan an image. A user can also click on a position on the image. I need those coordinates on the image for later use.
The following code is zooming and panning the image:
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
_maxX = canvas.Width;
_maxY = canvas.Height;
canvas.Translate(_posX, _posY);
if (_scaleDetector.IsInProgress)
canvas.Scale(_scaleFactor, _scaleFactor, _scaleDetector.FocusX, _scaleDetector.FocusY);
else
canvas.Scale(_scaleFactor, _scaleFactor, _lastGestureX, _lastGestureY);
}
So far so good, now I have some MotionEvent in use, which is a LongPressListener. I wrote the following code to translate the coordinates from the MotionEvent to the coordinates on the image:
var actualX = e.GetX() - (_parent._posX / _parent._scaleFactor);
var actualY = e.GetY() - (_parent._posY / _parent._scaleFactor);
e in this case is the frame of the image. The frame holds an image (which is _parent), the user can drag the image. _parent._posX/Y are changed when that happens. The user can also zoom the image, that's the _scaleFactor.
So, when a user taps anywhere in e, I need to translate those coordinates to the image coordinates.
Those two lines of code works, but when the user zooms in, the coordinates are off as you can see in the attached image:
The red dots represent the calculated positions. As you can see, if a user zooms in the coordinates gets more off. What's wrong in this calculation?
Try to do this :-
var actualX = (e.GetX() - _parent._posX) / _parent._scaleFactor;
var actualY = (e.GetY() - _parent._posY) / _parent._scaleFactor;
I think your problem is because the Canvas is not getting updated, try using Canvas.UpdateLayout after zooming.
I managed to fix it using a Matrix:
private float[] TranslateCoordinates(float[] coordinates)
{
var matrix = new Matrix(Matrix);
matrix.PreScale(_scaleFactor, _scaleFactor);
matrix.PreTranslate(_posX, _posY);
matrix.Invert(matrix);
matrix.MapPoints(coordinates);
return coordinates;
}
The float[] contains the values of MotionEvent's GetX() and GetY().
I am working in my own editor for making WPF forms. My issue is that I am having the worst time selecting multiple controls (buttons, labels, etc) and dragging them smoothly across the main window. My application chokes when I try to drag, oh say, 20 selected buttons at the same time.
I found that the culprit is the fact that I am drawing multiple rectangles for each object as they are being dragged and this function is being called in the MouseMove event.
void ControlObjectControl_MouseMove(object sender, MouseEventArgs e)
{
if (newPosition != oldPosition)
{
DragSelection(newPosition);
}
}
private void DragSelection(Point newPosition)
{
foreach (FrameworkElement item in designer.SelectionService.CurrentSelection)
{
if (item is ObjectControl)
(item as ObjectControl).m_ParentControlObject.Position = new System.Drawing.Rectangle() { X = X, Y = Y, Width = (int)item.Width, Height = (int)item.Height };
//..There's code that calculates the item's position and dimensions
}
}
How do I make it to where it only draws the rectangle once and I am still able to see my selected object(s) move smoothly when I drag them?
I did something similar in my application except I used a TranslateTransform to move my elements. Each "frame" (every mouse move) that I was dragging, I got the position of the mouse and compared that to the previous position of the mouse. I would then set a new TranslateTransform X/Y values equal to the X/Y mouse position change and then would give that to the RenderTransform of each object I wanted to move. Something like:
void ControlObjectControl_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
// Get the change in Location
mouseLocation = Mouse.GetPosition();
Point deltaLocation = mouseLocation - previousLocation;
// Make a new transform
TranslateTransform transform = new TranslateTransform();
transform.X = deltaLocation.X;
transform.Y = deltaLocation.Y;
// Apply the transform
// foreach thing
thing.RenderTransform = transform;
// set previous location
previousLocation = mouseLocation;
}
}
Now your objects only get drawn once and only their positions get changed. Hope this helps
I'm trying to make a little graphics program that has a circle of diameter 100 on the screen and from the center of it, a line is coming out of it that is always attached to the mouse pointer until such time that the user does a click, and then the line is permanently drawn. It's exactly like MSPaint's line, except that starting point is always the center of the circle.
I tried a few things that DON'T work.
I can get the line to appear only after a mouse-click. That's not what I want. I want the line to always be present and pivoting from the circle-center until the mouse is clicked and then it's then permanently on the screen.
I can get a smeary thing where the line is always being drawn. It makes a sort of star shape, but that's not what I want either.
Basically, I want the same functionality that you have in MSPaint when you draw a line. What am I supposed to do? Draw the line and then erase it a second later, and then draw it again when the mouse is in a new position? I tried something like that, but it does a thing where it erases the background a little bit, and then the line is only drawn when the mouse is in motion, but not when the mouse is stationary.
If anyone can provide a code snippet, that'd be great. Or just some pseudo-code.
Is this the right pseudo code?
Start:
Left click and a line appears from center of circle to mouse tip
Line stays there until a new mouse coordinate is made (how do I keep track)?
Line from center of circle to original location gets erased
New line is made to new location of mouse coordinates.
I think this something of a state-machine to use what I learned in digital class. How are states implemented in C#?
Any help would be appreciated, and thanks to everyone that can understand my question even though I'm probably not using the proper terminology.
So short answer is you will need some custom painting. The longer answer involves custom drawing, and event handling.
The other piece of code you need is a list of some sort to hold all of the lines. The code below creates a user control and does the custom painting without relying on a state machine. To test it, create a new project add a user control called UserControl1, and add it to a form. Make sure you tie into the listed events.
I tried to comment the relevant sections and this shows a quick and dirty way to do what you appear to be trying to do.
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace CustomDrawingAndEvents
{
public partial class UserControl1 : UserControl
{
private struct MyLine
{
public Point mStart;
public Point mEnd;
public MyLine(Point xStart, Point xEnd)
{
mStart = xStart;
mEnd = xEnd;
}
}
private List<MyLine> mLines;
private Point mCircleCenter;
private Point mMousePosition;
public UserControl1()
{
InitializeComponent();
mLines = new List<MyLine>();
//Double Buffer to prevent flicker
DoubleBuffered = true;
//Create the center for our circle. For this just put it in the center of
//the control.
mCircleCenter = new Point(this.Width / 2, this.Height / 2);
}
private void UserControl1_MouseClick(object sender, MouseEventArgs e)
{
//User clicked create a new line to add to the list.
mLines.Add(new MyLine(mCircleCenter, e.Location));
}
private void UserControl1_MouseMove(object sender, MouseEventArgs e)
{
//Update mouse position
mMousePosition = e.Location;
//Make the control redraw itself
Invalidate();
}
private void UserControl1_Paint(object sender, PaintEventArgs e)
{
//Create the rect with 100 width/height (subtract half the diameter to center the rect over the circle)
Rectangle lCenterRect = new Rectangle(mCircleCenter.X - 50, mCircleCenter.Y - 50, 100, 100);
//Draw our circle in the center of the control with a diameter of 100
e.Graphics.DrawEllipse(new Pen(Brushes.Black), lCenterRect);
//Draw all of our saved lines
foreach (MyLine lLine in mLines)
e.Graphics.DrawLine(new Pen(Brushes.Red), lLine.mStart, lLine.mEnd);
//Draw our active line from the center of the circle to
//our mouse location
e.Graphics.DrawLine(new Pen(Brushes.Blue), mCircleCenter, mMousePosition);
}
}
}
I have a draggable element in a StackPanel in a Windows 8 store app. My goal is simple: drag the item somewhere on the screen and immediately after the user stops dragging it the element should return to its original starting position.
I have the following code which is meant to accomplish this task:
private void grdCover_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
Grid coverControl = sender as Grid;
double xOffset = -e.Cumulative.Translation.X;
double yOffset = -e.Cumulative.Translation.Y;
if (coverControl.RenderTransform is TranslateTransform)
{
TranslateTransform existingTransform = coverControl.RenderTransform as TranslateTransform;
existingTransform.X += xOffset;
existingTransform.Y += yOffset;
}
else
{
TranslateTransform transform = new TranslateTransform();
transform.X = xOffset;
transform.Y = yOffset;
coverControl.RenderTransform = transform;
}
}
The code sort of works. The screen looks like this upon application start:
The top element, which looks like a H is well aligned with the bottom element which looks like a U. When I first drag the H element it jumps back to its well aligned position, or at least any misalignment is so little that it's hardly perceivable to the naked eye. As I keep dragging and releasing the H element it gets more and more misaligned like this:
After 15-20 dragging moves the H element gets completely misplaced:
The problem might be due to some rounding error of the double values in the Point objects when they are translated into pixels, but that's only a wild guess. Also, on a high resolution device, such as my PC it takes more moves for the misalignment to become visible than on a lower resolution one, such as the Windows Simulator in Visual Studio.
Some other code that may be related to this issue:
I perform the dragging operation with the following code:
private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
TranslateTransform translateTransform = (sender as Grid).RenderTransform as TranslateTransform;
translateTransform.X += e.Delta.Translation.X;
translateTransform.Y += e.Delta.Translation.Y;
}
I also have the following event handler in place to stop the element from moving too much on the screen after the user is done dragging the element:
private void grdCover_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingRoutedEventArgs e)
{
e.TranslationBehavior.DesiredDeceleration = 10000000000000000;
e.Handled = true;
}
In case you're wondering I wanted to set the desired deceleration to Double.Max to block any further "sliding" movement on the screen but I got an exception saying it was out of bounds. So instead I chose this arbitrary large value.
I have no extra margins or padding on the layout root or the element to be moved or its container.
Any ideas are welcome.
Thanks, Andras
OK, I got it to work. The problem was that there was a slight mismatch between the Point coordinates in the following code bits:
TranslateTransform translateTransform = (sender as Grid).RenderTransform as TranslateTransform;
translateTransform.X += e.Delta.Translation.X;
translateTransform.Y += e.Delta.Translation.Y;
and
double xOffset = -e.Cumulative.Translation.X;
double yOffset = -e.Cumulative.Translation.Y;
The solution was to retrieve the value of
e.Delta.Translation.X
and
e.Delta.Translation.Y
and assign their values to the variables xOffset and yOffset. Retrieving the values of
e.Cumulative.Translation.X
and
e.Cumulative.Translation.Y
gave slightly different coordinates so the element kept jumping back to the wrong location.