【问题标题】:UWP/WinRT: How to make the tab key behave as normal in a TextBox?UWP/WinRT:如何使 Tab 键在 TextBox 中表现正常?
【发布时间】:2015-11-01 15:54:09
【问题描述】:

默认情况下,文本框不插入制表符。当您按 Tab 时,它会将焦点移至下一个元素。当您按下 Ctrl-Tab 时,它会插入一个制表符。

如何修复这种行为,使其表现得像人们通常期望的文本框一样,例如 Tab 键使用制表符插入缩进?此外,如何将 Ctrl-Tab 重新映射到替代功能?

对于插入制表符的第一个问题,我可以附加到TextBox的KeyDown事件,如果按下的键是Tab,则将事件标记为已处理以防止TextBox失去焦点,但是如何插入Tab角色?

当我附加到文本框的 KeyDown 事件时,如果已按住 Ctrl,则按 Tab 键根本不会触发侦听器。如果我附加到 TextBox 的 KeyUp 事件,按下 tab 键确实会被拾起,但只有在它已经将一个选项卡插入到 TextBox 之后。如果没有这种不需要的行为,如何重新映射 Ctrl-Tab?

我正在使用 C++/CX。

【问题讨论】:

标签: textbox windows-runtime c++-cx uwp


【解决方案1】:

如果其他人遇到同样的情况,这是我最终开发的解决方案。在我看来,这个问题的简单程度令人震惊,而且也相当不令人满意。如果有人有更好的解决方案,我很想听听。

一般的想法是重写 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 的撤消数据被擦除。

缺点可能意味着此解决方案无法使用。同样,如果有更好的解决方案,我很想听听。至少,也许看到我的方法的结果可以省去其他人自己实施和发现所有这些问题的麻烦。

【讨论】:

  • 所以回顾一下,我对你所做的一项更改(当然,它在 C# 中)是编辑 TextBox 的 SelectedText 中的内容,而不是处理完整的 @ 987654324@ 财产。如果我在您的代码中遗漏了某些内容,我深表歉意,但我不必担心撤消擦除。有很多内部扩展代码,但是here's what I'm doing for my first cut at this.
猜你喜欢
  • 2015-10-31
  • 2012-09-15
  • 2019-10-31
  • 2017-09-21
  • 1970-01-01
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多