默认情况下,文本框不插入制表符。当您按 Tab 时,会将焦点移至下一个元素。当您按 Ctrl-Tab 时,它会插入一个制表符。
如何修复此行为,使其像人们通常期望文本框的行为一样,例如 Tab 键使用制表符插入缩进?此外,如何将 Ctrl-Tab 重新映射到替代功能?
对于插入制表符的第一个问题,我可以附加到 TextBox 的 KeyDown 事件,如果按下的键是 Tab,则将该事件标记为已处理以防止 TextBox 失去焦点,但是如何插入 Tab性格?
当我附加到文本框的 KeyDown 事件时,如果已经按住 Ctrl 键,则按 Tab 键根本不会触发监听器。如果我附加到 TextBox 的 KeyUp 事件,按下 Tab 键确实会被拾取,但前提是它已经将选项卡插入到 TextBox 中。如何重新映射 Ctrl-Tab 而不发生这种不需要的行为?
我正在使用 C++/CX 工作。
最佳答案
如果其他人遇到同样的情况,这里是我最终开发的解决方案。在我看来,这个问题如此简单却令人震惊地丑陋,而且也相当令人不满意。如果有人有更好的解决方案,我很想听听。
总体思路是重写 Tab 的 KeyDown 事件以插入“\t”字符。如果能够覆盖 Ctrl+Tab 的 KeyDown 事件,那就太好了,但这似乎不可能,因为 TextBox 上的某种硬编码吞没了 Ctrl+Tab KeyDown 事件,并且它甚至永远不会触发。因此,Ctrl+Tab 的 KeyUp 事件被覆盖。
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,直到松开 Tab。
触发时,会短暂地看到选项卡正在创建和删除,这看起来很糟糕。
使用 Ctrl+Tab 会导致 TextBox 的撤消数据被删除。
缺点可能意味着该解决方案无法使用。再说一次,如果有更好的解决方案,我很想听听。至少,也许看到我的方法的结果可以省去其他人自己实现和发现所有这些问题的麻烦。
关于textbox - UWP/WinRT : How to make the tab key behave as normal in a TextBox?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31907616/