Public Class Form1 Private hook As ListViewHook Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load hook = New ListViewHook(ListView1) End Sub Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed hook.ReleaseHandle() End Sub End Class
' 下記では NativeWindow で WndProc を捕らえていますが、解放の手間が発生するので、 ' 実際には ListView を Inherits して WndProc を捕らえる方法をお奨めします Public Class ListViewHook Inherits NativeWindow Private target As ListView Public Sub New(lvw As ListView) If lvw Is Nothing Then Throw New ArgumentNullException(NameOf(lvw)) target = lvw AssignHandle(lvw.Handle) End Sub Protected Overrides Sub WndProc(ByRef m As Message) Select Case m.Msg Case &H201 To &H209 'WM_LBUTTONDOWN〜WM_MBUTTONDBLCLK Dim lp As Integer If IntPtr.Size = 8 Then lp = CInt(m.LParam.ToInt64() And &HFFFFFFFFL) Else lp = m.LParam.ToInt32() End If Dim pos As New Point(lp And &HFFFF, lp >> 16) Dim hit = target.HitTest(pos) Select Case hit.Location Case ListViewHitTestLocations.AboveClientArea Case ListViewHitTestLocations.BelowClientArea Case ListViewHitTestLocations.LeftOfClientArea Case ListViewHitTestLocations.RightOfClientArea Case ListViewHitTestLocations.None Return End Select End Select MyBase.WndProc(m) End Sub End Class
■No93958 (魔界の仮面弁士 さん) に返信 > 2020/02/27(Thu) 11:02:35 編集(投稿者) > > ■No93954 (harunex さん) に返信 >>例えば、ListViewにアイテムが5つ表示されている状態で、 > > System.Windows.Controls.ListView ではなく、 > System.Windows.Forms.ListView の話で良いでしょうか。 > > >>6番目以降(何も無い空白の項目)を >>クリックすると、元々選択されているアイテムの選択が外れます。 > > Windows のエクスプローラーでファイル一覧を表示している時、 > 余白部をクリックすると、同じ動作になりますね。 > > >>これを防止するために、何か対策ございませんでしょうか。 > > SelectionMode = One な ListBox であれば、選択が外れないのですよね。 > Multi何某を指定した場合は、最後の選択が解除されてしまいますが。 > > > ListView の場合は、どうあっても最後の選択が解除されるので、 > WndProc を捕らえて、余白クリック時の手続きを握りつぶすという > 強硬手段ぐらいしか思い当たらないです。 > > とりあえずサンプル。 > ただし MultiSelect 時のドラッグ選択機能も失われてしまう点に注意。 > > Public Class Form1 > Private hook As ListViewHook > Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load > hook = New ListViewHook(ListView1) > End Sub > Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed > hook.ReleaseHandle() > End Sub > End Class > > ' 下記では NativeWindow で WndProc を捕らえていますが、解放の手間が発生するので、 > ' 実際には ListView を Inherits して WndProc を捕らえる方法をお奨めします > Public Class ListViewHook > Inherits NativeWindow > Private target As ListView > Public Sub New(lvw As ListView) > If lvw Is Nothing Then Throw New ArgumentNullException(NameOf(lvw)) > target = lvw > AssignHandle(lvw.Handle) > End Sub > Protected Overrides Sub WndProc(ByRef m As Message) > Select Case m.Msg > Case &H201 To &H209 'WM_LBUTTONDOWN〜WM_MBUTTONDBLCLK > Dim lp As Integer > If IntPtr.Size = 8 Then > lp = CInt(m.LParam.ToInt64() And &HFFFFFFFFL) > Else > lp = m.LParam.ToInt32() > End If > Dim pos As New Point(lp And &HFFFF, lp >> 16) > Dim hit = target.HitTest(pos) > Select Case hit.Location > Case ListViewHitTestLocations.AboveClientArea > Case ListViewHitTestLocations.BelowClientArea > Case ListViewHitTestLocations.LeftOfClientArea > Case ListViewHitTestLocations.RightOfClientArea > Case ListViewHitTestLocations.None > Return > End Select > End Select > MyBase.WndProc(m) > End Sub > End Class