61065


お世話になっております。  
C#のContextMenuStripでShift+Enterを検出したいのですが、うまくいきません。  
具体的にはクリックされた時のイベントでWindowsAPIのGetKeyStateでShiftキーの状態を取得しているんですが、そもそもShift+Enterではクリックしたときのイベントが起きないようです。  
ちなみに、Shiftキーを押しながら、普通にマウスで左クリックしたときはうまくいくようです。  
何か方法はあるでしょうか。  
以上、よろしくお願いします。


CC BY-SA 4.0
2019-12-03T11:37:58.607
61064
2019-12-03T14:22:51.567
29034
question
c#
C#のメニューでShift+Enterを取得したい


'Shift' の状態だけを取るなら `Control.ModifierKeys.HasFlag(Keys.Shift)` で取れます。

例

[code]

            private void timer1_Tick(object sender, EventArgs e)
            {
                if (Control.ModifierKeys.HasFlag(Keys.Shift))
                {
                    this.label1.Text = "Shift ON";
                } 
                else
                {
                    this.label1.Text = "Shift OFF";
                }
            }
    
[/code]

> そもそもShift+Enterではクリックしたときのイベントが起きないようです。

あ、こっちのほうが問題だったんですね。  
contextMenuStrip1 PrevKeyDown イベント の中で キーを判定して SHIFT + RETURN の場合に  
選択されている メニューを呼び出すようにコーディングしてみました。

[code]

    this.contextMenuStrip1.PreviewKeyDown += 
    new System.Windows.Forms.PreviewKeyDownEventHandler(this.contextMenuStrip1_PreviewKeyDown);
    
[/code]

[code]

    private void contextMenuStrip1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyData.HasFlag(Keys.Shift)
            && e.KeyData.HasFlag(Keys.Return))
        {
            var cMenu = sender as ContextMenuStrip;
            if (cMenu != null)
            {
                var selectItem = cMenu.Items.Cast<ToolStripMenuItem>()
                        .Where(r => r.Selected == true).FirstOrDefault();
    
                selectItem?.PerformClick();
            }
        }
    }
    
[/code]

それっぽく動作すると思います。


CC BY-SA 4.0
2019-12-03T12:21:36.303
61065
2019-12-03T14:22:51.567
2019-12-03T14:22:51.567
18851
18851
61064
answer


この記事がVBの質問でEnterキーのことですが、同様のことを扱っています。  
[KeyDown event doesn't fire on ContextMenuStrip with enter
key?](https://stackoverflow.com/q/20751326/9014308)  
質問

> .NET : I have a Context menu strip that I want to handle using keyboard
> keys.  
>  I have the following event handler:
[code]

>     Private Sub ContextMenuEnterKey(ByVal Sender As Object, ByVal E As
> KeyEventArgs) Handles ContextMenu.KeyDown
>         If E.KeyValue = Keys.Enter Then
>             'Do some staff
>         End If
>     End Sub
>  
[/code]

>
> The events fires correctly with other keys except EnterKey.  
>  Does anyone know what's wrong with that ?

回答

> To which control's KeyDown event are you binding your handler? In the Forms
> designer the ? KeyDown event isn't even shown for ContextMenuStrip (at least
> here in VS2012, and I'm working in C#...) I can bind to in in code, but this
> doesn't seem to have any effect.
>
> But there is a PreviewKeyDown event in ContextMenuStrip which gets called
> for every keystroke within the context menu, also for the Enter key. Maybe
> this can help you?
>
>
> ただし、ContextMenuStripにはPreviewContextDownイベントがあり、コンテキストメニュー内のすべてのキーストロークに対して、またEnterキーに対しても呼び出されます。  
>  たぶんこれはあなたを助けることができますか？

* * *

こんな感じで登録しておけば：

[code]

    this.contextMenuStrip1.PreviewKeyDown += ContextMenuStrip1_PreviewKeyDown;
    
[/code]

こちらのイベントハンドラで入力されたキーの処理がCtrl/Alt/Shift併押下判断も含めてできます。  
ただしカーソルを動かした等の全部のキーが入ってきます。

[code]

    private void ContextMenuStrip1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        Console.WriteLine("IsInputKey={0}, KeyCode={1}, KeyData={2}, KeyValue={3}, Modifiers={4}\n", e.IsInputKey.ToString(), e.KeyCode.ToString("X"),e.KeyData.ToString("X"),e.KeyValue.ToString("X"),e.Modifiers.ToString("X"));
    }
    
[/code]

参考：  
[Control.PreviewKeyDown イベント](https://docs.microsoft.com/ja-
jp/dotnet/api/system.windows.forms.control.previewkeydown?view=netframework-4.8)  
[PreviewKeyDownEventArgs クラス](https://docs.microsoft.com/ja-
jp/dotnet/api/system.windows.forms.previewkeydowneventargs?view=netframework-4.8)

>
[code]

>     プロパティ
>     Alt         Alt キーが押されたかどうかを示す値を取得します。
>     Control     Ctrl キーが押されたかどうかを示す値を取得します。
>     IsInputKey  キーが通常の入力キーであるかどうかを示す値を取得または設定します。
>     KeyCode     KeyDown イベントまたは KeyUp イベントのキーボード コードを取得します。
>     KeyData     KeyDown や KeyUp イベントに対する SHIFT、CONTROL、ALT
> キーなどのキー修正子と組み合わせたキー コードを取得します。
>     KeyValue    KeyDown イベントまたは KeyUp イベントのキーボード値を取得します。
>     Modifiers   KeyDown イベントまたは KeyUp イベントの修飾フラグを取得します。
>     Shift       Shift キーが押されたかどうかを示す値を取得します。
>  
[/code]

[コントロールで矢印、Tab、Enter、Escキーが押されたことを知る](https://dobon.net/vb/dotnet/control/btndetectarraykey.html)

>
> PreviewKeyDownイベントはKeyDownイベントの前に発生します。KeyDownやKeyUpイベントが発生しないようなキーが押された場合も発生し、押されたキーを知ることができます。  
>
> さらに、KeyDownやKeyUpイベントが発生しないようなキーが押された場合でも、PreviewKeyDownイベントハンドラでPreviewKeyDownEventArgs.IsInputKeyプロパティをTrueにすることにより、KeyDownやKeyUpイベントが発生するようになります。ただしこの場合は、そのキー本来の機能（例えば、矢印キーであれば、フォーカスの移動）は失われます。


CC BY-SA 4.0
2019-12-03T12:44:42.623
61067
2019-12-03T14:12:00.150
2019-12-03T14:12:00.150
26370
26370
61064
answer