Moove / Slide Several UIelement on the screen - c#

With my actual code i can make one object moove
private void OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
e.Handled = true;
}
private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
e.Handled = true;
ballTranslate.X += e.DeltaManipulation.Translation.X;
ballTranslate.Y += e.DeltaManipulation.Translation.Y;
savx = ballTranslate.X;
savy = ballTranslate.Y;
}
private void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
e.Handled = true;
}
and my xaml :
<Image x:Name="ball"
Source="/bal.png"
ManipulationStarted="OnManipulationStarted"
ManipulationCompleted="OnManipulationCompleted"
ManipulationDelta="OnManipulationDelta" Canvas.Left="212" Canvas.Top="282">
<Image.RenderTransform>
<TranslateTransform x:Name="ballTranslate"/>
</Image.RenderTransform>
</Image>
when I add an other Image(ball) and I try to moove one; the other one moove too.
And I'd like to add several balls with something like a button. (cause the goal of my game is to place object on the screen.
My question is how can I add an other ball with the same comportement ?
More XAML with an other image (but i'd like to not pass through XAML to add an image cause i dunno how many images i need;
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="0,0,0,0">
<Canvas x:Name="CanMap" Margin="10,0,-10,0">
<Image Grid.RowSpan="2" Source="/textg.png" Stretch="Fill" Height="480" Width="752" Canvas.Left="-24" RenderTransformOrigin="0.499,0.512" CacheMode="BitmapCache" />
<!-- <Image Name="image1" Stretch="Fill" Source="/bal.png" MouseMove="MouseMoving" Grid.ColumnSpan="4" Canvas.Left="337" Canvas.Top="239"/>-->
<Image x:Name="ball"
Source="/bal.png"
ManipulationStarted="OnManipulationStarted"
ManipulationCompleted="OnManipulationCompleted"
ManipulationDelta="OnManipulationDelta" Canvas.Left="447" Canvas.Top="323">
<Image.RenderTransform>
<TranslateTransform x:Name="ballTranslate"/>
</Image.RenderTransform>
</Image>
<Image x:Name="ball2"
Source="/bal.png"
ManipulationStarted="OnManipulationStarted"
ManipulationCompleted="OnManipulationCompleted"
ManipulationDelta="OnManipulationDelta" Canvas.Left="120" Canvas.Top="310">
<Image.RenderTransform>
<TranslateTransform x:Name="ballTranslate2"/>
</Image.RenderTransform>
</Image>
</Canvas>
</Grid>
add image: (I can't use bitmap )
void AddImage(string src)
{
Image image = new Image();
Uri uri = new Uri(src, UriKind.Relative);
ImageSource img = new System.Windows.Media.Imaging.BitmapImage(uri);
image.SetValue(Image.SourceProperty, img);
RenderTransform = new TranslateTransform();
image.ManipulationDelta += OnManipulationDelta;
// Add additional handlers here..
CanMap.Children.Add(image);
}
-->
private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
e.Handled = true;
var transform = (sender as UIElement).RenderTransform as TranslateTransform;
transform.X += e.DeltaManipulation.Translation.X;
transform.Y += e.DeltaManipulation.Translation.Y;
savex = transform.X;
savey = transform.Y;
}

Updated answer:
void AddImage(string src)
{
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(src, UriKind.RelativeOrAbsolute);
bitmap.EndInit();
var img = new Image()
{
Source = bitmap,
RenderTransform = new TranslateTransform()
}
img.ManipulationDelta += OnManipulationDelta;
// Add additional handlers here..
CanMap.Children.Add(img);
}
void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var transform = (sender as UIElement).RenderTransform as TranslateTransform;
transform.X += e.DeltaManipulation.Translation.X;
transform.Y += e.DeltaManipulation.Translation.Y;
}

Related

WPF how to move a slider thumb slower when shift key is pressed

I have a slider which I want the thumb moves to exact position when click on anywhere on the slider track and moves slower when I press Shift key and drag the thumb. I know how to detect when the shift key is pressed but I don't know how to slow down the thumb. Any help would be appreciated!
Here is the xaml code:
<Grid>
<Slider x:Name="m_Slider" IsMoveToPointEnabled="True" Orientation="Vertical"
Height="200" Width="30" Minimum="0" Maximum="20" HorizontalAlignment="Center"
Thumb.DragStarted="Slider_ShiftDrag"/>
</Grid>
and here is the code-behind:
void Slider_ShiftDrag(object sender, DragStartedEventArgs e)
{
if (e != null && (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
{
//What should I do here?
}
}
I've written a fake slider to achieve your goal. I don't use the native Thumb because the native one captures the mouse and always follow the mouse. So I write a Rectangle instead of Thumb to do the dragging.
This is the XAML:
<Grid Width="400" Height="32">
<Rectangle x:Name="Tracker" Height="2" Fill="Gray" />
<Rectangle x:Name="Thumb" Width="8" Height="32" Margin="-4 -16" Fill="DarkGray" HorizontalAlignment="Left" VerticalAlignment="Center"
MouseDown="Thumb_MouseDown" MouseMove="Thumb_MouseMove" MouseUp="Thumb_MouseUp" LostMouseCapture="Thumb_LostMouseCapture">
<UIElement.RenderTransform>
<TranslateTransform x:Name="ThumbTranslation" />
</UIElement.RenderTransform>
</Rectangle>
</Grid>
And this is the code-behind:
private Point? _lastPoint;
private void Thumb_MouseDown(object sender, MouseButtonEventArgs e)
{
_lastPoint = e.GetPosition(Tracker);
Thumb.CaptureMouse();
}
private void Thumb_MouseMove(object sender, MouseEventArgs e)
{
if (_lastPoint != null)
{
var currentPoint = e.GetPosition(Tracker);
var offset = currentPoint - _lastPoint.Value;
_lastPoint = currentPoint;
if (Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
{
offset *= 0.2;
}
SetThumbTranslation(offset.X);
}
}
private void Thumb_MouseUp(object sender, MouseButtonEventArgs e)
{
_lastPoint = null;
Thumb.ReleaseMouseCapture();
}
private void Thumb_LostMouseCapture(object sender, MouseEventArgs e)
{
_lastPoint = null;
}
private void SetThumbTranslation(double offsetX)
{
var x = ThumbTranslation.X + offsetX;
x = Math.Max(x, 0);
x = Math.Min(x, Tracker.ActualWidth);
ThumbTranslation.X = x;
}

How can I make a Rectangle on a canvas which is draggable?

I have these three functions to trigger the events. I already have a static version of my needs, but I need a dynamically version of it.
bool captured = false;
double x_shape, x_canvas, y_shape, y_canvas;
UIElement source = null;
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
source = (UIElement)sender;
Mouse.Capture(source);
captured = true;
x_shape = Canvas.GetLeft(source);
x_canvas = e.GetPosition(canvasPreview).X;
y_shape = Canvas.GetTop(source);
y_canvas = e.GetPosition(canvasPreview).Y;
}
private void MouseMove(object sender, MouseEventArgs e)
{
//MessageBox.Show("test");
if (captured)
{
double x = e.GetPosition(canvasPreview).X;
double y = e.GetPosition(canvasPreview).Y;
x_shape += x - x_canvas;
Canvas.SetLeft(source, x_shape);
x_canvas = x;
y_shape += y - y_canvas;
Canvas.SetTop(source, y_shape);
y_canvas = y;
}
}
private void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
captured = false;
}
I have made a canvas in WPF called 'canvasPreview', I want to add the rectangle (currently in the static version I am using an ellipse) to the canvas, it must be draggable with above functions. It is already working, but it have to be dynamically.
I hope you can help me, thank you in advance!
I'm sure this sample code will help you.
XAML:
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button x:Name="addRectangleButton" Content="Add Rectngle" Click="addRectangleButton_Click"/>
</StackPanel>
<Canvas Grid.Row="1" x:Name="canvas" Margin="0,12,0,0">
<Rectangle x:Name="rectangle" Width="100" Height="50" Fill="RoyalBlue" MouseDown="rectangle_MouseDown" MouseMove="rectangle_MouseMove" MouseUp="rectangle_MouseUp" Canvas.Left="0" Canvas.Top="0"/>
</Canvas>
</Grid>
C#:
bool drag = false;
Point startPoint;
public MainWindow()
{
InitializeComponent();
}
// this creates and adds rectangles dynamically
private void addRectangleButton_Click(object sender, RoutedEventArgs e)
{
// create new Rectangle
Rectangle rectangle = new Rectangle();
// assign properties
rectangle.Width = 100;
rectangle.Height = 50;
rectangle.Fill = new SolidColorBrush(Colors.RoyalBlue);
// assign handlers
rectangle.MouseDown += rectangle_MouseDown;
rectangle.MouseMove += rectangle_MouseMove;
rectangle.MouseUp += rectangle_MouseUp;
// set default position
Canvas.SetLeft(rectangle, 0);
Canvas.SetTop(rectangle, 0);
// add it to canvas
canvas.Children.Add(rectangle);
}
private void rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
// start dragging
drag = true;
// save start point of dragging
startPoint = Mouse.GetPosition(canvas);
}
private void rectangle_MouseMove(object sender, MouseEventArgs e)
{
// if dragging, then adjust rectangle position based on mouse movement
if (drag)
{
Rectangle draggedRectangle = sender as Rectangle;
Point newPoint = Mouse.GetPosition(canvas);
double left = Canvas.GetLeft(draggedRectangle);
double top = Canvas.GetTop(draggedRectangle);
Canvas.SetLeft(draggedRectangle, left + (newPoint.X - startPoint.X));
Canvas.SetTop(draggedRectangle, top + (newPoint.Y - startPoint.Y));
startPoint = newPoint;
}
}
private void rectangle_MouseUp(object sender, MouseButtonEventArgs e)
{
// stop dragging
drag = false;
}

WPF DragDrop.GiveFeedback not firing continously

I'm trying to create a popup that follows the mouse pointer while dragging a draggable item.
The following snipping opens the popup at the mouse pointer but I rely on the GiveFeedback delegate to allow me to update the popup location (that is, if the pointer moved)
private void Members_DragOver(object sender, DragEventArgs e)
{
dragPopup.DataContext = DraggedItem;
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
dragPopup.IsOpen = true;
}
private void Members_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (dragPopup.IsOpen)
{
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
dragPopup.IsOpen = true;
}
}
And the popup itself which resided in the main grid of my window.
NOTE
I've tried handling the position during the MouseMove or PreviewMouseMove, but these events are ignored completely during a drag-and-drop procedure.
<Popup x:Name="dragPopup" Placement="MousePoint">
<Border BorderThickness="2" Background="White" DataContext="{Binding}">
<StackPanel Orientation="Horizontal" Margin="4,3,8,3">
<TextBlock Text="{Binding FullName}" FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
</Border>
</Popup>
The GiveFeedback delegate fires only once (setting a breakpoint with a hitcounter of 5 confirms this). Even though this MSDN article says:
This event is raised continuously during the drag-and-drop operation. Therefore, you should avoid resource-intensive tasks in the event handler. For example, use a cached cursor instead of creating a new cursor each time the GiveFeedback event is raised.
Why is the delegate fired only once?
You are right, GiveFeedBack is the way to do it.I did manage to get the GiveFeedBack to be called during drag. Apparently the mouse position in GiveFeedBack is handled different than in the mouse move. I manage to fix this by using the WinForms mouse position. Add reference System.Windows.Forms and System.Drawing for the following code:
Xaml:
<Grid GiveFeedback="Members_GiveFeedback">
<Popup x:Name="dragPopup" Placement="MousePoint">
<Border BorderThickness="2" Background="White" DataContext="{Binding}">
<StackPanel Orientation="Horizontal" Margin="4,3,8,3">
<TextBlock Text="Test" FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
</Border>
</Popup>
<StackPanel Orientation="Horizontal">
<ListBox x:Name="sourcList" Height="50"
PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown"
PreviewMouseMove="sourcList_PreviewMouseMove"
AllowDrop="True" >
<ListBoxItem > source Item #1</ListBoxItem>
</ListBox>
<ListBox x:Name="droplist" Height="50" AllowDrop="True" Drop="droplist_Drop" >
<ListBoxItem >dest Item #2</ListBoxItem>
</ListBox>
</StackPanel>
</Grid>
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var mousePoint = Mouse.GetPosition(this);
startPoint=mousePoint;
var point = GetMousePositionWindowsForms();
var formsmousePoint = new Point(point.X, point.Y);
var pointfromscreen = dragPopup.PointFromScreen(formsmousePoint);
dragPopup.HorizontalOffset = pointfromscreen.X - 100;
dragPopup.VerticalOffset = pointfromscreen.Y - 100;
dragPopup.IsOpen = true;
}
private void sourcList_PreviewMouseMove(object sender, MouseEventArgs e)
{
...
}
private void droplist_Drop(object sender, DragEventArgs e)
{
...
}
private void Members_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (dragPopup.IsOpen)
{
var point=GetMousePositionWindowsForms();
var mousePoint = new Point(point.X, point.Y);
var pointfromscreen=dragPopup.PointFromScreen(mousePoint);
dragPopup.HorizontalOffset = pointfromscreen.X-100;
dragPopup.VerticalOffset = pointfromscreen.Y-100;
}
}
public static Point GetMousePositionWindowsForms()
{
System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
return new Point(point.X, point.Y);
}
I just got your popup following my mouse by doing the following:
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
dragPopup.IsOpen = true;
}
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
}
Then on the xaml side
<Grid MouseMove="Grid_MouseMove">
...
<ListBox Height="50" PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown" AllowDrop="True">
<ListBoxItem> ListBox Item #1</ListBoxItem>
</ListBox>
The position is a little off though.
private void UIElement_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
StartMousePosition = new System.Windows.Point(GetMousePositionWindowsForms().X, GetMousePositionWindowsForms().Y);
MoveDragInformationPopup();
DragInstrong textformationPopup.IsOpen = true;
}
private void UIElement_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (DragInformationPopup.IsOpen)
{
MoveDragInformationPopup();
}
}
private void MoveDragInformationPopup()
{
var point = GetMousePositionWindowsForms();
DragInformationPopup.HorizontalOffset = (point.X - StartMousePosition.X) + 5;
DragInformationPopup.VerticalOffset = (point.Y - StartMousePosition.Y) + 5;
}
private System.Drawing.Point GetMousePositionWindowsForms()
{
return System.Windows.Forms.Control.MousePosition;
}

How to put bookmark onto slider while timeline marking in c#/xaml metro app

I have checked this sample. It shows me TimeLineMarker API. Now when I press button "Add Marker" at that time markers are added and text block shows the markers, on which time it was added. Now I want to display those markers onto Slider control in the form of any sign like any shape or whatever, so when I want to go directly onto the marker I can go directly clicking on slider. How can I do this ?
Finally got answer from MSDN, thanks Matt
XAML
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Center">
<Grid>
<Canvas x:Name="MyCanvas" Width="{Binding ElementName=MySlider, Path=ActualWidth}" Height="{Binding ElementName=MySlider, Path=ActualHeight}" Background="BlueViolet"/>
<Slider x:Name="MySlider" Orientation="Horizontal" Width="750" Height="50" Loaded="MySlider_Loaded_1"/>
</Grid>
<Button Content="Set marker" Click="Button_Click_1"/>
</StackPanel>
</Grid>
C#
int UniqueId = 0;
List<CustomTick> MyCustomTicks = new List<CustomTick>();
Thumb MySliderThumb;
Point ThumbCurrentPoint;
private void MySlider_Loaded_1(object sender, RoutedEventArgs e)
{
FrameworkElement templateRoot = VisualTreeHelper.GetChild((Slider)sender, 0) as FrameworkElement;
MySliderThumb = templateRoot.FindName("HorizontalThumb") as Thumb;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MySliderThumb.TransformToVisual(MyCanvas).TryTransform(new Point(0, 0), out ThumbCurrentPoint);
CustomTick MyCustomTick = new CustomTick();
MyCustomTick.X = ThumbCurrentPoint.X;
MyCustomTick.Y = ThumbCurrentPoint.Y;
MyCustomTick.Value = MySlider.Value;
MyCustomTick.ID = UniqueId++;
MyCustomTicks.Add(MyCustomTick);
Windows.UI.Xaml.Shapes.Rectangle MyRectangle = new Windows.UI.Xaml.Shapes.Rectangle();
MyRectangle.Name = MyCustomTick.ID.ToString();
MyRectangle.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
MyRectangle.Width = MySliderThumb.ActualWidth;
MyRectangle.Height = MySliderThumb.ActualHeight;
MyRectangle.PointerPressed += MyRectangle_PointerPressed;
MyCanvas.Children.Add(MyRectangle);
Canvas.SetTop(MyRectangle, MyCustomTick.Y - MyRectangle.Height );
Canvas.SetLeft(MyRectangle, MyCustomTick.X);
}
void MyRectangle_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Shapes.Rectangle MyRectangle = sender as Windows.UI.Xaml.Shapes.Rectangle;
CustomTick MyCustomTick = new CustomTick();
foreach (CustomTick CT in MyCustomTicks)
{
if (CT.ID.ToString() == MyRectangle.Name)
{
MyCustomTick = CT;
break;
}
}
MySlider.Value = MyCustomTick.Value;
}
List<CustomTick> MyTicks = new System.Collections.Generic.List<CustomTick>();
private class CustomTick
{
public double X;
public double Y;
public double Value;
public int ID;
}

Combining RotateTransform and TranslateTransform

I am using the Thumb class to let the user drag and drop an image across a canvas. When the right button gets pressed, i want the user to be able to rotate the image. The rotation is based around the center of the image. I have the following XAML Code
<Grid>
<Canvas Background="Red" Grid.RowSpan="2" x:Name="canvas"
PreviewMouseRightButtonUp="Canvas_MouseUp"
PreviewMouseMove="Canvas_MouseMove">
<UserControl MouseRightButtonDown="Canvas_MouseDown" RenderTransformOrigin="0.5,0.5">
<Thumb Name="myRoot" DragDelta="myRoot_DragDelta">
<Thumb.Template>
<ControlTemplate>
<Grid>
<Image Source="/WpfApplication1;component/someImage.png" />
<Rectangle Stroke="#FF0061CE" StrokeThickness="1" Width="230" Height="250" />
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
<UserControl.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rotateTransform" />
<TranslateTransform x:Name="translateTransform" />
</TransformGroup>
</UserControl.RenderTransform>
</UserControl>
</Canvas>
</Grid>
And this code behind
bool isMouseDown = false;
Point pos;
double lastAngle = 0;
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
isMouseDown = true;
lastAngle = rotateTransform.Angle;
pos = Mouse.GetPosition(canvas);
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
isMouseDown = false;
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (!isMouseDown) return;
var curPos = Mouse.GetPosition(canvas);
rotateTransform.Angle = lastAngle + (pos.Y - curPos.Y);
}
private void myRoot_DragDelta(object sender, DragDeltaEventArgs e)
{
translateTransform.X += e.HorizontalChange;
translateTransform.Y += e.VerticalChange;
}
It works if i only drag and drop the image around the screen and rotate the image a small amount (50 degrees in any direction seems ok). However manipulating it more than that and the image starts move around the screen unpredictibly.
I have tried moving the transformations to different controls, so to not to mix them up but have not received an acceptable result.
How can i get my code to behave like i want?
UPDATE: This is driving my crazy. I have changed the code and XAML to use a MatrixTransformation instead
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (!isMouseDown) return;
var curPos = Mouse.GetPosition(canvas);
angle = (lastAngle + (pos.Y - curPos.Y)) % 360;
UpdateMatrixTransform();
}
private void myRoot_DragDelta(object sender, DragDeltaEventArgs e)
{
posX += e.HorizontalChange;
posY += e.VerticalChange;
UpdateMatrixTransform();
}
void UpdateMatrixTransform()
{
Matrix m = new Matrix();
m.Rotate(angle);
m.OffsetX = posX;
m.OffsetY = posY;
matrixT.Matrix = m;
}
In my mind, this should work: First, rotate the graphic than move it to the offset. It does not work like i expect it to. It rotates the image, but than moves it strangely in spiral fashion outwards if i keep moving the mouse. No matter what i do, and in what order i execute my transformations, it wont work.
I'm not sure why you're using a UserControl to wrap the Thumb since it should be able to act as the root element here. Here is a solution that involes scrapping the use of TranslateTransform and instead using Canvas.Left and Canvas.Top properties:
EDIT: Updated Answer
Here's the XAML:
<Canvas x:Name="canvas">
<Thumb Name="myRoot"
Canvas.Left="0" Canvas.Top="0"
DragDelta="myRoot_DragDelta"
MouseMove="myRoot_MouseMove"
MouseDown="myRoot_MouseDown"
MouseUp="myRoot_MouseUp">
<Thumb.Template>
<ControlTemplate>
<Grid RenderTransformOrigin="0.5, 0.5">
<Rectangle Fill="AliceBlue"
Stroke="#FF0061CE"
StrokeThickness="1"
Width="100" Height="100"/>
<Grid.RenderTransform>
<RotateTransform x:Name="rotateTransform" />
</Grid.RenderTransform>
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
And here's the code behind:
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
}
Point? lastPosition = null;
RotateTransform rotateTransform;
private void myRoot_MouseDown(object sender, MouseButtonEventArgs e)
{
lastPosition = null;
if (e.ChangedButton == MouseButton.Right)
myRoot.CaptureMouse();
}
private void myRoot_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Right)
myRoot.ReleaseMouseCapture();
}
private void myRoot_MouseMove(object sender, MouseEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
Point curPosition = Mouse.GetPosition(myRoot);
if (lastPosition != null)
{
Point centerPoint = new Point(myRoot.ActualWidth / 2, myRoot.ActualWidth / 2);
if (rotateTransform == null)
rotateTransform = (RotateTransform)myRoot.Template.FindName("rotateTransform", myRoot);
rotateTransform.Angle = Math.Atan2(curPosition.Y - centerPoint.Y, curPosition.X - centerPoint.X) * 100;
}
lastPosition = curPosition;
e.Handled = true;
}
}
private void myRoot_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
Canvas.SetLeft(myRoot, Canvas.GetLeft(myRoot) + e.HorizontalChange);
Canvas.SetTop(myRoot, Canvas.GetTop(myRoot) + e.VerticalChange);
}
}
You have to tell the RotateTransform that you want to rotate around the center of the object rather than the center of the coordinate system, which is the default. To do that, set the CenterX and CenterY properties of the RotateTransform to the center of the object.

Categories

Resources