投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/1/21 14:10:31
> ネットで調べてKeyDataというものとKeyCodeというものがあるらしい、というところまでは分かったのですが、それ以上よく分からなかったため、
KeyPress イベントの e.KeyChar は、さほど悩むところでもありませんが、
KeyDown / KeyUp イベントは、ちょっとわかりにくいですよね。
e.KeyCode / e.KeyData に加えて e.KeyValue というものまでありますし…。


まず、同時押しされる『修飾キー』ですが、これは e.Modifiers で得られます。

ここでいう修飾キーとは Ctrlキー、Shiftキー、Altキーの 3 種を
指しており、Windows キーはここに含まれません。
キーボードによっては、修飾キーが左右2か所に配置されることもありますが
複数のキーがあった場合、このイベントでは両者を区別できません。

もしも左右の修飾キー、たとえば LShiftKey と RShiftKey を区別したいような場合には、
ProcessKeyMessage メソッドをオーバーライドすることで調べられます。

修飾キーがどれも押されていなければ、e.Modifiers は Keys.None を返します。

3 種すべての修飾キーがすべて押されている場合には、
 If e.Modifiers = (Keys.Shift Or Keys.Control Or Keys.Alt) Then
のように、それぞれをビット Or 加算した値として捉えられます。
あるいは上記と同じ処理を、
 If e.Shift AndAlso e.Control AndAlso e.Alt Then
と書くこともできます。
And/Or/AndAlso/OrElse を混同しないように注意してください。


このように、KeyDown や KeyUp であれば e.Modifiers を使って修飾キーを捉えられますが、
KeyPress や MouseDown などには e.Modifiers がありません。しかし、同等機能が
Control クラスにある「ModifierKeys 共有プロパティ」からも得られますので、
 If e.Modifiers = (Keys.Shift Or Keys.Control Or Keys.Alt) Then
に相当する処理を
 If ModifierKeys = (Keys.Shift Or Keys.Control Or Keys.Alt) Then
と書くこともできます。


なお、文献によっては「Shift キーが押された状態」を
 If e.Modifiers.HasFlags(Keys.Shift) Then
 If (e.Modifiers And Keys.Shift) = Keys.Shift Then
 If (e.Modifiers And Keys.Shift) <> 0 Then
などと記していることもあるのですが、これらの記述法は注意が必要です。
上記はあくまでも Shift キーの状態しか判断していないため、
「Shift」だけでなく、「Ctrl+Shift」「Alt+Shift」「Ctrl+Alt+Shift」の
組み合わせにも反応することになってしまいます。



次は、一番大事な e.KeyCode 。これは、「修飾キー以外」のキーを指します。
また、e.KeyValue は CInt(e.KeyCode) と同義です。

e.KeyCode は物理的なキー位置を示しますので、
CapsLock が On の時の "A" も、CapsLock が Off の時の "a" も、
どちらも Keys.A という同じ情報が返されます。
("A" と "a" を区別する場合は、KeyPress イベントの e.KeyChar を使えます)

そしてこの e.KeyCode ですが……実は修飾キーが単体で押されている場合も
e.KeyCode が Keys.None になることはありません。次のような値になります。

Shift キーが押されている場合は、e.KeyCode = Keys.ShiftKey (Modifiers = Keys.Shift)
Ctrl キーが押されている場合は、e.KeyCode = Keys.ControlKey (Modifiers = Keys.Control)
Alt キーが押されている場合は、e.KeyCode = Keys.Menu (Modifiers = Keys.Alt)




最後は、混乱されていた e.KeyData ですが、
これは e.Modifiers と e.KeyCode のビット OR 演算したものです。
つまり「e.KeyData」と「e.Modifiers Or e.KeyCode」が同じ値になります。

e.KeyData の中から、e.Modifiers の成分だけを取り出す場合には、Keys.Modifiers 値をビット AND 演算します。
つまり「e.KeyData And Keys.Modifiers」と「e.Modifiers」が同じ値になります。

e.KeyData の中から、e.KeyCode の成分だけを取り出す場合には、Keys.KeyCode 値をビット AND 演算します。
つまり「e.KeyData And Keys.KeyCode」と「e.KeyCode」が同じ値になります。

これが、先の回答で『e.KeyData と e.KeyCode の混在利用は不自然』と述べた所以です。


つまり、元のコードでいうところの
> If e.KeyCode = Keys.KeyCode.Alt And e.KeyData = Keys.KeyCode.Enter Then 'Alt + Enter Key
のコードについては、実際には
 If e.Modifiers = Keys.Alt AndAlso e.KeyCode = Keys.Enter Then
あるいは
 If e.KeyData = (Keys.Alt Or Keys.Return) Then
もしくは
 If e.KeyCode = Keys.Enter AndAlso e.Alt AndAlso Not e.Control AndAlso Not e.Shift Then
などと記述します。(どれでも同じ結果が得られます)

結果だけ見れば、元のコードでも同じ結果を得られるのですが、
警告 BC42025 の件と合わせて見直しておかれた方が良いでしょう。