65288


いつもお世話になっております．

WPFでテキストエディタを作成しており，ALT+H,J,K,Lのショートカットでキャレットを上下左右に移動させる機能（vimのカーソル移動のキーバインドのALT同時押しバージョン）を実装しようと思いました．

現在はInputManagerを用いて実装を試みています．しかしこの方法だとALTキーが押されたままの扱いとなり，入力がALT+←，ALT+↑，というように処理されるためキャレットが移動しません．  
キーのシミュレートをする際にModifierキーの押下をキャンセルする方法または，.Net側で提供されるキャレットの上下左右移動を実現する関数(QtにおけるQPlainTextEditのmoveCursor関数のような)などはないでしょうか．

以下が実装したコードを簡略化したものです．

### Editor.cs

[code]

    //using Namespaces ...
    
    namespace editor {
        class Editor : TextBox {
            public Editor() { /* initialize */ }
    
            public void SendKey(Key key) {
                PresentationSource presentationSource = PresentationSource.FromVisual(this);
                InputManager.Current.ProcessInput(new KeyEventArgs(Keyboard.PrimaryDevice, presentationSource, Environment.TickCount, key)
                {
                    RoutedEvent = PreviewKeyDownEvent
                });
            }
        }
    }
    
[/code]

### EditorViewModel.cs

[code]

    //using Namespaces ...
    
    namespace editor {
        class EditorViewModel : INotifyPropertyChanged {
            public event PropertyChangedEventHandler PropertyChanged;
    
            public ICommand Up { get; private set; }
            public ICommand Down { get; private set; }
            public ICommand Left { get; private set; }
            public ICommand Right { get; private set; }
    
            public EditorViewModel() {
                Up = new UpCommand();
                Down = new DownCommand();
                Left = new LeftCommand();
                Right = new RightCommand();
            }
        }
    
        class UpCommand : ICommand
        {
            public event EventHandler CanExecuteChanged;
    
            public bool CanExecute(object parameter) => true;
    
            public void Execute(object parameter)
            {
                Editor editor = parameter as Editor;
                editor.SendKey(Key.Up);
            }
        }
    
        class DownCommand : ICommand
        {
            public event EventHandler CanExecuteChanged;
    
            public bool CanExecute(object parameter) => true;
    
            public void Execute(object parameter)
            {
                Editor editor = parameter as Editor;
                editor.SendKey(Key.Down);
            }
        }
    
        class LeftCommand : ICommand
        {
            public event EventHandler CanExecuteChanged;
    
            public bool CanExecute(object parameter) => true;
    
            public void Execute(object parameter)
            {
                Editor editor = parameter as Editor;
                editor.SendKey(Key.Left);
            }
        }
    
        class RightCommand : ICommand
        {
            public event EventHandler CanExecuteChanged;
    
            public bool CanExecute(object parameter) => true;
    
            public void Execute(object parameter)
            {
                Editor editor = parameter as Editor;
                editor.SendKey(Key.Right);
            }
        }
    }
    
[/code]

### Editor.xaml

[code]

    <TextBox x:Name="editor" ...>
      <TextBox.InputBindings>
        <KeyBinding Command={Binding Up} Gesture="Alt+K" CommandParameter="{Binding ElementName=editor}" />
        <KeyBinding Command={Binding Down} Gesture="Alt+J" CommandParameter="{Binding ElementName=editor}" />
        <KeyBinding Command={Binding Left} Gesture="Alt+H" CommandParameter="{Binding ElementName=editor}" />
        <KeyBinding Command={Binding Right} Gesture="Alt+L" CommandParameter="{Binding ElementName=editor}" />
      </TextBox.InputBindings>
    </TextBox>
    
[/code]

因みにCaretIndexプロパティを書き換えてキャレットを移動させるという方法もありますが，この方法だとキャレットの上下移動の再現がタブ文字などの関係で煩雑なコードになってしまうのでできれば避けたいです．

**開発環境**  
Windows 10(1803)  
VisualStudio 2017，  
.NET Framework 4.5

宜しくお願いします．


CC BY-SA 4.0
2020-03-29T11:07:50.740
65201
2020-04-01T23:52:42.540
2020-04-01T23:52:42.540
32650
32650
question
c# .net wpf
WPFのTextBoxでKeyBindingを介した方向キーのシミュレート


自己解決しました．

WPFにおいてドキュメント系コントロールの操作はEditingCommandsクラスのメンバを用いて行えます．  
<https://docs.microsoft.com/ja-
jp/dotnet/api/system.windows.documents.editingcommands?view=netframework-4.8>

今回の質問においては，

[code]

    <KeyBinding Command="EditingCommands.MoveDownByLine" Gesture="Alt+J" />
    <KeyBinding Command="EditingCommands.MoveUpByLine" Gesture="Alt+K" />
    <KeyBinding Command="EditingCommands.MoveLeftByCharacter" Gesture="Alt+H" />
    <KeyBinding Command="EditingCommands.MoveRightByCharacter" Gesture="Alt+L" />
    
[/code]

または，

[code]

    public void Execute(object parameter)
    {
        Editor editor = parameter as Editor;
        EditingCommands.MoveUpByLine(null, editor);
    }
    
[/code]

とすればよいです．


CC BY-SA 4.0
2020-04-01T23:51:29.083
65288
2020-04-01T23:51:29.083
32650
65201
answer