I don't necessarily want to use the slider control but rather make the whole screen an interactive slider. For example, I'm practicing on a nightstand app and I'd like it so they can slide their finger down to lower the brightness or up to increase the brightness. I know this has been done in other apps but I'm not sure where to start. If someone could give me a starting point on what technique would work or any ideas in accomplishing this it would be great!
Thank you
You can use GestureListener from Silverlight Toolkit. Take a look at sample application provided with SL Toolkit. There is a sample page GestureSample.xaml. You will find there how to detect gestures.
One way could be to use Manipulation events. So, for example, you get the starting position in the ManipulationStarted event's ManipulationOrigin property . You can then get the final position in the ManipulationCompleted event's Manipulation property. Substract the two Y components and check if it's greater than or less than zero. If it's greater than zero, the user has moved downwards otherwise they've moved upwards.
private void LayoutRoot_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
startY = e.ManipulationOrigin.Y;
}
private void LayoutRoot_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
{
endY = e.ManipulationOrigin.Y;
if(endY - startY > 0)
MessageBox.Text("Down")
else
MessageBox.Text("Up");
//add check to see if it equals zero in which case the user didn't swipe
}
Alternatively, you could perform similar actions with the Silverlight Toolkit or the XNA Gestures. (They both differ slightly).
Related
I need help. I have a Picturebox and would now like to calculate given coordinates on the picture and then play them in the label. How can I do that best?
As seen in the picture.
If you then click on the image on it, then the data is entered in a list box.
Thank you for your help.
My Picture here: https://prnt.sc/puxyu6
In WPF this particular might for once be the hardest. WPF/UWP is designed for the MVVM, and I do not know anyone but beginners that programm outside of MVVM. And I can not think of way to do this with MVVM.
PictureBox is also the WinForms Element. The WPF equivalent is called Image.
Navigation aids like this are not a trivial thing. One reason there are so few of it. But it comes down to few step process:
Get the x and y pixel coordinates that was clicked, also in relation to that the overall display size of the Image. Usually the MouseClick Event would be the tool for that, but I can not find it. MouseDown or LeftMouseDown are the closest events.
If the entire image was shown with no zooming or cropping, it is now just simple math. If it was 20% of the X axis and 21% of the Y axis, it is pretty easy to figure out where 20% of X and 21 of Y is on the SourceImage.
If there was any zoom or crop, this has to be taken into account, otherwise it is 2.
Equate the Image Pixel position with the coordinates you know for it.
Part 1 would look like this and needs to be registered with the MouseDown or LeftMouseDown Event of the Image:
private void ContentControl_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Unpack the sender
Image source = (Image)Sender;
//Get the click point
Point clickPoint = e.GetPosition(source);
//There is more then 1 height Property in WPF.
//The Actuall one is what you are looking for
//Unfortunately you get doubles for this and int for the other. Consider general advise regarding double math
double ElementHeight = source.ActualHeight;
double ElementWidth = source.ActualWidth;
//Do what you need to find the relative position
//Part 2
}
Hopefully someone else can give you a better answer.
I'd like to make a slider control that when I press a key (lets say shift), its thumb (and its value) will drag slower than the mouse and so become more precise.
I'm still new to WPF and I don't really where to start.
Any hints?
EDIT---
Here is what I'm trying so far with horizontal slider :
Point pStart;
Point pCurrent;
private void CMiXSlider_DragDelta(object sender, DragDeltaEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftShift))
{
pCurrent = Mouse.GetPosition(CMiXSlider);
double center = Math.Abs(pCurrent.X - pStart.X);
Value = (1.0 / CMiXSlider.ActualWidth) * center;
}
}
private void CMiXSlider_DragStarted(object sender, DragStartedEventArgs e)
{
pStart = Mouse.GetPosition(CMiXSlider);
}
it behaves almost as expected but the thumb is always at the center position between 0 and pCurrent. Looks like pStart doesn't keep its value when DragDelta is triggered.
This is primarily a UX question, and only secondarily a WPF question. I cannot help you with WPF, but I can give you some input from a UX point of view.
Don't.
Just don't do this. It is a bad idea, for a number of reasons:
a) It is highly non-standard. No application that I ever heard of does something like that. Therefore, nobody will know that your slider behaves differently when some modifier key is pressed, and nobody will ever try to drag your slider with a modifier key down.
b) You cannot teach users to do it. Cluttering your user interface with additional text labels containing instructions on how to use it is clunky and abandoned as a practice decades ago.
c) Even if you do somehow manage to teach users to do it, the mental effort of learning some new way to use an existing and familiar control is not worth the added benefit of simply having better control over the precision of the slider.
d) This could either work by moving the slider by a fraction of the distance by which the pointer moves, or by slowing down the pointer.
moving the slider by a fraction of the distance by which the pointer moves would look ugly and clunky. It would work, but it would look broken.
slowing down the pointer is a tricky proposition, and it would only work with a mouse. What about a touch interface where the user uses their finger? You can't slow that down.
Solutions:
Implement movement by arrow keys. That's the standard way of allowing fine control over the value of a slider. When the slider has focus, then the arrow keys should change the value by one unit.
If the nature of your application is such that high precision is of great importance, then consider replacing the slider with a numeric control. Make it a spinner if need be. (A numeric control with an up and down button.) Or perhaps make it a numeric control with a drop-down slider, so the primary means of operation is numeric, and operation by slider is secondary and optional. (I have no idea how nor if you can do that with WPF.)
Sometimes this functionality is useful, for example a lighting/audio control or fine positioning of robotic arms. In these UX situations users will probably find out by RTFM.
I'm not in front of a PC, here is some simple psuedo code to illustrate how to do it with a Custom Slider Control that ignores every second value change when the shift key is down.
public class CustomSlider : Slider
{
private int precision = 2;
private int movement = 0;
protected override void OnValueChanged(double oldValue, double newValue)
{
bool keyShift = (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
if (keyShift && movement % precision == 0)
{
base.OnValueChanged(oldValue, newValue);
}
else if (!keyShift)
{
base.OnValueChanged(oldValue, newValue);
}
movement++;
if (movement == int.MaxValue) movement = 0;
}
}
You could apply this solution to Numeric Up/Down, Scroll Bars and various other controls.
In addition to the code above, for even more precise interaction you can detect for Ctrl key in the OnValueChanged event and increase precision, eg
precision = Keyboard.IsKeyDown(Key.Control) ? 3 : 2;
Part of my particular dilemma is that I would like to be able to get the initial position of a drag gesture. Depending on the initial position of that drag gesture, the application would either 1) pan the view or 2) display a menu, but not perform these gestures at the same time (which is where part of struggle lies).
For example, if the user initiated a drag from the very left side of their screen and dragged inwards, a menu would pop in instead of the view panning.
I would also like to be able to execute a double tap gesture without also activating a tap gesture, if that's at all possible. I've tried working with boolean flags - for example,
// ...
if (gesture.GestureType == GestureType.DoubleTap)
{
isDoubleTap == true;
}
// ...
public static Vector2 Tap
{
get
{
if (!isDoubleTap)
return gesture.Position;
// ...
But that doesn't work.
I've tried using TouchCollection - if anyone would like me to elaborate on my issues with that I can, but for now I'll say what I tried hasn't worked. It's entirely possible I may have just goofed as I am a novice when it comes to working with touch input.
I've been working on this for a few days and have done as much searching as I can, and nothing I've found has alleviated my issue - if I happened to have missed something, I apologize.
Thank you for your time!
Concerning start position of a drag:
There is a gesture for a drag ending, so if you receive a drag and its the first one since the last drag ended, thats the initial position.
Concerning tap/doubletap:
MonoGame works the same way as XNA as documented here:
The user tapped the screen twice in quick succession. This
always is preceded by a Tap gesture.
This sounds like a input-bindings design problem more than a technical question imo. Consider also what you can move to instead occur on press or release rather than only making use of gestures.
I am very very beginner of C# programming.
The previous program that I made can get touch input as a click event on the Surface Pro.
So, It cannot get multi-touch input.
How can I get the multi-touch inputs(positions on the screen) on the Windows Surface Pro when writing the application in c#?
I heard that I can use touch class, but I never know how to use it ....
I am struggling with this for 2 weeks, but could not make any progress.
Anyone who can explain how to use touch class specifically?
Or any other suggestions to get touch input values from the Surface pro touch panel?
Assuming you are programming WPF.
Register UIElement.TouchDown event, for example, in you MainWindow's constructor, add
this.TouchDown += MainWindow_TouchDown;
If multiple fingers are touching screen at the same time, the TouchDown event is fired for each finger.
You can get the position of the touch (relative to screen) from the TouchEventArgs which is passed as an argument to the event handler.
void MainWindow_TouchDown(object sender, TouchEventArgs e)
{
TouchPoint pointFromWindow = e.GetTouchPoint(this); //relative to Top-Left corner of Window
Point locationFromScreen = this.PointToScreen(new Point(pointFromWindow.Position.X, pointFromWindow.Position.Y)); //translate to coordinates relative to Top-Left corner of Screen
}
Note: .NET 4.0 is required, Windows 8 shipped with .NET 4.0 pre-installed. If you are running on Windows 7, you have to ensure it is installed.
I am trying to implement a custom control which consists of a grid with some canvas elements as children , When a swipe action is made on the grid , I am intended to preform some operation with the canvas elements .
I am unable to handle the swipe for the grid , i have posted the same in the
msdn - win8 Dev forum
I was in the same boat as you guys, since there was no samples out there on how this was done, but after perusing and scrutinizing the MSDN documentation on how a swipe gesture is implemented on a Windows 8 Store app using C#, this is what i came up with (and it works for my app which requires swiping up / down / left / right):
First of all, instead of the GestureRecognizer, the Manipulation events need to be used, so on the grid that you want to handle the swiping (lets' say you make it so that it takes the whole screen so it interprets the gestures) do the following:
I called my grid swipingSurface and i'm handling manipulation modes for both the Y-axis and X-axis:
swipingSurface.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
Then wire up the manipulation events that you want to be notified, in my case i just want to know then the manipulation started and when it ended:
swipingSurface.ManipulationStarted += OnManipulationStarted;
swipingSurface.ManipulationCompleted += OnManipulationCompleted;
Do whatever you want on your manipulation started, such as getting the initial point if you want. But the actual trick is on the ManipulationCompleted event, in which you need to get the Velocities resulting from your gesture, as follows:
public void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
var velocities = e.Velocities;
}
The ManipulationCompletedEventArgs Velocities property will bring back a struct of type ManipulationVelocities, which contains other properties inside:
-Angular: The rotational velocity in degrees per millisecond.
-Expansion: The expansion, or scaling, velocity in DIPs per millisecond.
-Linear: The straight line velocity in DIPs per millisecond.
I'm actually looking at the Linear velocity, which is a Point that contains X and Y values indicating the direction in which the gesture was performed; for example, if the swipe was upward, you will notice that the Y value is positive, and if its down the Y value is negative; the same goes for the X value, if the swipe is left, the X values are negative and if the swipe is right, the X values are positive, so you can play around with those values and check your swiping direction, final points, etc.
Hope this helps.
You could try setting ManipulationMode on your swipe-able control and handling the Manipulation~ events. Note that some controls might stop bubbling of UI events, so if you say put your control inside of a Button or a ScrollViewer - the events might not work.
You could check out SwipeHintThemeAnimation that uses GestureRecognizer to hook up to a Rectangle control or modify it to use your Grid control, see the documentation.