i found a link in msdn to draw a shape in .XAML file, but how to do the same with c#, drawing a shape with c# in wp7 in silverlight without use xna?
I think this http://www.windowsphonegeek.com/tips/drawing-in-wp7-1-getting-started-and-line-shape will help you to draw shapes using C#.
Your XAML:
<Canvas x:Name="ContentPanelCanvas" Grid.Row="1" Background="Transparent" Margin="12,0,12,0">
<Line X1="10" Y1="100" X2="150" Y2="100" Stroke="Green" StrokeThickness="5"/>
</Canvas>
C#:
Line line = new Line();
line.Stroke = new SolidColorBrush(Colors.Purple);
line.StrokeThickness = 15;
Point point1 = new Point();
point1.X = 10.0;
point1.Y = 100.0;
Point point2 = new Point();
point2.X = 150.0;
point2.Y = 100.0;
line.X1 = point1.X;
line.Y1 = point1.Y;
line.X2 = point2.X;
line.Y2 = point2.Y;
this.ContentPanelCanvas.Children.Add(line);
Related
I am attempting to draw a line from the center of an image on a canvas to the mouse's position when the scroll wheel is moved.
I have a function that looks like this:
// e is MouseWheelEventArgs
var position = e.GetPosition(canvas);
var x = Canvas.GetLeft(image) + image.ActualWidth / 2;
var y = Canvas.GetTop(image) + image.ActualHeight / 2;
Ellipse point = new Ellipse
{
Margin = new Thickness(x, y, 0, 0)
};
Line line = new Line
{
X1 = position.X,
Y1 = position.Y,
X2 = x,
Y2 = y
};
canvas.Children.Add(point);
canvas.Children.Add(line);
The point is drawn correctly at the pointer's location, and the line is drawn from the center of the image, but the point the line is drawn to is incorrect. Why is this?
Here is an image to show the location of the point and the line
I would suggest to implement this with Geometries.
With a XAML like this
<Canvas Background="Transparent" MouseWheel="Canvas_MouseWheel">
<Image x:Name="image" Canvas.Left="0" Canvas.Top="0" Source="..."/>
<Path x:Name="line" Stroke="Green" StrokeThickness="2"/>
<Path x:Name="point" Fill="Red"/>
</Canvas>
the event handler could look like this:
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
var position = e.GetPosition((Canvas)sender);
var center = new Point(
Canvas.GetLeft(image) + image.ActualWidth / 2,
Canvas.GetTop(image) + image.ActualHeight / 2);
line.Data = new LineGeometry(center, position);
point.Data = new EllipseGeometry(position, 3, 3);
}
Does anyone know of an easy way to animate a movement from an Image's current location to a new location (X,Y) using WPF animation with no XAML, 100% programmatically? And with no reference to "this" (with RegisterName etc).
I am trying to make an extension class for Image to do animation stuff on it. It is easy enough to change the width and height properties through animation, but after searching for location animation of an object it suddenly becomes more advanced.
As it is an extension class I will only have a reference to the actual Image object and the X and Y I want to move it to.
public static void MoveTo(this Image targetControl, double X, double Y, double Width, double Height){
//code here
...
}
Update:
Thanks. Almost working. It seems The GetTop and GetLeft returns 'NaN' not explicitly set. Found the workaround in this post: Canvas.GetTop() returning NaN
public static void MoveTo(this Image target, double newX, double newY) {
Vector offset = VisualTreeHelper.GetOffset(target);
var top = offset.Y;
var left = offset.X;
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
I had to swap two of the values (FROM) with 0. I assume that must be because in this context the upper left corner of the picture is the origin? But now it works.
Try this:
public static void MoveTo(this Image target, double newX, double newY)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.XProperty,anim1);
trans.BeginAnimation(TranslateTransform.YProperty,anim2);
}
Here it is... It changes the size and moves a MediaElement under the Canvas. Just input your parameters:
Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = mediaElement1.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = mediaElement1.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, mediaElement1.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, mediaElement1.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
<Viewbox Stretch="Uniform" StretchDirection="Both" SnapsToDevicePixels="True">
<Grid Width="640" Height="480" Name="MainLayout" SnapsToDevicePixels="True" Background="Black">
<Canvas Width="640" Height="480" Name="MainCanvas" SnapsToDevicePixels="True">
<MediaElement Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" LoadedBehavior="Manual" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" />
<Button Canvas.Left="294" Canvas.Top="196" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
</Canvas>
</Grid>
</Viewbox>
UPDATE:
Instead of MediaElement use this line:
<Rectangle Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" Fill="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}" />
And don't forget to put the C# code to:
private void button1_Click(object sender, RoutedEventArgs e) {}
You can use MediaElement as well but you have to define a VideoClip to see something ;)
Please find a solution that uses the Left and Top properties of Canvas for the extension method. See the following code:
public static void MoveTo(this Image target, Point newP)
{
Point oldP = new Point();
oldP.X = Canvas.GetLeft(target);
oldP.Y = Canvas.GetTop(target);
DoubleAnimation anim1 = new DoubleAnimation(oldP.X, newP.X, TimeSpan.FromSeconds(0.2));
DoubleAnimation anim2 = new DoubleAnimation(oldP.Y, newP.Y , TimeSpan.FromSeconds(0.2));
target.BeginAnimation(Canvas.LeftProperty , anim1);
target.BeginAnimation(Canvas.TopProperty, anim2);
}
This code is based on #DeanChalk's answer.
It moves an Image contained within a Canvas (RFID_Token) diagonally from the top-right to the bottom-left, positioned centrally over another Image within a Canvas (RFID_Reader).
<Canvas>
<Canvas x:Name="RFID_Reader_Canvas">
<Image x:Name="RFID_Reader" Source="RFID-Reader.png" Height="456" Width="682" Canvas.Left="37" Canvas.Top="524"/>
</Canvas>
<Canvas x:Name="RFID_Token_Canvas">
<Image x:Name="RFID_Token" Source="RFID-Token.png" Height="268" Width="343" Canvas.Left="874" Canvas.Top="70"/>
</Canvas>
</Canvas>
var StartX = Canvas.GetLeft(RFID_Token);
var StartY = Canvas.GetTop(RFID_Token);
var EndX = RFID_Reader.Width / 2 + Canvas.GetLeft(RFID_Reader) - StartX - (RFID_Token.Width / 2);
var EndY = RFID_Reader.Height / 2 + Canvas.GetTop(RFID_Reader) - StartY - (RFID_Token.Height / 2);
var AnimationX = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(1));
var AnimationY = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(1));
var Transform = new TranslateTransform();
RFID_Token_Canvas.RenderTransform = Transform;
Transform.BeginAnimation(TranslateTransform.XProperty, AnimationX);
Transform.BeginAnimation(TranslateTransform.YProperty, AnimationY);
I kept having NaN or 0 values for my nested elements, here's a modified version of Danny's answer :
public void MoveTo(Canvas canvas, FrameworkElement target, FrameworkElement destination)
{
Point oldPoint = target.TransformToAncestor(canvas).Transform(new Point(0, 0));
Point newPoint = destination.TransformToAncestor(canvas).Transform(new Point(0, 0));
var EndX = destination.Width / 2 + newPoint.X - oldPoint.X - (target.Width / 2);
var EndY = destination.Height / 2 + newPoint.Y - oldPoint.Y - (target.Height / 2);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(0.3));
DoubleAnimation anim2 = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(0.3));
trans.BeginAnimation(TranslateTransform.XProperty, anim1);
trans.BeginAnimation(TranslateTransform.YProperty, anim2);
}
I need help to bound the path or canvas in a boundary. What I want is, when I click the mouse-left-button, holding it and move for panning. It should not move when mouse pointer reach some boundary as BORDER. I'll add code here please help me out
XAML code:
<Border x:Name="OutMoastBorder" Height="820" Width="820" ClipToBounds="True" BorderThickness="2" BorderBrush="Black" Block.IsHyphenationEnabled="True">
<Border x:Name="clipBorder" Height="810" Width="810" BorderThickness="2" BorderBrush="Black" ClipToBounds="True">
<Canvas x:Name="CanvasPanel" Height="800" Width="800" Background="Beige">
</Canvas>
</Border>
</Border>
<Grid>
<Button Content="Original Size" Height="23" Name="btn_Original" Width="75" Click="btn_Original_Click" Margin="4,4,921,973" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="4,59,0,0" Name="txtNoOfZones" VerticalAlignment="Top" Width="120" MaxLength="2" PreviewTextInput="txtNoOfZones_PreviewTextInput" />
<Label Content="Enter a number below for No. of Zones" Height="28" HorizontalAlignment="Left" Margin="4,33,0,0" Name="label1" VerticalAlignment="Top" Width="220" FontFamily="Vijaya" FontSize="15" FontWeight="Bold" FontStyle="Normal" />
<Button Content="Zones" Height="23" HorizontalAlignment="Left" Margin="130,58,0,0" Name="btnNoOfZones" VerticalAlignment="Top" Width="41" Click="btnNoOfZones_Click" />
</Grid>
</Grid>
Code behind for zooming and panning:
void Zoom_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point p = e.MouseDevice.GetPosition(((Path)sender));
Matrix m = CanvasPanel.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);
CanvasPanel.RenderTransform = new MatrixTransform(m);
// CanvasPanel.RenderTransformOrigin = new Point(0.5, 0.5);
}
private Point origin;
private Point start;
void Pan_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (((Path)sender).IsMouseCaptured) return;
((Path)sender).CaptureMouse();
start = e.GetPosition(clipBorder);
origin.X = CanvasPanel.RenderTransform.Value.OffsetX;
origin.Y = CanvasPanel.RenderTransform.Value.OffsetY;
}
void Pan_MouseLeftBtnUp(object sender, MouseButtonEventArgs e)
{
((Path)sender).ReleaseMouseCapture();
}
void Pan_MouseMove(object sender, MouseEventArgs e)
{
if (!((Path)sender).IsMouseCaptured) return;
Point p = e.MouseDevice.GetPosition(clipBorder);
Matrix m = CanvasPanel.RenderTransform.Value;
m.OffsetX = origin.X + (p.X - start.X);
m.OffsetY = origin.Y + (p.Y - start.Y);
CanvasPanel.RenderTransform = new MatrixTransform(m);
}
private const int NoOfSectors = 180;
private const int NoOfZones = 5;
void OnLoaded(object sender, RoutedEventArgs args)
{
const double PIES = 2 * Math.PI / NoOfSectors;
Point center = new Point(CanvasPanel.ActualWidth / 2, CanvasPanel.ActualHeight / 2); // center (x,y) Co-ordinates to get center of canvas
double radius = 0.1 * Math.Min(CanvasPanel.ActualWidth, CanvasPanel.ActualHeight);
for (int s = 0; s <= NoOfSectors; s++)
{
for (int z = 1; z <= NoOfZones; z++)
{
Path path = new Path();
PathGeometry pathGeo = new PathGeometry();
PathFigure pathFig = new PathFigure();
double radians = 2 * Math.PI * s / NoOfSectors;
double outerRadius = radius * z;
double innerRadius = radius * ((z - 1));
Size outerArcSize = new Size(outerRadius, outerRadius);
Size innerArcSize = new Size(innerRadius, innerRadius);
Point p1_1st_LineSegment; //------------------------------> Points variable, to store each iterate point in these.
Point p2_1st_ArcSegment;
Point p3_2nd_LineSegment;
Point p4_2nd_ArcSegment;
p1_1st_LineSegment = new Point(center.X + innerRadius * Math.Cos(radians - PIES), center.Y - innerRadius * Math.Sin(radians - PIES)); // point for LINE from Center
p2_1st_ArcSegment = new Point(center.X + innerRadius * Math.Cos(radians), center.Y - innerRadius * Math.Sin(radians)); // point for ARC after the 1st LINE formation
p3_2nd_LineSegment = new Point(center.X + outerRadius * Math.Cos(radians), center.Y - outerRadius * Math.Sin(radians)); // Point for 2nd LINE after forming both LINE abd ARC
p4_2nd_ArcSegment = new Point(center.X + outerRadius * Math.Cos(radians - PIES), center.Y - outerRadius * Math.Sin(radians - PIES)); // Point for 2nd ARC which is Counter-CLockwise that closes a path
pathFig.StartPoint = center;
pathFig.Segments.Add(new LineSegment(p1_1st_LineSegment, true));
pathFig.Segments.Add(new ArcSegment(p2_1st_ArcSegment, innerArcSize, 1, false, SweepDirection.Clockwise, true));
pathFig.Segments.Add(new LineSegment(p3_2nd_LineSegment, true));
pathFig.Segments.Add(new ArcSegment(p4_2nd_ArcSegment, outerArcSize, 1, false, SweepDirection.Counterclockwise, true));
pathFig.IsClosed = false; //false because, path has to be close with ARC, not with LINE
pathFig.IsFilled = true;
pathGeo.Figures.Add(pathFig); // binding data to a Geometry
pathGeo.FillRule = FillRule.Nonzero;
path.Data = pathGeo; // binding whole geometry data to a path
path.Stroke = Brushes.Black;
path.Fill = Brushes.Silver;
path.StrokeThickness = 0.1;
// CanvasPanel.RenderTransformOrigin = new Point(0.5, 0.5); //--------------------> this makes "Canvas" to be Zoom from center
CanvasPanel.Children.Add(path); // binding to a CanvasPanel as a children
path.MouseLeftButtonDown += MouseLeftButtonClick; // calling Mouse-click-event
path.MouseWheel += Zoom_MouseWheel;
path.MouseLeftButtonDown += Pan_MouseLeftButtonDown;
path.MouseLeftButtonUp += Pan_MouseLeftBtnUp;
path.MouseMove += Pan_MouseMove;
}
}
Please help me out.
Regards,
Viswanath.
PLz replace the MouseMove event with this following code in code behind.
void Pan_MouseMove(object sender, MouseEventArgs e)
{
if (!((Path)sender).IsMouseCaptured) return;
Point p = e.MouseDevice.GetPosition(clipBorder);
if (p.X > 0 && p.Y > 0 && p.X < clipBorder.ActualWidth && p.Y < clipBorder.ActualHeight)
{
Matrix m = CanvasPanel.RenderTransform.Value;
m.OffsetX = origin.X + (p.X - start.X);
m.OffsetY = origin.Y + (p.Y - start.Y);
CanvasPanel.RenderTransform = new MatrixTransform(m);
}
}
I have tested, this will surely solve this.
regards,
Viswa
I've created a Windows Store Application in visual studio 2013, and I really don't know how to rotate a button on PointerEntered in c#. Using hover, I just want to rotate it to 360 angle. I would appreciate it if somebody will help me.
Here is an example from MSDN:
The XAML:
<Canvas Height="200" Width="200">
<!-- Rotates the Polyline 45 degrees about the point (0,0). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50">
<Polyline.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45" />
</Polyline.RenderTransform>
</Polyline>
</Canvas>
The c# Code:
(Use this as and where required...)
// Create a Polyline.
Polyline polyline1 = new Polyline();
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(0, 50));
polyline1.Points.Add(new Point(25, 75));
polyline1.Points.Add(new Point(50, 50));
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(25, 0));
polyline1.Stroke = Brushes.Blue;
polyline1.StrokeThickness = 10;
// Create a RotateTransform to rotate
// the Polyline 45 degrees about its
// top-left corner.
RotateTransform rotateTransform1 =
new RotateTransform(45);
polyline1.RenderTransform = rotateTransform1;
// Create a Canvas to contain the Polyline.
Canvas canvas1 = new Canvas();
canvas1.Width = 200;
canvas1.Height = 200;
Canvas.SetLeft(polyline1, 75);
Canvas.SetTop(polyline1, 50);
canvas1.Children.Add(polyline1);
Im trying to rotate a <Image> of an arrow (placed in the middle of a 40x40 image). By what I remember from graphics class i need to first translate the image back to its center, rotate and then translate back:
TranslateTransform tTrans = new TranslateTransform();
tTrans.X -= 20;
tTrans.X -= 20;
RotateTransform rTrans = new RotateTransform();
rTrans.Angle = 60;
TranslateTransform t2Trans = new TranslateTransform();
tTrans.X += 20;
tTrans.X += 20;
imgWind.RenderTransform = ?;
Anyone got a good idea on how i can apply the transformations?
You can simply use
imgWind.RenderTransform = new RotateTransform(){ CenterX = 0.5, CenterY = 0.5, Angle = 45 };
Or in XAML:
<UIElement RenderTransformOrigin="0.5,0.5">
<UIElement.RenderTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" />
</UIElement.RenderTransform>
</UIElement>
By setting the CenterX and CenterY you don't have to translate before and after. In WPF (or silverlight for that matter) the transforms will take care of that themselfs.