|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Common Control API
Routines SendMessage: Perform Hit Testing in ListViews |
||
Posted: | Thursday January 20, 2000 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows NT4 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Prerequisites |
The hit test code works with both the VB6 mscomctl.ocx and
VB5 comctl32.dll controls.
The FullRowSelect property is available only on the VB6 control. VB5 users should see the VBnet FullRowSelect API method in the Common Controls Library. When using the VB5 control, enhanced Comctl32 functionality is only available to users with comctl32.dll version 4.70 or greater installed. This dll is typically installed with IE3.x or greater. |
|
This
page demonstrates using the LVHITTESTINFO type along with the LVM_SUBITEMHITTEST message to determine where on the control the mouse was
clicked, regardless of the view mode or whether the FullRowSelect feature has been enabled (Label1). The code is provided in the MouseDown
event to both take advantage of the mouse coordinates passed, as well as providing a mechanism to perform an action before the corresponding
ItemClick event is fired. The MouseDown event also contains a line that will select the primary list item whenever a SubItem is
clicked, even in non-FullRowSelect mode.
Note that the illustration shows the selected list index as its 0-based API value. This page contains all the code required to build the demonstration app shown. It also works when an imagelist has been assigned to the control; in that case it will accurately identify and report where the control was clicked - overtop the text or overtop the icon (Label2). |
BAS Module Code |
None. |
|
Form Code |
Create a new project, adding a VB5 or VB6 ListView control (ListView1), along with a check box (Check1) and two labels (Label1, Label2). You can optionally add an ImageList populated with at least a single 16x16 icon, assigning it to the SmallIcon property of the ListView. Add the following code to the form: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const LVM_FIRST As Long = &H1000 Private Const LVM_HITTEST As Long = (LVM_FIRST + 18) Private Const LVM_SUBITEMHITTEST As Long = (LVM_FIRST + 57) Private Const LVHT_NOWHERE As Long = &H1 Private Const LVHT_ONITEMICON As Long = &H2 Private Const LVHT_ONITEMLABEL As Long = &H4 Private Const LVHT_ONITEMSTATEICON As Long = &H8 Private Const LVHT_ONITEM As Long = (LVHT_ONITEMICON Or _ LVHT_ONITEMLABEL Or _ LVHT_ONITEMSTATEICON) Private Type POINTAPI x As Long y As Long End Type Private Type LVHITTESTINFO pt As POINTAPI flags As Long iItem As Long iSubItem As Long 'ie3+ only .. was NOT in win95. 'Valid only for LVM_SUBITEMHITTEST End Type Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Private Sub Check1_Click() ListView1.FullRowSelect = Not ListView1.FullRowSelect End Sub Private Sub Form_Load() Dim itmX As ListItem Dim itmH As ColumnHeader Dim n As Long 'Crete dummy data in the ListView With ListView1 .View = lvwReport .FullRowSelect = False .LabelEdit = lvwManual For n = 1 To 4 Set itmH = .ColumnHeaders.Add(, , "Column " & CStr(n)) itmH.Width = 1000 Next For n = 1 To 20 Set itmX = .ListItems.Add(, , "Item " & CStr(n)) itmX.SubItems(1) = CStr(n) itmX.SubItems(2) = CStr(n ^ 2) itmX.SubItems(3) = CStr(n ^ 3) Next End With End Sub Private Sub ListView1_MouseDown(Button As Integer, _ Shift As Integer, _ x As Single, y As Single) Dim HTI As LVHITTESTINFO Dim itmX As ListItem Dim msg1 As String Dim msg2 As String '---------------------------------------- 'this gets the hittest info using 'the mouse co-ordinates With HTI .pt.x = (x \ Screen.TwipsPerPixelX) .pt.y = (y \ Screen.TwipsPerPixelY) .flags = LVHT_ONITEM End With Call SendMessage(ListView1.hwnd, LVM_SUBITEMHITTEST, 0, HTI) '---------------------------------------- 'this determines whether the hit test 'returned a main or sub item If HTI.iSubItem = 0 Then If HTI.iItem > -1 Then msg1 = "User clicked over main item " & HTI.iItem Else msg1 = "User clicked a main item's white space" End If ElseIf HTI.iSubItem > 0 Then msg1 = "User clicked main item " & HTI.iItem & _ " by clicking SubItem " & HTI.iSubItem End If '---------------------------------------- 'this determines what part of 'the item or SubItem was clicked If HTI.flags And LVHT_ONITEM Then If HTI.flags And LVHT_ONITEMICON Then msg2 = "(click occurred over the item's icon area)" End If If HTI.flags And LVHT_ONITEMLABEL Then Select Case HTI.iSubItem Case 0: msg2 = "(click occurred over the item's main text)" Case Else: msg2 = "(click occurred over the SubItem text)" End Select End If End If '---------------------------------------- 'this selects the current item if the 'control's FullRowSelect is False, and 'a SubItem was clicked. (One is added 'because the API is 0-based, and the 'ListItems collection is 1-based). If HTI.iSubItem > 0 Then ListView1.ListItems(HTI.iItem + 1).Selected = True End If Label1.Caption = msg1 Label2.Caption = msg2 End Sub |
Comments |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |