3

I'd like to enhance this WPF DateTimePicker control by adding an Adorner above and below the selected field, something like

DateTimePicker

To do so I need to figure out the X coordinate of the beginning and end of the selection in the TextBox. How can I do that?

Qwertie
  • 16,354
  • 20
  • 105
  • 148
  • Sending messages directly to the edit control using win32 API might help. Edit control supports a messages called EM_POSFROMCHAR look at http://msdn.microsoft.com/en-us/library/windows/desktop/bb761631(v=vs.85).aspx – nanda Nov 14 '12 at 18:42
  • @nanda: WPF controls aren't based on Win32 at all and don't have any HWND, so that can't be used. – Julien Lebosquain Nov 14 '12 at 18:44
  • Sorry, missed to notice that you had mentioned wpf as a tag. – nanda Nov 14 '12 at 18:46

1 Answers1

2

(EDIT: Derp - I missed your "only the selection" part...this would give you the full text length)

The property you're looking for is ExtentWidth on the TextBox:

(Sorry, only have LINQPad on hand, so gotta do this the hard way...)

var wnd = new Window();
var panel = new StackPanel();
wnd.Content = panel;

var textBox = new TextBox();
textBox.Name = "theTextBox";
textBox.FontFamily = new FontFamily("Arial");
textBox.FontSize = 20;
textBox.Text = "This is some text I want to measure";
panel.Children.Add(textBox);

wnd.Show();

var showWidth = new TextBlock();
showWidth.Text = "This should show the size of the text";
var binding = new System.Windows.Data.Binding();
binding.Path = new PropertyPath("ExtentWidth");
binding.Source = textBox;
binding.Mode = System.Windows.Data.BindingMode.OneWay;
showWidth.SetBinding(TextBlock.TextProperty, binding);
panel.Children.Add(showWidth);

EDIT #2: Ok, try this instead: (Again, only LINQPad)

void Main()
{
    var wnd = new Window();
    var panel = new StackPanel();
    var textBox = new TextBox();
    textBox.FontSize = 20;
    textBox.Text = "This is some text I want to measure";
    textBox.SelectionChanged += OnSelectionChanged;
    showWidth = new TextBlock();
    panel.Children.Add(textBox);
    panel.Children.Add(showWidth);
    wnd.Content = panel;
    wnd.Show();
}

private TextBlock showWidth;

private void OnSelectionChanged(object sender, EventArgs args)
{
    var tb = sender as TextBox;
    double left = tb.GetRectFromCharacterIndex(tb.SelectionStart).Left;
    showWidth.Text = string.Format("{0:0}px", left);
    showWidth.Margin = new Thickness(left, 0, 0, 0);
}
Qwertie
  • 16,354
  • 20
  • 105
  • 148
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • I simplified `OnSelectionChanged` if you don't mind... the key to it is `GetRectFromCharacterIndex`. – Qwertie Nov 14 '12 at 21:46
  • Not a problem - threw it together way too quickly, just wanted to make a "runnable harness" around that one call. :) – JerKimball Nov 14 '12 at 21:52