トップ回答者
タッチによるテキストの選択について

質問
回答
-
グリッパーを作るなら、こんなかんじ。
#こまかいことを実装してる時間がないのでマウスでグリッパーの処理のみです。(本当はAdornerでやるのが理想)
<UserControl x:Class="WpfApplication1.AnchorCaretTextBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <UserControl.Resources> <Style TargetType="Thumb" x:Key="anchor"> <EventSetter Event="DragDelta" Handler="Thumb_DragDelta" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Thumb"> <Grid Canvas.Left="100" Canvas.Top="100"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Rectangle Width="2" Height="{Binding FontSize,ElementName=txb}" Fill="Black" /> <Ellipse Grid.Row="1" Width="20" Height="20" Stroke="Black" StrokeThickness="2" Fill="White" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources> <Grid> <TextBox Text="AAAAAAAAAAAAA" FontSize="30" DockPanel.Dock="Top" AcceptsReturn="true" CaretBrush="Transparent" SelectionChanged="TextBox_SelectionChanged" ScrollViewer.ScrollChanged="TextBox_ScrollChanged" x:Name="txb"> </TextBox> <Canvas x:Name="canvas" Visibility="Visible" > <Thumb Style="{StaticResource anchor}" x:Name="thumbA" /> <Thumb Style="{StaticResource anchor}" x:Name="thumbB" /> </Canvas> </Grid> </UserControl>
namespace WpfApplication1 { using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Controls.Primitives; public partial class AnchorCaretTextBox : UserControl { public AnchorCaretTextBox() { InitializeComponent(); } public override void OnApplyTemplate() { base.OnApplyTemplate(); thumbStart = thumbA ; thumbEnd = thumbB; } /// <summary>選択範囲が変わったらアンカー用のThumbの位置を移動させる</summary> private void TextBox_SelectionChanged(object sender, RoutedEventArgs e) { TextBox txb = (TextBox)sender; UpdateThumbPosition(txb); } /// <summary>スクロールで選択範囲の描画位置が変わったらThumbを移動させる</summary> private void TextBox_ScrollChanged(object sender, ScrollChangedEventArgs e) { UpdateThumbPosition((TextBox)sender); } /// <summary>Thumbを選択範囲に一致させる</summary> private void UpdateThumbPosition(TextBox txb) { Point pStart = txb.GetRectFromCharacterIndex(txb.SelectionStart).Location; Point pEnd = txb.GetRectFromCharacterIndex(txb.SelectionStart + txb.SelectionLength).Location; SetCanvas(thumbStart, pStart, true); SetCanvas(thumbEnd, pEnd, true); } private void SetCanvas(Control ctl, Point p, bool isVisible) { if (ctl != null) { if (isVisible) { ctl.Visibility = System.Windows.Visibility.Visible; if (!double.IsInfinity(p.X)) { Canvas.SetLeft(ctl, p.X - ctl.ActualWidth / 2); } if (!double.IsInfinity(p.Y)) { Canvas.SetTop(ctl, p.Y); } } else { ctl.Visibility = System.Windows.Visibility.Hidden; } } } /// <summary>Thumbが移動されたらTextBoxの選択範囲を変更する</summary> private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { Thumb CaretThumb = (Thumb)sender; Thumb anchorThumb; var p = Mouse.GetPosition(txb); if (!isDragging) { isDragging = true; CaretThumb.MouseUp += CaretThumb_MouseUp; offset = Mouse.GetPosition(CaretThumb).Y / 2; } p = new Point(p.X, p.Y - offset); int caretIndex = txb.GetCharacterIndexFromPoint(p, true); int anchorIndex; if (CaretThumb == thumbStart) { anchorThumb = thumbEnd; anchorIndex = txb.SelectionStart + txb.SelectionLength; } else { anchorThumb = thumbStart; anchorIndex = txb.SelectionStart; } if (caretIndex < anchorIndex) { txb.SelectionStart = caretIndex; txb.SelectionLength = anchorIndex - caretIndex; thumbStart = CaretThumb; thumbEnd = anchorThumb; } else { txb.SelectionStart = anchorIndex; txb.SelectionLength = caretIndex - anchorIndex; thumbStart = anchorThumb; thumbEnd = CaretThumb; } } private void CaretThumb_MouseUp(object sender, MouseButtonEventArgs e) { ((Thumb)sender).MouseUp -= CaretThumb_MouseUp; isDragging = false; } private Thumb thumbStart; private Thumb thumbEnd; private bool isDragging; private double offset; } }
長押ししたらワード単位に選択範囲を広げる処理とグリッパーの表示を切り替える処理を追加してやってください。
ワード選択はRichTextBoxならParagraphなどで文字列をある程度は解析できるので、それでワード単位を解析してやるとか。個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)