2015-08-09 9 views
1

По умолчанию текстовое поле не вставляет символы табуляции. Когда вы нажимаете Tab, вместо этого он перемещает фокус на следующий элемент. Когда вы нажимаете Ctrl-Tab, он вставляет символ табуляции.UWP/WinRT: Как заставить ключ вкладки вести себя как обычно в TextBox?

Как это поведение может быть зафиксировано так, как обычно люди ожидают, что текстовые поля будут вести себя так, чтобы клавиша Tab вставляла отступ с использованием символа табуляции? Кроме того, как можно переместить Ctrl-Tab в альтернативную функцию?

Для первого вопроса о вставке символа табуляции я могу подключиться к событию KeyDown в TextBox, и если нажата клавиша Tab, то отметьте событие как обработанное, чтобы предотвратить потерять TextBox, но как я могу вставить Таб-символ?

Когда я прикрепляю к событию KeyDown текстового поля, нажатие клавиши Tab никогда не запускает прослушиватель вообще, если Ctrl уже удерживается. Если я присоединюсь к событию KeyUp в TextBox, нажатие клавиши табуляции будет поднято, но только после того, как она уже вставила вкладку в TextBox. Как можно переделать Ctrl-Tab без этого нежелательного поведения?

Я работаю в C++/CX.

+0

Возможно, это помогает: http: // stackoverflow.com/questions/12654213/allow-user-to-use-tab-in-richeditbox-in-windows-8-app – sibbl

+0

@sibbl К сожалению, этот подход не работает для TextBox, потому что нет эквивалента, который могут быть доступны напрямую, насколько я могу рассказать объектной модели документа RichEditBox. –

+0

Я делаю то же, что и ваш ответ. Интересный факт: [Ctrl-I вставляет вкладку] (http://stackoverflow.com/questions/35045514/how-to-stop-control-i-from-inserting-a-tab-in-a-uwp-textbox- в-corewindow-сферы). Не знаю, откуда появился этот странный TextBox (см. Также [weird newline management] (http://stackoverflow.com/questions/35138047/textbox-text-substringtextbox-selectionstart-doesnt-work-because-selectedtext) в [' SelectedText', 'SelectionLength' и т. Д.] (Https://social.msdn.microsoft.com/Forums/en-US/f31f34ed-8751-4792-99d6-7c080582d899)), но я надеюсь, что Microsoft приходит в себя и рефакторирует Это./sigh – ruffin

ответ

1

В случае, если кто-то еще находится в той же ситуации, вот решение, которое я закончил. Это, на мой взгляд, ужасно уродливо, насколько просто проблема, а также довольно неудовлетворительная. Если у кого-то есть лучшее решение, я хотел бы услышать об этом.

Общая идея - переопределить событие KeyDown для Tab, чтобы вставить символ '\ t'. Было бы замечательно также переопределить событие KeyDown для Ctrl + Tab, но это не представляется возможным, поскольку какой-то hardcoding в TextBox поглощает событие Ctrl + Tab KeyDown, и он даже не срабатывает. Поэтому событие KeyUp для Ctrl + Tab переопределяется.

KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) 
{ 
    if (e->Key == VirtualKey::Control) m_CtrlKeyPressed = true; 
    else if (e->Key == VirtualKey::Tab) { 
     // There is no need to test for if Ctrl is pressed here, since Ctrl-Tab appears to 
     // be hardcoded into TextBox. 
     // When Ctrl is pressed, a KeyDown event for Tab is never fired by TextBox. 

     // Normally TextBox will try to give up focus when Tab is pressed - this prevents 
     // that. 
     e->Handled = true; 

     // Platform::Strings support almost no operations, so we will need to cast the 
     // TextBox's text into a wstring to insert. 
     TextBox^ textBox = static_cast<TextBox^>(sender); 
     std::wstring modifiedString(textBox->Text->Data()); 

     // SelectionStart works as current cursor position even when no text is selected. 
     int cursorPosition = textBox->SelectionStart; 

     // Unfortunately, casting into a wstring reveals Windows line-endings as \r\n, 
     // which count as two characters now. 
     // Therefore, every time we run into a line-ending our cursorPosition will become 
     // off by one, so we need to compensate. 
     int offsetDueToLineEndings = 0; 
     for (int i = 0; i < cursorPosition + offsetDueToLineEndings; i++) 
     { 
      if (modifiedString[i] == '\r') offsetDueToLineEndings++; 
     } 
     modifiedString.insert(cursorPosition + offsetDueToLineEndings, 1, '\t'); 

     // Unfortunately, this text replacement wipes TextBox's built-in undo data. 
     textBox->Text = ref new String(modifiedString.c_str()); 
     textBox->SelectionStart = cursorPosition + 1; 
    } 
} 


KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) 
{ 
    if (e->Key == VirtualKey::Control) m_CtrlKeyPressed = false; 
    else if (m_CtrlKeyPressed) 
    { 
     if (e->Key == VirtualKey::Tab) { 
      // See KeyDown for Tab for comments on this code. 
      TextBox^ textBox = static_cast<TextBox^>(sender); 
      std::wstring modifiedString(textBox->Text->Data()); 

      int cursorPosition = textBox->SelectionStart; 

      int offsetDueToLineEndings = 0; 
      for (int i = 0; i < cursorPosition + offsetDueToLineEndings; i++) 
      { 
       if (modifiedString[i] == '\r') offsetDueToLineEndings++; 
      } 
      modifiedString.erase(cursorPosition + offsetDueToLineEndings - 1, 1); 

      textBox->Text = ref new String(modifiedString.c_str()); 
      textBox->SelectionStart = cursorPosition - 1; 

      // Do something with Ctrl+Tab 
     } 
    } 
} 

С этой реализацией существует ряд серьезных проблем.

Для простого Tab печати:

  • Вставка из Tab приводит данные отмены для TextBox протирать.

Для печати Ctrl + Tab:

  • Если пользователь удерживает Ctrl + Tab, несколько вкладок будут вставлены, пока он не освободит Tab.

  • При запуске в течение сплит-момента открывается и удаляется вкладка, которая выглядит дрянной.

  • Использование Ctrl + Tab приводит к уничтожению данных отмены для TextBox.

Недостатки, вероятно, означают, что это решение непригодно. Опять же, если есть лучшее решение, я хотел бы услышать об этом. По крайней мере, возможно, увидев результаты моего подхода, вы можете спасти кого-то еще от проблемы внедрения и обнаружения всех этих проблем.

+1

Так что оглядываясь назад, одно изменение, которое я сделал из того, что у вас есть (предоставлено, это на C#), заключается в том, чтобы редактировать то, что находится в TextBox 'SelectedText', а не обрабатывать полное свойство Text. Извиняюсь, если я что-то пропустил с вашим кодом, но мне не нужно беспокоиться об уничтожении. Там много внутреннего кода расширения, но [вот что я делаю для своего первого разреза на этом] (http://pastebin.com/0xTLLh12). – ruffin