Is it possible to change caret width for TextBox in silverlight when overwrite mode? - silverlight

I have the TextBox in silverlight 4 in 2 modes: insert and overwrite.
Can anyone help me? If I press the overwrite mode, I want to make the caret blinking size bigger.
I have used to CaretBrush, but it can change the color of caret only.
Many thanks if you have suggestion or the sample code.

At the time looking someone can help, I tried this solution for myself, It's abit complex, but I hope someone can use my code and customize yourself. Someone can get this code for trying if you have this case
The MainPage.xaml code:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.micros`enter code here`oft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid Name="LayoutRoot">
<Canvas x:Name="canvasDataView" VerticalAlignment="Top" Background="White" HorizontalAlignment="Left">
<TextBox HorizontalAlignment="Left" Canvas.Left="50" VerticalAlignment="Top" x:Name="positionTextBox" Canvas.ZIndex="2" Text="position" Canvas.Top="25" Visibility="Collapsed" Width="100" Height="25"></TextBox>
<TextBox x:Name="textBox1" Text="asdfasdfasd asda asdf as adfasdfads adf asdf adfasdf" SelectionForeground="AliceBlue" KeyDown="textBox1_KeyDown" KeyUp="textBox1_KeyUp" TextWrapping="NoWrap" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" Height="25" Width="500" />
<TextBox x:Name="shadowTextBox" Canvas.ZIndex="-1" Canvas.Left="350" Height="20" Width="20" HorizontalScrollBarVisibility="Visible" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Visibility="Visible" TextWrapping="NoWrap"/>
</Canvas>
</Grid>
</UserControl>
The code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Expression.Interactivity;
using System.Windows.Controls.Primitives;
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
Duration duration = new Duration(TimeSpan.FromSeconds(0.5));
Storyboard storybroad = new Storyboard();
Rectangle myRectangle = null;
ScrollViewer sv;
public MainPage()
{
InitializeComponent();
textBox1.KeyUp += new KeyEventHandler(textBox1_KeyUp);
textBox1.TextChanged += new TextChangedEventHandler(textBox1_TextChanged);
textBox1.CaretBrush = new SolidColorBrush(Colors.Transparent);
}
void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
shadowTextBox.Text = textBox1.Text;
shadowTextBox.SelectionStart = textBox1.SelectionStart;
Point p = getCaretPosition(textBox1, shadowTextBox);
MoveCaret(p);
}
void textBox1_KeyDown(object sender, KeyEventArgs e)
{
shadowTextBox.Text = textBox1.Text;
shadowTextBox.SelectionStart = textBox1.SelectionStart;
}
void textBox1_KeyUp(object sender, KeyEventArgs e)
{
shadowTextBox.Text = textBox1.Text;
shadowTextBox.SelectionStart = textBox1.SelectionStart;
// get caret position
Point p = getCaretPosition(textBox1,shadowTextBox);
MoveCaret(p);
}
private Point getCaretPosition(TextBox textBox, TextBox shadowTextBox)
{
Point _point = new Point();
// get main textbox's scroll offset, if any
getScrollBar(textBox);
double initVerticalOffset = sv.VerticalOffset;
double initHorizontalOffset = sv.HorizontalOffset;
// get shadow box scroll offset
getScrollBar(shadowTextBox);
double vOffset = sv.VerticalOffset;
double hOffset = sv.HorizontalOffset;
// caret position is scroll offset of shadaw minus scroll offset of main (if any)
_point.Y = vOffset - initVerticalOffset;
_point.X = hOffset - initHorizontalOffset;
return _point;
}
private void getScrollBar(UIElement src)
{
// walk visual tree for this object until we get the scrollviewer
if (src.GetType().ToString() == "System.Windows.Controls.ScrollViewer")
sv = src as ScrollViewer;
else
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(src); i++)
{
UIElement elem = (UIElement)VisualTreeHelper.GetChild(src, i);
getScrollBar(elem);
}
}
}
void MoveCaret(Point point)
{
if (storybroad == null)
storybroad = new Storyboard();
storybroad.Stop();
if (point != new Point(0, 0))
{
if (myRectangle != null && canvasDataView.Children.Contains(myRectangle))
{
canvasDataView.Children.Remove(myRectangle);
}
myRectangle = new Rectangle();
myRectangle.SetValue(Canvas.TopProperty, point.Y);
myRectangle.SetValue(Canvas.LeftProperty, point.X);
myRectangle.Width = 5;
myRectangle.Height = 16;
myRectangle.Fill = new SolidColorBrush();
storybroad.BeginTime = new TimeSpan(0, 0, 0, 0, 0);
storybroad.RepeatBehavior = RepeatBehavior.Forever;
ColorAnimation color = new ColorAnimation();
canvasDataView.Children.Add(myRectangle);
color.From = Colors.Transparent;
color.To = Colors.Green;
color.Duration = duration;
storybroad.Children.Add(color);
Storyboard.SetTarget(color, myRectangle);
Storyboard.SetTargetProperty(color, new PropertyPath("(Fill).(SolidColorBrush.Color)"));
storybroad.Begin();
}
}
}
}

Related

WPF Drawing MultiLine Text on a canvas using the maximum font

I have several blocks of text that I need to add to a canvas for printing. They will all have a set width and height. They are all multiline and I would like the font to scale as large as possible. I have tried several things with a viewbox, however I can't seem to get the multiline and font scaling to work in unison.
<Viewbox Width="200" Height="200" Stretch="Uniform" >
<TextBox Text="Test test test test test test Test test test test test test "
TextWrapping="Wrap" AcceptsReturn="True" BorderThickness="0"></TextBox>
</Viewbox>
If I have somelike like the above, I get one line of text.
The only way I could see to do this was to start with a large font and scale it down until it fits.
double fontSize = 30;
tb.FontSize = fontSize;
while (CalculateIsTextTrimmed(tb))
{
fontSize--;
tb.FontSize = fontSize;
}
private static bool CalculateIsTextTrimmed(TextBlock textBlock)
{
Typeface typeface = new Typeface(
textBlock.FontFamily,
textBlock.FontStyle,
textBlock.FontWeight,
textBlock.FontStretch);
FormattedText formattedText = new FormattedText(
textBlock.Text,
System.Threading.Thread.CurrentThread.CurrentCulture,
textBlock.FlowDirection,
typeface,
textBlock.FontSize,
textBlock.Foreground);
formattedText.MaxTextWidth = textBlock.Width;
return (formattedText.Height > textBlock.Height);
}
Maybe a TextBlock would be better for presenting text-for-printing than a TextBox?
I tried implementing Jonah's solution. Inspired by This answer I wrapped it in a behavior (also note the addition of formattedText.Trimming = TextTrimming.None)
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;
namespace WpfApplication1
{
public class ScaleFontBehavior : Behavior<TextBlock>
{
// MaxFontSize
public static readonly DependencyProperty MaxFontSizeProperty = DependencyProperty.Register("MaxFontSize",
typeof (double), typeof (ScaleFontBehavior), new PropertyMetadata(20d));
// MinFontSize
public static readonly DependencyProperty MinFontSizeProperty = DependencyProperty.Register("MinFontSize",
typeof (double), typeof (ScaleFontBehavior), new PropertyMetadata(12d));
private readonly TextBlock dummy = new TextBlock();
public double MaxFontSize
{
get { return (double) GetValue(MaxFontSizeProperty); }
set { SetValue(MaxFontSizeProperty, value); }
}
public double MinFontSize
{
get { return (double) GetValue(MinFontSizeProperty); }
set { SetValue(MinFontSizeProperty, value); }
}
protected override void OnAttached()
{
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TextBlock.TextProperty,
typeof (TextBlock));
if (dpd != null)
{
dpd.AddValueChanged(AssociatedObject, delegate { CalculateFontSize(); });
}
AssociatedObject.SizeChanged += (s, e) => CalculateFontSize();
dummy.MaxWidth = AssociatedObject.MaxWidth;
dummy.TextWrapping = AssociatedObject.TextWrapping;
}
private void CalculateFontSize()
{
double fontSize = MaxFontSize;
AssociatedObject.FontSize = fontSize;
while (CalculateIsTextTrimmed(AssociatedObject))
{
fontSize--;
if (fontSize < MinFontSize) break;
AssociatedObject.FontSize = fontSize;
}
}
private static bool CalculateIsTextTrimmed(TextBlock textBlock)
{
var typeface = new Typeface(
textBlock.FontFamily,
textBlock.FontStyle,
textBlock.FontWeight,
textBlock.FontStretch);
var formattedText = new FormattedText(
textBlock.Text,
Thread.CurrentThread.CurrentCulture,
textBlock.FlowDirection,
typeface,
textBlock.FontSize,
textBlock.Foreground)
{ Trimming = TextTrimming.None };
formattedText.MaxTextWidth = textBlock.Width;
return (formattedText.Height > textBlock.Height);
}
}
class VisualHelper
{
public static List<T> FindVisualChildren<T>(DependencyObject obj) where T : DependencyObject
{
List<T> children = new List<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
var o = VisualTreeHelper.GetChild(obj, i);
if (o != null)
{
if (o is T)
children.Add((T)o);
children.AddRange(FindVisualChildren<T>(o)); // recursive
}
}
return children;
}
public static T FindUpVisualTree<T>(DependencyObject initial) where T : DependencyObject
{
DependencyObject current = initial;
while (current != null && current.GetType() != typeof(T))
{
current = VisualTreeHelper.GetParent(current);
}
return current as T;
}
}
}
Here's is an example of it's usage (type into the TextBox and see the text in the TextBlock scale to fit.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox x:Name="TextBox" MaxLines="10" AcceptsReturn="True" />
<TextBlock Text="{Binding ElementName=TextBox, Path=Text}" Height="200" Width="200" TextWrapping="Wrap">
<i:Interaction.Behaviors>
<wpfApplication1:ScaleFontBehavior MaxFontSize="50" MinFontSize="12" />
</i:Interaction.Behaviors>
</TextBlock>
</StackPanel>
</Window>
check if this works:
<Canvas>
<Viewbox Width="200" Height="200" Stretch="Uniform" >
<StackPanel Width="200" Height="200" >
<TextBox Width="Auto" Text="Test test test test test " TextWrapping="Wrap" AcceptsReturn="True" ></TextBox>
<TextBox Width="Auto" Text="Test test test test test " TextWrapping="Wrap" AcceptsReturn="True" ></TextBox>
<TextBlock Width="Auto" Text="Test test test test test " TextWrapping="Wrap" ></TextBlock>
</StackPanel>
</Viewbox>
</Canvas>

WPF for LCD screen Full HD

I am developing a WPF application that will be displayed in a Full-HD LCD screen (42 inch).
In addition, I need to accommodate the controls in absolute positions.
In the development environment I can not see a window in length 1920x1080 (this is the fixed resolution of the targeted screen).
What is the best practice to accomplish this task?
WPF uses Device Independent Units for specifying width/heights/positions/thicknesses, etc.
1 DIU/DIP = 1 physical pixel when your screen DPI is set to 96dpi.....but 1 DIU = a different number of physical pixels when the DPI is not 96dpi.
If you use a Canvas then it positions elements using DIUs.
Now you imply that you want to position absolutely in terms of pixel coordinates.
So to do this with the Canvas no matter what the current DPI setting is, you have to use a scaling trick (you can do this with a ViewBox, or a LayoutTransform).
The example below shows one way to achieve it (my screen is 1366x768....you can change it to Full HD).
It looks at the DPI of the system and gets the Canvas scaled down whenever the DPI goes up. This allows you to use Canvas coordinates that really mean pixel coords.
If you are able to change the users screen to 96dpi then there is no need to do the scaling trick because 1 DIU = 1 physical pixel at 96dpi...no rescaling needed.
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None"
AllowsTransparency="True" Background="White"
SizeToContent="WidthAndHeight"
Title="MainWindow" Loaded="Window_Loaded">
<Viewbox x:Name="viewbox">
<Canvas x:Name="canvas">
<Rectangle x:Name="rect" Canvas.Top="10" Canvas.Left="10" Stroke="Red" StrokeThickness="1"/>
<Button Canvas.Top="20" Canvas.Left="20">Test Button</Button>
<Ellipse Canvas.Top="100" Canvas.Left="100" Width="100" Height="100" Stroke="Red" StrokeThickness="10"/>
<TextBlock Canvas.Top="100" Canvas.Left="100" FontSize="15">Some Text</TextBlock>
</Canvas>
</Viewbox>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication12
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// HD
const int screenwidth = 1366;
const int screenheight = 768;
// FULL HD
//const int screenwidth = 1920;
//const int screenheight = 1080;
public MainWindow()
{
InitializeComponent();
Top = 0;
Left = 0;
canvas.Width = screenwidth;
canvas.Height = screenheight;
rect.Width = screenwidth - 20;
rect.Height = screenheight - 20;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
bool bScaleBackToPixels = true;
if (bScaleBackToPixels)
{
PresentationSource presentationsource = PresentationSource.FromVisual(this);
Matrix m = presentationsource.CompositionTarget.TransformToDevice;
double DpiWidthFactor = m.M11;
double DpiHeightFactor = m.M22;
viewbox.Width = screenwidth / DpiWidthFactor;
viewbox.Height = screenheight / DpiHeightFactor;
}
else
{
viewbox.Width = screenwidth;
viewbox.Height = screenheight;
}
}
}
}
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None"
AllowsTransparency="True" Background="White"
SizeToContent="WidthAndHeight"
Title="MainWindow" Loaded="Window_Loaded">
<Canvas x:Name="canvas">
<Rectangle x:Name="rect" Canvas.Top="10" Canvas.Left="10" Stroke="Red" StrokeThickness="1"/>
<Button Canvas.Top="20" Canvas.Left="20">Test Button</Button>
<Ellipse Canvas.Top="100" Canvas.Left="100" Width="100" Height="100" Stroke="Red" StrokeThickness="10"/>
<TextBlock Canvas.Top="100" Canvas.Left="100" FontSize="15">Some Text</TextBlock>
</Canvas>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication12
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// HD
const int screenwidth = 1366;
const int screenheight = 768;
// FULL HD
//const int screenwidth = 1920;
//const int screenheight = 1080;
public MainWindow()
{
InitializeComponent();
Top = 0;
Left = 0;
canvas.Width = screenwidth;
canvas.Height = screenheight;
rect.Width = screenwidth - 20;
rect.Height = screenheight - 20;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
bool bScaleBackToPixels = true;
if (bScaleBackToPixels)
{
PresentationSource presentationsource = PresentationSource.FromVisual(this);
Matrix m = presentationsource.CompositionTarget.TransformToDevice;
double DpiWidthFactor = m.M11;
double DpiHeightFactor = m.M22;
double scalex = 1 / DpiWidthFactor;
double scaley = 1 / DpiHeightFactor;
canvas.LayoutTransform = new ScaleTransform(scalex, scaley);
}
}
}
}
At the 96 DPI setting (Smaller - 100%) the screen looks like this:
At the 120 DPI setting (Medium - 125%) (i.e. 96 x 1.25 = 120DPI) the screen looks like this when using my ScaleBackToPixels technique above (i.e. it looks the same as the first screen).
At the 120 DPI setting (Medium - 125%) (i.e. 96 x 1.25 = 120DPI) the screen looks like this when you don't do any adjustments at all (notice how the circle is bigger, and the font and size of the Button).
All 3 images side by side for comparison:
Here is the transformation that makes the screen resolution 1920x1080 (FullHD) visible in my laptop screen resolution 1366x768:
XAML
<ContentControl Canvas.Left="1630" Canvas.Top="400" Content="{Binding Time}" />
<ContentControl Canvas.Left="1630" Canvas.Top="590" Content="{Binding NextPrayTime}" />
<ContentControl Canvas.Left="1650" Canvas.Top="700" Content="{Binding Today}" />
<ContentControl Canvas.Right="520" Canvas.Top="120" Content="{Binding Content}" />
<ContentControl Canvas.Left="0" Canvas.Top="965" Content="{Binding PrayTimes}">
</ContentControl>
</Canvas>
</Viewbox>
C#
static public class HD
{
static public float Width { get { return 1366.0f; } }
static public float Height { get { return 768.0f; } }
}
static public class FHD
{
static public float Width { get { return 1920.0f; } }
static public float Height { get { return 1080.0f; } }
}
static public class HDRatios
{
static public double Width
{
get
{
#if (DEBUG)
return double.Parse((HD.Width / FHD.Width).ToString("0.0"));
#else
return 1;
#endif
}
}
static public double Height
{
get
{
#if (DEBUG)
return double.Parse((HD.Height / FHD.Height).ToString("0.0"));
#else
return 1;
#endif
}
}
The code demonstrates that in development environment (DEBUG flag) the transformation will be applied and in the release version the transformation will not be applied since the Canvas.Left and Canvas.Top are according to the resolution of Full HD.
I hope that this experience will assist others that encounter displaying controls in WPF within a Canvas in absolute metrics.

Connect a line between two ellipses

I'm trying to connect a line between two ellipses where if one was dragged the line would move with it. I have a canvas and inside that are two stackpanels... in each stackpanel is an ellipse on the left... content control in the middle... and another ellipse on the right. The idea is to connect a line between the right ellipse from one stackpanel to the left ellipse in the second stackpanel. So far I have this but can't seem to get much farther as the propertypath being used to do the binding doesn't make too much sense to me... which is why I have a Canvas in there right now.
Line line = new Line();
line.Stroke = connectedEllipse.Fill;
line.StrokeThickness = 2;
Binding x1 = new Binding();
Binding x2 = new Binding();
Binding y1 = new Binding();
Binding y2 = new Binding();
x1.Path = new PropertyPath(Canvas.LeftProperty);
x2.Path = new PropertyPath(Canvas.LeftProperty);
y1.Path = new PropertyPath(Canvas.TopProperty);
y2.Path = new PropertyPath(Canvas.TopProperty);
x1.Source = y1.Source = connectedEllipse;
x2.Source = y2.Source = (sender as Ellipse);
line.SetBinding(Line.X1Property, x1);
line.SetBinding(Line.X2Property, x2);
line.SetBinding(Line.Y1Property, y1);
line.SetBinding(Line.Y2Property, y2);
Ok I've hacked up some code which doesn't use the attached properties method. This probably isn't "good" code since I wrote it up in 20 minutes but it will get you started.
MainWindow.xaml
<Window x:Class="EllipseTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:EllipseTest"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" >
<Window.Resources>
<ControlTemplate x:Key="template1">
<Ellipse Width="60" Height="30" Fill="Blue" />
</ControlTemplate>
</Window.Resources>
<Canvas Name="canvas">
<my:ExtendedThumb x:Name="thumb1" Canvas.Left ="0" Canvas.Top="0" DragDelta="myThumb_DragDelta" Template="{StaticResource template1}" />
<my:ExtendedThumb x:Name="thumb2" Canvas.Left ="50" Canvas.Top="20" DragDelta="myThumb_DragDelta" Template="{StaticResource template1}" />
</Canvas>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace EllipseTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Path path;
public MainWindow()
{
InitializeComponent();
}
private void myThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
ExtendedThumb thumb = e.Source as ExtendedThumb;
Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
if (thumb == thumb1)
UpdateLine(thumb, thumb2);
else
UpdateLine(thumb1, thumb);
}
private void UpdateLine(ExtendedThumb firstThumb, ExtendedThumb secondThumb)
{
double left1 = Canvas.GetLeft(firstThumb);
double top1 = Canvas.GetTop(firstThumb);
double left2 = Canvas.GetLeft(secondThumb);
double top2 = Canvas.GetTop(secondThumb);
thumb1.ConnectingLine.StartPoint = new Point(left1 +firstThumb.ActualWidth / 2, top1 + firstThumb.ActualHeight / 2);
thumb1.ConnectingLine.EndPoint = new Point(left2 + secondThumb.ActualWidth / 2, top2 + secondThumb.ActualHeight / 2);
thumb2.ConnectingLine.StartPoint = new Point(left2 + secondThumb.ActualWidth / 2, top2 + secondThumb.ActualHeight / 2);
thumb2.ConnectingLine.EndPoint = new Point(left1 + firstThumb.ActualWidth / 2, top1 + firstThumb.ActualHeight / 2);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
path = new Path();
path.Stroke = Brushes.Black;
path.StrokeThickness = 2;
canvas.Children.Add(path);
LineGeometry line = new LineGeometry();
path.Data = line;
thumb1.ConnectingLine = line;
thumb2.ConnectingLine = line;
UpdateLine(thumb1, thumb2);
}
}
}
ExtendedThumb.cs
using System;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Linq;
using System.Text;
namespace EllipseTest
{
public class ExtendedThumb : Thumb
{
public LineGeometry ConnectingLine { get; set; }
public ExtendedThumb() : base() { ConnectingLine = new LineGeometry(); }
}
}
Also, I got the idea from the contents of this link: http://denisvuyka.wordpress.com/2007/10/13/wpf-draggable-objects-and-simple-shape-connectors/

Open full screen an image with multitouch in WPF

I'm developing a multitouch application. There is one way to open the image in fullscreen mode when i do the pinchzoom?
The code is this:
<Window x:Class="TouchRect.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TouchRect"
Title="MainWindow" Height="700" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="189*"/>
<RowDefinition Height="472*"/>
</Grid.RowDefinitions>
<!--<local:RulerCanvas x:Name="canvas" >-->
<Image x:Name="image3" Width="74" Height="49" IsManipulationEnabled="True" Source="flower3.jpg" Margin="446,-268,458,408">
<Image.RenderTransform>
<MatrixTransform Matrix="2.41806325085411,0,0,2.41806325085411,280.737615796121,292.420001677231" />
</Image.RenderTransform>
</Image>
<Image x:Name="image2" Width="74" Height="49" IsManipulationEnabled="True" Source="flower2.jpg" Margin="110,-266,794,406" Stretch="Fill" >
<Image.RenderTransform>
<MatrixTransform Matrix="2.41806325085411,0,0,2.41806325085411,280.737615796121,292.420001677231"/>
</Image.RenderTransform>
</Image>
<Image x:Name="image" Width="74" Height="49" IsManipulationEnabled="True" Source="flower.jpg" Stretch=" fill" Margin="-248,-271,1152,411">
<Image.RenderTransform>
<MatrixTransform Matrix="2.41806325085411,0,0,2.41806325085411,280.737615796121,292.420001677231" />
</Image.RenderTransform>
</Image>
<MediaElement x:Name="media" Source="C:\Users\Public\Videos\Sample Videos\Wildlife.wmv" Canvas.Left="183" Canvas.Top="151" LoadedBehavior="Manual" IsManipulationEnabled="True" Margin="37,18,38,38" Grid.Row="1" />
<DataGrid AutoGenerateColumns="False" Height="0" HorizontalAlignment="Left" Margin="100,86,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="217" />
<!--</local:RulerCanvas>-->
</Grid>
I'm using this class in .cs
Where i have to add that code?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
namespace TouchRect
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
media.Volume = 100;
media.Play();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
canvas.ManipulationStarting += new EventHandler<ManipulationStartingEventArgs>(image_ManipulationStarting);
canvas.ManipulationDelta += new EventHandler<ManipulationDeltaEventArgs>(image_ManipulationDelta);
// inertia
canvas.ManipulationInertiaStarting += new EventHandler<ManipulationInertiaStartingEventArgs>(canvas_ManipulationInertiaStarting);
}
void canvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
{
// Decrease the velocity of the Rectangle's movement by
// 10 inches per second every second.
// (10 inches * 96 DIPS per inch / 1000ms^2)
e.TranslationBehavior = new InertiaTranslationBehavior()
{
InitialVelocity = e.InitialVelocities.LinearVelocity,
DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0)
};
// Decrease the velocity of the Rectangle's resizing by
// 0.1 inches per second every second.
// (0.1 inches * 96 DIPS per inch / (1000ms^2)
e.ExpansionBehavior = new InertiaExpansionBehavior()
{
InitialVelocity = e.InitialVelocities.ExpansionVelocity,
DesiredDeceleration = 0.1 * 96 / 1000.0 * 1000.0
};
// Decrease the velocity of the Rectangle's rotation rate by
// 2 rotations per second every second.
// (2 * 360 degrees / (1000ms^2)
e.RotationBehavior = new InertiaRotationBehavior()
{
InitialVelocity = e.InitialVelocities.AngularVelocity,
DesiredDeceleration = 720 / (1000.0 * 1000.0)
};
e.Handled = true;
}
UIElement last;
void image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
// lazy hack not in the blog post..
var uie = e.OriginalSource as UIElement;
if (uie != null)
{
if (last != null) Canvas.SetZIndex(last, 0);
Canvas.SetZIndex(uie, 2);
last = uie;
}
//canvas is the parent of the image starting the manipulation;
//Container does not have to be parent, but that is the most common scenario
e.ManipulationContainer = canvas;
e.Handled = true;
// you could set the mode here too
// e.Mode = ManipulationModes.All;
}
void image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
//this just gets the source.
// I cast it to FE because I wanted to use ActualWidth for Center. You could try RenderSize as alternate
var element = e.Source as FrameworkElement;
if ( element != null )
{
//e.DeltaManipulation has the changes
// Scale is a delta multiplier; 1.0 is last size, (so 1.1 == scale 10%, 0.8 = shrink 20%)
// Rotate = Rotation, in degrees
// Pan = Translation, == Translate offset, in Device Independent Pixels
var deltaManipulation = e.DeltaManipulation;
var matrix = ((MatrixTransform)element.RenderTransform).Matrix;
// find the old center; arguaby this could be cached
Point center = new Point ( element.ActualWidth/2, element.ActualHeight/2) ;
// transform it to take into account transforms from previous manipulations
center = matrix.Transform(center);
//this will be a Zoom.
matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);
// Rotation
matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);
//Translation (pan)
matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
((MatrixTransform)element.RenderTransform).Matrix = matrix;
e.Handled = true;
// We are only checking boundaries during inertia
// in real world, we would check all the time
if (e.IsInertial)
{
Rect containingRect = new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);
Rect shapeBounds = element.RenderTransform.TransformBounds(new Rect(element.RenderSize));
// Check if the element is completely in the window.
// If it is not and intertia is occuring, stop the manipulation.
if (e.IsInertial && !containingRect.Contains(shapeBounds))
{
//Report that we have gone over our boundary
e.ReportBoundaryFeedback(e.DeltaManipulation);
// comment out this line to see the Window 'shake' or 'bounce'
// similar to Win32 Windows when they reach a boundary; this comes for free in .NET 4
e.Complete();
}
}
}
}
}
You will have to do that with code behind. Do these steps:
this.WindowState = WindowState.Normal;
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
this.Topmost = true;
this.Top = 0;
this.Left = 0;
The seemingly useless first line is actually workaround to weird behavior of WPF window (where the window being maximized will not cover task bar if it is already maximized).
And as for the multitouch, here is tutorial.

canvas not occupying full space in grid

I have a canvas in grid. On the mousemove event of canvas i am trying to translate the canvas. It works fine. However my canvas doesn't occupy the full space in the grid. What changes do i need to make in this program so that the canvas occupies the full space.
This is my xaml :-
<UserControl x:Class="SilverlightTestCanvasDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="canvas" Margin="0" Background="Red">
<TextBlock Canvas.Left="84" TextWrapping="Wrap" Text="This is some text to test whether screen is moving" Canvas.Top="99" Height="84" Width="196" FontSize="18.667" FontFamily="Cambria"/>
</Canvas>
</Grid>
</UserControl>
This is the code :-
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SilverlightTestCanvasDemo
{
public partial class MainPage : UserControl
{
private bool _isDown = false;
private Point _lastPoint;
public MainPage()
{
InitializeComponent();
this.Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
canvas.MouseLeftButtonDown += canvas_MouseLeftButtonDown;
canvas.MouseLeftButtonUp += canvas_MouseLeftButtonUp;
canvas.MouseMove += canvas_MouseMove;
}
void canvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_isDown)
{
Point point = e.GetPosition(canvas);
double deltaX = point.X - _lastPoint.X;
double deltaY = point.Y - _lastPoint.Y;
CompositeTransform transform = null;
if (!(canvas.RenderTransform is CompositeTransform))
{
transform = new CompositeTransform();
canvas.RenderTransform = transform;
}
else
{
transform = canvas.RenderTransform as CompositeTransform;
}
transform.TranslateX += deltaX;
transform.TranslateY += deltaY;
//canvas.Height += deltaY;
//canvas.Width += deltaX;
_lastPoint = e.GetPosition(canvas);
}
}
void canvas_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
_isDown = false;
}
void canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
_isDown = true;
_lastPoint = e.GetPosition(canvas);
}
}
}
Thanks in advance :)
Try this:-
<Grid x:Name="LayoutRoot">
<Canvas x:Name="canvas" Margin="0" Background="AliceBlue">
<Canvas>
<TextBlock Canvas.Left="84" TextWrapping="Wrap" Text="This is some text to test whether screen is moving" Canvas.Top="99" Height="84" Width="196" FontSize="18.667" FontFamily="Cambria"/>
</Canvas>
</Canvas>
</Grid>
and tweak the mouse move code behind to this:-
void canvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_isDown)
{
Point point = e.GetPosition(canvas);
double deltaX = point.X - _lastPoint.X;
double deltaY = point.Y - _lastPoint.Y;
CompositeTransform transform = null;
if (!(canvas.Children[0].RenderTransform is CompositeTransform))
{
transform = new CompositeTransform();
canvas.Children[0].RenderTransform = transform;
}
else
{
transform = canvas.Children[0].RenderTransform as CompositeTransform;
}
transform.TranslateX += deltaX;
transform.TranslateY += deltaY;
_lastPoint = e.GetPosition(canvas);
}
}
What's happening here is a second inner Canvas is being used as a caddy to hold the set of actual children. Now you need only transform this inner canvas to move all the content about.

Resources