Hello I'm Drawing a line in my Application . I'm using Caliburn.Micro MVVM Framework . In my DICOM image I'm able to draw a line using Pointer and Calculate distance . I use 3 events MouseDown,MouseMove and MouseUp. I left click to my Mouse and then I move if I release I able to Draw . My problem is when I move my mouse may be it sometimes change direction that time using Graphics.Drawline draw line but when I'm in the last point it should the Straight line . But as I move my Mouse it has the other point the line too that does not belong to this Line . Please see the what I did
It should be a starigh line as Sometimes My mouse move the color still at that point .There is a famous DICOM Viewer App Name Radiant Here you can see
Line is Straight.
Here is My code
<Image Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="4"
x:Name="DIIMGFINAL" cal:Message.Attach="[Event MouseDown] = [Action MDownCalCulateDistance($source, $eventArgs)];
[Event MouseMove] = [Action MMoveCalCulateDistance($source, $eventArgs)];
[Event MouseUp] = [Action MUpCalCulateDistance($source, $eventArgs)]">
</Image>
And Here is MY C# Code in ViewModel Class. This is MouseDown Event
public void MDownCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
{
if (!(sender is System.Windows.Controls.Image)) return;
_diIMGTemp = DIIMGFINAL;
if (_firstPoint.X == 0 && _firstPoint.Y == 0)
{
System.Windows.Point px1 = e.GetPosition((System.Windows.Controls.Image)sender);
_firstPoint = px1;
}
if (_secondPoint.X != 0 && _secondPoint.Y != 0)
{
System.Drawing.Bitmap drawbitmap = BitmapImage2Bitmap(DIIMGPrimary);
Graphics g;
using (g = Graphics.FromImage(drawbitmap))
{
g.DrawLine(Pens.Red, Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y), Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y));
g.Dispose();
}
Convert_BitMap_BitImage(drawbitmap);
DIIMGFINAL = DIIMGPrimary;
var geometry = new FrameGeometry(DicomDataSet);
var patientCoord1 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y)));
var patientCoord2 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y)));
double distanceInMM = patientCoord1.Distance(patientCoord2);
DisTanceInMM = distanceInMM;
//_firstPoint = new System.Windows.Point(0, 0);
//_secondPoint= new System.Windows.Point(0, 0);
// _isClicked = false;
}
}
This is MouseUp Event ..
public void MUpCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
{
_firstPoint = new System.Windows.Point(0, 0);
_secondPoint = new System.Windows.Point(0, 0);
}
And The last one is Mouse Move Event .
public void MMoveCalCulateDistance(object sender, System.Windows.Input.MouseEventArgs e)
{
if (!(sender is System.Windows.Controls.Image)) return;
System.Windows.Point px = e.GetPosition((System.Windows.Controls.Image)sender);
XCoordinate = px.X;
YCoordinate = px.Y;
// if (_isClicked == false) return;
// MousePoint
if ((_firstPoint.X == 0 && _firstPoint.Y == 0))
{
return;
}
else
{
System.Windows.Point px2 = e.GetPosition((System.Windows.Controls.Image)sender);
_secondPoint = px2;
System.Drawing.Bitmap drawbitmap = BitmapImage2Bitmap(DIIMGPrimary);
Graphics g;
// g.Clear();
using (g = Graphics.FromImage(drawbitmap))
{
g.DrawLine(Pens.Red, Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y), Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y));
}
Convert_BitMap_BitImage(drawbitmap);
DIIMGFINAL = DIIMGPrimary;
var geometry = new FrameGeometry(DicomDataSet);
var patientCoord1 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_firstPoint.X), Convert.ToInt32(_firstPoint.Y)));
var patientCoord2 = geometry.TransformImagePointToPatient(new Point2(Convert.ToInt32(_secondPoint.X), Convert.ToInt32(_secondPoint.Y)));
double distanceInMM = patientCoord1.Distance(patientCoord2);
DisTanceInMM = distanceInMM;
}
}
Please Help me Thanks in Advance.Sorry For lengthy question .
You should probably not draw directly on the image. This is quite inefficient, and you will also have problems like you have encountered. A better approach would be to create an overlay with lines and other graphics, See the question how to bind lines to a canvas on an example how to do this.
If you put your items control and your image in the same grid the items control should work like an overlay. i.e.
<Grid>
<Image>
<!--... -->
</Image>
<ItemsControl ItemsSource="{Binding Lines}">
<!--...-->
</ItemsControl>
</Grid>
You can use the same approach with an bitmap overlay, but that would be less efficient than letting wpf draw your primitives for you.
Related
So I want to make a funtunality like in Windows when you display a Picture that when you zoom in you can just move the Picture with the mouse. I already got the zoom part in my project:
<ScrollViewer Name="scroll" Margin="40"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Canvas
MouseWheel="Container_MouseWheel" x:Name="canvas">
<Viewbox>
<Image x:Name="img" Source="{Binding imageSource}" Grid.ColumnSpan="2" />
</Viewbox>
</Canvas>
</ScrollViewer>
and the Code in the MouseWheel Event:
var element = sender as UIElement;
var position = e.GetPosition(element);
var transform = element.RenderTransform as MatrixTransform;
var matrix = transform.Matrix;
var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor
matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
element.RenderTransform = new MatrixTransform(matrix);
but now Ive got the Problem that when I zoom I cant just click and hold the Image with the mouse and move to an another part of the picture, if you dont really know what I mean just open an Image on windows zoom in and then hold the mouse and move in the picture.
What I have tried was to add these 3 Events to my Canvas and this is the code behind for the 3 Events:
private Image draggedImage;
private Point mousePosition;
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var image = e.Source as Image;
if (image != null && canvas.CaptureMouse())
{
mousePosition = e.GetPosition(canvas);
draggedImage = image;
Panel.SetZIndex(draggedImage, 1); // in case of multiple images
}
}
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (draggedImage != null)
{
canvas.ReleaseMouseCapture();
Panel.SetZIndex(draggedImage, 0);
draggedImage = null;
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (draggedImage != null)
{
var position = e.GetPosition(canvas);
var offset = position - mousePosition;
mousePosition = position;
Canvas.SetLeft(draggedImage, Canvas.GetLeft(draggedImage) + offset.X);
Canvas.SetTop(draggedImage, Canvas.GetTop(draggedImage) + offset.Y);
}
}
but this didnt work saddly, does anyone has an Idea on how to make it work?
You should not mix layout (i.e. set Canvas.Left/Top) and render transformations. If you zoom by means of a RenderTransform, you should also pan by the same RenderTransform.
Here is a simple example where the MouseMove handler also manipulates the RenderTransform of the Image element.
<Canvas x:Name="canvas"
Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"
MouseWheel="CanvasMouseWheel">
<Image x:Name="image" Source=...>
<Image.RenderTransform>
<MatrixTransform/>
</Image.RenderTransform>
</Image>
</Canvas>
Note that mouse positions are determined differently for pan and zoom, in order to get an "unscaled" offset for panning, but an origin point relative to the Image for zooming.
private Point? mousePosition;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (canvas.CaptureMouse())
{
mousePosition = e.GetPosition(canvas); // position in Canvas
}
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
canvas.ReleaseMouseCapture();
mousePosition = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (mousePosition.HasValue)
{
var position = e.GetPosition(canvas); // position in Canvas
var translation = position - mousePosition.Value;
mousePosition = position;
var transform = (MatrixTransform)image.RenderTransform;
var matrix = transform.Matrix;
matrix.Translate(translation.X, translation.Y);
transform.Matrix = matrix;
}
}
private void CanvasMouseWheel(object sender, MouseWheelEventArgs e)
{
var position = e.GetPosition(image); // position in Image
var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1);
var transform = (MatrixTransform)image.RenderTransform;
var matrix = transform.Matrix;
matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
transform.Matrix = matrix;
}
As the title is already describing I am working on a custom standalone minimap application for a game. It should also have the possibility to place custom markers. This feature does not have to be interactive, it could also load fixed markers from the code or a file.
I am looking for some advice on the best approach, it does not have to be something real fancy. It is only for personal use. Only one thing is fixed: The worldmap is supplied as *.bmp.
I am also aiming for writing everything myself (so not using any Nugets) for the sake of learning.
Below you will find my current approach. This is the first version, so the code is far from being optimized...
MainWindow.xaml:
<ScrollViewer x:Name="MyScrollViewer" HorizontalScrollBarVisibility="Visible">
<Image x:Name="WorldMap" Source="..." Stretch="None"/>
</ScrollViewer>
<Rectangle Name="Player" RadiusX="3" RadiusY="3" Height="6" Width="6" Fill="White"/>
MainWindow.xaml.cs:
public MainWindow()
{
InitializeComponent();
Demo();
}
private async void Demo()
{
while (true)
{
var result = GameClient.GetPlayerPosition();
var hori = result[0] - MyScrollViewer.ActualWidth / 2;
var verti = result[1] - MyScrollViewer.ActualHeight / 2;
MyScrollViewer.ScrollToHorizontalOffset(hori);
MyScrollViewer.ScrollToVerticalOffset(verti);
await Task.Delay(100);
}
}
My first goal was to be able to track the clients position at all, which worked.
The map is moving accordingly as long as the player is not near the edges of the map.
If the player is near any edge, the app is not tracking the position correctly, since the ScrollViewer can not scroll below zero. But I am aware of this.
The next step would be to also move the Player-Rectangle I defined in the XAML, to be able to track its position near the edges. This is something I am currently not worried about.
So I basically have two questions:
Do you think the current approach is fine?
How could I realize custom markers / labels on the map?
Edit:
This is the final solution after Clemens suggested it in the comments:
XAML:
<Grid Background="Black">
<Canvas x:Name="MainCanvas">
<Image x:Name="WorldMapRot" Source="..." Stretch="None"/>
</Canvas>
</Grid>
Codebehind:
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
CaptureMouse();
start = e.GetPosition(this);
origin.X = MainCanvas.RenderTransform.Value.OffsetX;
origin.Y = MainCanvas.RenderTransform.Value.OffsetY;
isDragged = true;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
ReleaseMouseCapture();
isDragged = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (isDragged == false)
return;
base.OnMouseMove(e);
if (e.LeftButton == MouseButtonState.Pressed && IsMouseCaptured)
{
var pos = e.GetPosition(this);
var matrix = MainCanvas.RenderTransform.Value;
matrix.OffsetX = origin.X + (pos.X - start.X);
matrix.OffsetY = origin.Y + (pos.Y - start.Y);
MainCanvas.RenderTransform = new MatrixTransform(matrix);
}
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
base.OnMouseWheel(e);
Point p = e.MouseDevice.GetPosition(MainCanvas);
Matrix m = MainCanvas.RenderTransform.Value;
if (e.Delta > 0)
m.ScaleAtPrepend(1.1, 1.1, p.X, p.Y);
else
m.ScaleAtPrepend(1 / 1.1, 1 / 1.1, p.X, p.Y);
MainCanvas.RenderTransform = new MatrixTransform(m);
}
So basically i need to make an app that fits a painting in a frame on a wall that's square. I'm using aforge to detect the square and with it's corners i place and resize the image i want to the frame. This is done by pressing the third button which triggers imageAdapt() method. Unfortunately the image is not rescaled to the right size and placed wrongly. Here's my code:
namespace MyFirstJob
{
public sealed partial class MainPage : Page
{
public static int a = -1;
public static int b = -1;
FolderPicker folderPicker1 = new Windows.Storage.Pickers.FolderPicker();
FolderPicker folderPicker2 = new Windows.Storage.Pickers.FolderPicker();
StorageFolder folder1;
StorageFolder folder2;
System.Collections.Generic.IReadOnlyList<StorageFile> filesList1;
System.Collections.Generic.IReadOnlyList<StorageFile> filesList2;
public MainPage()
{
InitializeComponent();
folderPicker1.FileTypeFilter.Add(".png");
folderPicker2.FileTypeFilter.Add(".png");
}
private async void button1_Click(object sender, RoutedEventArgs e)
{
a++;
folder1 = await folderPicker1.PickSingleFolderAsync();
filesList1 = await folder1.GetFilesAsync();
var stream = await
filesList1[a].OpenAsync(Windows.Storage.FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
await bitmapImage.SetSourceAsync(stream);
image1.Source = bitmapImage;
}
private async void button2_Click(object sender, RoutedEventArgs e)
{
b++;
folder2 = await folderPicker2.PickSingleFolderAsync();
filesList2 = await folder2.GetFilesAsync();
var stream = await
filesList2[b].OpenAsync(Windows.Storage.FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
await bitmapImage.SetSourceAsync(stream);
image2.Source = bitmapImage;
}
private async void adaptImage()
{
var stream = await
filesList1[a].OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
WriteableBitmap writableBitmap = new
WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
writableBitmap.SetSource(stream);
BlobCounter blobCounter = new BlobCounter();
blobCounter.MinHeight = 100;
blobCounter.MinWidth = 100;
blobCounter.MaxHeight = 600;
blobCounter.MaxWidth = 600;
blobCounter.ProcessImage((Bitmap)writableBitmap);
Blob[] blobs = blobCounter.GetObjectsInformation();
SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
foreach (var blob in blobs)
{
List<IntPoint> edgePoints =
blobCounter.GetBlobsEdgePoints(blob);
List<IntPoint> cornerPoints;
if (shapeChecker.IsQuadrilateral(edgePoints, out cornerPoints))
{
if (shapeChecker.CheckPolygonSubType(cornerPoints) == PolygonSubType.Square)
{
double lenght = getLenght(cornerPoints[0].X,
cornerPoints[0].Y, cornerPoints[1].X, cornerPoints[1].Y);
image2.Height = lenght;
image2.Width = lenght;
image2.Margin = new Thickness(cornerPoints[0].X,
cornerPoints[0].Y, 0, 0);
}
}
}
}
private void button3_Click(object sender, RoutedEventArgs e)
{
adaptImage();
}
private double getLenght(int x1, int y1, int x2, int y2)
{
return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
}
}
When it starts: First button loads the background , second one the painting and then the last one makes it fit the painting
After loading the background everything is ok
Loading the painting (a random square)
The final image where the painting is not fit proprely in the square
Since you didn't upload the XAML code, I added the following XAML code for testing and it can work well on my side with your code snippet.
<Canvas>
<Image x:Name="image1" ></Image>
<Image x:Name="image2" ></Image>
<StackPanel Canvas.Top="20">
<Button x:Name="Button1" Click="button1_Click" Content="button1"></Button>
<Button x:Name="Button2" Click="button2_Click" Content="button2"></Button>
<Button x:Name="Button3" Click="button3_Click" Content="button3"></Button>
</StackPanel>
</Canvas>
Code behind are the same. I tested on build 15036. For aforge I'm using AForge Core 2.2.5.60302 and Imaging 2.2.5.60302.
But I can reproduce your issue with Grid panel as the parent container, and at the same time the cornerPoints of square doesn't begin from point 0,0. Inside a Grid panel, child elements are measured and arranged according to their row/column assignments.The image control may be positioned in the middle at default. But the cornerPoints of square is the coordinate relative to the top-left corner of background image, so it may be wrong to calculate the margin by cornerPoints. Canvas is suit for your scenarios. So please check if you are using a parent container for the Image controls that will arrange the image controls , for example, a StackPanel or a Grid. More details please reference Layout panels.
I have a canvas which has a zooming function. There are a lot of elements inside of it so, for selection I was going to use a selection box which I create dynamically when selection box is clicked. On clicking the button, I add the rectangle to the canvas and again, on clicking the button, I remove it.
I have the following xaml code:
<Viewbox x:Name="vbCanvas">
<Grid x:Name="theGrid"
MouseDown="Grid_MouseDown"
MouseUp="Grid_MouseUp"
MouseMove="Grid_MouseMove"
Background="Transparent">
<Canvas Name="canvasWaSNA" Margin="0,10,10,10" Height="720" Width="1280">
</Canvas>
</Grid>
</Viewbox>
mouse events of theGrid draws the rectangle on runtime on the canvas. The codes for those events are:
bool mouseDown = false;
Point mouseDownPos;
Point mouseUpPos;
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseDown = true;
mouseDownPos = e.GetPosition(theGrid);
theGrid.CaptureMouse();
// Initial placement of the drag selection box.
Canvas.SetLeft(sBox, mouseDownPos.X);
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Width = 0;
sBox.Height = 0;
// Make the drag selection box visible.
sBox.Visibility = Visibility.Visible;
}
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
// Release the mouse capture and stop tracking it.
mouseDown = false;
mouseUpPos = e.GetPosition(theGrid);
theGrid.ReleaseMouseCapture();
// Show the drag selection box.
sBox.Visibility = Visibility.Visible;
MessageBox.Show(mouseDownPos.ToString() + " " + mouseUpPos.ToString());
}
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
// When the mouse is held down, reposition the drag selection box.
Point mousePos = e.GetPosition(theGrid);
if (mouseDownPos.X < mousePos.X)
{
Canvas.SetLeft(sBox, mouseDownPos.X);
sBox.Width = mousePos.X - mouseDownPos.X;
}
else
{
Canvas.SetLeft(sBox, mousePos.X);
sBox.Width = mouseDownPos.X - mousePos.X;
}
if (mouseDownPos.Y < mousePos.Y)
{
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Height = mousePos.Y - mouseDownPos.Y;
}
else
{
Canvas.SetTop(sBox, mousePos.Y);
sBox.Height = mouseDownPos.Y - mousePos.Y;
}
}
}
To create a Rectangle at runtime, I have to click a button. The event of that button is as follows:
private void select_Click_1(object sender, RoutedEventArgs e)
{
if (!canvasWaSNA.Children.Contains(sBox))
{
sBox.Name = "selectionBox";
sBox.StrokeThickness = 1.5 / zoomfactor;
sBox.StrokeDashArray = new DoubleCollection { 1, 2 };
sBox.Visibility = System.Windows.Visibility.Collapsed;
sBox.Stroke = Brushes.Gray;
canvasWaSNA.Children.Add(sBox);
}
else
{
sBox.Visibility = System.Windows.Visibility.Collapsed;
canvasWaSNA.Children.Remove(sBox);
}
}
I am using the following code to zoom into the canvas:
double zoomfactor = 1.0;
void window_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point p = e.MouseDevice.GetPosition(canvasWaSNA); //gets the location of the canvas at which the mouse is pointed
Matrix m = canvasWaSNA.RenderTransform.Value;
if (e.Delta > 0)
{ //the amount of wheel of mouse changed. e.Delta holds int value.. +ve for uproll and -ve for downroll
m.ScaleAtPrepend(1.1, 1.1, p.X, p.Y);
zoomfactor *= 1.1;
}
else
{
m.ScaleAtPrepend(1 / 1.1, 1 / 1.1, p.X, p.Y);
zoomfactor /= 1.1;
}
canvasWaSNA.RenderTransform = new MatrixTransform(m);
}
When my canvas is on original size, The rectangle is drawn perfectly but as I zoom in or zoom out, rectangle is drawn abnormally. It starts to draw from other points. What might be the problem? Please help
Well, I wasnot supposed to capture the mouse position with respect to theGrid, as I had to create the rectangle with respect to canvas. So, I have to get the position as e.GetPosition(canvasWaSNA) and the intended result was shown. It captured the mouse position on the canvas. Now, the rectangle is drawn perfectly even when zoomed in or zoomed out.
Also, I improved the StrokeThickness of the rectangle drawn by referencing it with the zoomfactor of the canvas.
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{mouseDown = true;
mouseDownPos = e.GetPosition(canvasWaSNA);
theGrid.CaptureMouse();
sBox.StrokeThickness = 1.5 / zoomfactor;
// Initial placement of the drag selection box.
Canvas.SetLeft(sBox, mouseDownPos.X);
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Width = 0;
sBox.Height = 0;
// Make the drag selection box visible.
sBox.Visibility = Visibility.Visible;
}
I need to move an image over a canvas on tap and slide. How can I achieve this. I tried the following. The image is moving but not as the user moves it.
XAML
<Canvas Background="White">
<Image Name="img" Width="200" Height="200" Source="Assets/11.png" ManipulationMode="All" ManipulationStarted="img_ManipulationStarted" ManipulationDelta="img_ManipulationDelta"/>
</Canvas>
C#
private Point initialPt;
private void img_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
initialPt = e.Position;
}
private void img_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Point currentPt = e.Position;
double x = currentPt.X - initialPt.X;
double y = currentPt.Y - initialPt.Y;
if (x != 0 || y != 0)
{
TranslateTransform posTransform = new TranslateTransform();
posTransform.X = currentPt.X;
posTransform.Y = currentPt.Y;
img.RenderTransform = posTransform;
e.Complete();
}
}
Instead of using a TranslateTransform, you should directly set the absolute position in the canvas, so you have to bind the ManipulationDelta event to the Canvas, and detect if the point of impact is inside of the image.
<Canvas Background="White" ManipulationMode="All" ManipulationDelta="canvas_ManipulationDelta">
<Image Name="img" Width="200" Height="200" Source="Assets/11.png"/>
</Canvas>
Here is the new event handling function:
private void canvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if ((e.Position.X > Canvas.GetLeft(img) && e.Position.X < Canvas.GetLeft(img) + img.Width)
|| (e.Position.Y > Canvas.GetTop(img) && e.Position.Y < Canvas.GetTop(img) + img.Height)) {
{
Canvas.SetLeft(img, e.Position.X);
Canvas.SetTop(img, e.Position.Y);
}
}
Simple as pie. You can remove initialPt and img_ManipulationStarted.