LoginSignup
0
2

More than 3 years have passed since last update.

【備忘録】複数行テキストボックスで改行とIME確定を見分ける

Posted at

要件は以下の通り。

  1. 複数行入力可能なTextBoxで、
  2. 日本語入力と英語入力が混ざった状態で、
  3. IME入力の確定には反応せず、
  4. 改行を表すEnterキーが押されたことを検知する

(Visual Studio 2019・.NET Framework4.7.2)

要件1

作るだけ。

MainWindow.xaml

<Window x:Class="sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:sample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="Txtbox" Margin="20,20,20,20" Padding="5,5,5,5" Text=""
                 AcceptsReturn="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto"/>
    </Grid>
</Window>

できた。

image.png

要件2~4

確認のため、とりあえず普通に、KeyDownを検知してみる。

MainWindow.xaml

    <Grid>
        <TextBox x:Name="Txtbox" Margin="20,20,20,20" Padding="5,5,5,5" Text=""
                 AcceptsReturn="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto"
                 KeyDown="Txtbox_KeyDown"/>
    </Grid>

MainWindow.xaml.cs

private void Txtbox_KeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("{0}が押されました!", e.Key.ToString());
}

これでよし。

image.png

なんでやねん。

英語入力しか検知できないようです。

作戦変更

Enterキーが物理的に押されているかどうか確認する。CtrlキーやShiftキーが押されていた場合の動作は別途用意すれば良い。

MainWindow.xaml.cs

private void Txtbox_KeyDown(object sender, KeyEventArgs e)
{
    if (Keyboard.IsKeyDown(Key.Return))
    {
        Console.WriteLine("Enterキーが押されました!");
    }
}

これでよし。

image.png

なんでやねん。

先ほどの結果と合わせて考えると、IME確定も改行もKeyDownイベントとして認識されていないっぽい。

さらに作戦変更

検知するイベントを変えます。

MainWindow.xaml

    <Grid>
        <TextBox x:Name="Txtbox" Margin="20,20,20,20" Padding="5,5,5,5" Text=""
                 AcceptsReturn="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto"
                 PreviewKeyDown="Txtbox_PreviewKeyDown"/>
    </Grid>

MainWindow.xaml.cs

private void Txtbox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    Console.WriteLine("{0}が押されました!", e.Key.ToString());
}

image.png

いけそう。

MainWindow.xaml.cs

private void Txtbox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key.ToString() == "Return")
    {
        Console.WriteLine("改行されました!");
        // ここ、正しくは、「改行されそう!」ですが、そんなことは気にしない。
    }
}

image.png

完璧です。

結局

PreviewKeyDownイベントで、e.Key.ToString() == "Return"を判定してやればよい。

ちなみになぜこれを備忘録として残す事になったかというと、ネットで調べるとTextChangedイベントで、テキストボックスの行数が変わったら改行するというコードが先に出てきて、謎実装しかけるはめになったから。
ちなみに、TextChangedイベントを使うと、最後のEnterが改行として使われてからイベントが発火することになるため、それを許さない要件の場合そもそも使えない。(つまり、「あいうえお」の「い」と「う」の間にカーソルがある状態で、イベントを発火させようとしてEnterすると、先に改行が入るため、「あい\r\nうえお」を処理する羽目になる。)
その点、PreviewKeyDownイベントを使えば、e.Handled = true;としてやることで、キーイベントの処理を明示的に終了できるので、その心配も無い。

さらにちなみに、KeyEventArgs.ImeProcessedKeyというのもあるみたいだが、これは英語圏で使われる文字を打ったときは全部Noneを返してくるので、今回のように改行を検知したいなら、Keyboard.IsKeyDown(Key.Return) && e.ImeProcessedKey.ToString() == "None"とすれば使えないこともない。
そうではなく、IME確定を検知したいなら、e.ImeProcessedKey.ToString() == "Return"となるので、強い味方となりそうだ。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2