投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/11/17 10:20:58
> 配列の形にしてみましたが、Paintのところが良くわかりませんでした。
たとえばこんな感じ。

Partial Public Class Form1
  '描画する箱の一覧 
  Private boxes As New List(Of Rectangle)()
  '現在選択中の箱 
  Private selectedBox As Rectangle?
  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    KeyPreview = True
  End Sub

  Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    '既存の箱があれば、選択状態にするため selectedBox 変数に入れておく 
    selectedBox = boxes.FirstOrDefault(Function(b) b.Contains(e.Location))
    If selectedBox.HasValue AndAlso selectedBox.Value.IsEmpty Then
      selectedBox = Nothing
      'クリックされるたびに 15x15 サイズの箱を追加する 
      boxes.Insert(0, New Rectangle(e.X - 7, e.Y - 7, 15, 15))
    End If
    '描画すべき内容が変化したことを Form に知らせる 
    Invalidate()
  End Sub
  Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    For Each box In boxes
      '選択している箱は赤、未選択は黒で描画する 
      e.Graphics.DrawRectangle(If(box = selectedBox, Pens.Red, Pens.Black), box)
    Next
  End Sub

  Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    If selectedBox.HasValue Then
      '箱の選択中に DELETE が押されればその箱を削除、ESCAPE なら選択解除 
      If e.KeyCode = Keys.Delete Then
        boxes.Remove(selectedBox.Value)
        Invalidate()
      ElseIf e.KeyCode = Keys.Escape Then
        selectedBox = Nothing
        Invalidate()
      End If
    End If
  End Sub
End Class




> 直してみたのですが、この形で、2つ以上の複数キー同時押しは、
> どのように取得するのでしょうか?
どのキーとどのキーの同時押しを想定しておられますか?

まず KeyDown/KeyPress/KeyUp は、修飾キー以外の同時押しを
捉えられるような設計にはなっていません。

Shift, Ctrl, Alt といった「修飾キー」は同時押しに対応していますが、
それ以外のキーは、そもそも同時押しを保証していないためです。
ゲーミングキーボードの中には、同時入力への反応が良いものもあるようですが、
通常のキーボードの場合、下記のような制限があるため、必ずしも同時入力に対応できません。
http://dailynewsagency.com/2014/03/08/microsoft-applied-sciences-group-bbw/


そうした制限があることを踏まえた上で、複数同時押しの判定のために
「指定したキーが現在押された状態になっているかどうか」を調べることは可能です。
参照設定に PresentationCore と WindowsBase を加えた上で、下記のようにします。

' 現在、[←]キーが押された状態になっていれば True 
If System.Windows.Input.Keyboard.GetKeyStates(System.Windows.Input.Key.Left).HasFlag(System.Windows.Input.KeyStates.Down) Then


あるいは、RawInput でキューを捕らえるといった手法もあります。


> MymbaseとMeもまだ呑み込めてません・・・
MyBase / MyClass / Me のことでしょうか?

https://shimonss.hatenablog.com/entry/2017/06/04/143411
https://smdn.jp/programming/vb.net/me_myclass_mybase/
http://rucio.a.la9.jp/main/VBdotNet/Advance/Advance3.htm
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/program-structure/me-my-mybase-and-myclass


Me は自身のインスタンスを表し、
MyClass は、自クラスのメンバーを参照する際に利用し、
MyBase は、基底クラスのメンバーを参照する際に利用します。

この違いがあるため、イベントハンドラーの
 Handles MyBase.Load
 Handles Me.Load
は、厳密に言えば異なる結果になることがあります。

Partial Public Class Form1
  '通常であれば、これら 3 つは同じように動作しますが… 
  Private Sub Form1_Load_0(sender As Object, e As EventArgs) Handles Me.Load
    ListBox1.Items.Add("Me.Load")
  End Sub
  Private Sub Form1_Load_1(sender As Object, e As EventArgs) Handles MyBase.Load
    ListBox1.Items.Add("MyBase.Load")
  End Sub
  Private Sub Form1_Load_2(sender As Object, e As EventArgs) Handles MyClass.Load
    ListBox1.Items.Add("MyClass.Load")
  End Sub

  '独自の Load イベントがシャドーイングされていた場合、上記の違いが見えてきます 
  Public Shadows Event Load As EventHandler
  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    '自クラスである Form1 で定義された Load イベントを呼び出す 
    RaiseEvent Load(Me, EventArgs.Empty)
    'この場合、基底クラス(Form) の Load では無いので、MyBase.Load は発生しない 
  End Sub
  ' 上記の「Shadows Event Load」と「Sub Button1_Click」が無買った場合は、 
  ' "Me.Load", "MyBase.Load", "MyClass.Load" が同じように動作します 

  Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    '基底クラスである Form の Load イベントを呼び出すための Protected なメソッド 
    MyBase.OnLoad(EventArgs.Empty)
  End Sub
End Class