Skip to main content

Past Blast

Featured Products

Windows Mobile Developer Controls
Windows Mobile Developer Controls
Stay in touch using the DEVBUSS RSS feeds.
 

News

Windows Mobile Developer Controls
Windows Mobile Developer Controls

Performance Grid

Written by Pete Vickers  [author's bio]  [read 46341 times]
Edited by Derek

Download the code

Page 1  Page 2  Page 3 

And the code for the Find_Subitem is...

Private Sub Find_Subitem(X As Long, Y As Long)
Dim xlv As Long
Dim Rect As Long
Dim subitem As Long
xlv = AllocPointer(20)
Call SetLongAt(xlv, 0, X)
Call SetLongAt(xlv, 4, Y)
Dim Lret As Long
lv.SetFocus
Lret = SendMessage(GetFocus(), _
LVM_SUBITEMHITTEST, 0, xlv)
subitem = GetLongAt(xlv, 16)
FreePointer (xlv)
Rect = AllocPointer(16)
Call SetLongAt(Rect, 0, LVIR_LABEL)
Call SetLongAt(Rect, 4, subitem)
Lret = SendMessage(GetFocus(), _
LVM_GETSUBITEMRECT, _
lv.SelectedItem.Index, Rect)
Lret = MapWindowPoints(GetFocus(), _
frmGrdPerf.hWnd, Rect, 2)
siLeft = GetLongAt(Rect, 0)
siTop = GetLongAt(Rect, 4)
siRight = GetLongAt(Rect, 8)
siBottom = GetLongAt(Rect, 12)
txtFocus.Move _
(siLeft + 4) * Screen.TwipsPerPixelX, _
(siTop * Screen.TwipsPerPixelY) - 200, _
(siRight - siLeft) * Screen.TwipsPerPixelX, _
(siBottom - siTop) * Screen.TwipsPerPixelY
FreePointer (Rect)
If subitem <> 0 Then
txtFocus.Text = _
lv.SelectedItem.SubItems(subitem)
Else
txtFocus.Text = _
lv.ListItems(lv.SelectedItem)
End If
txtFocus.Visible = True
txtFocus.ZOrder
txtFocus.SelStart = 0
txtFocus.SelLength = Len(txtFocus.Text)
txtFocus.SetFocus
End Sub

The structure used for LVM_SUBITEMHITTEST is...

Public Type LVHITTESTINFO
pt As POINTAPI
flags As Long
iItem As Long
iSubItem As Long
End Type

And pointapi is...

Public Type POINTAPI
X As Long
Y As Long
End Type

First of all we allocate 20 bytes for the structure we need for the LVM_SUBITEMHITTEST. Next we supply the x and y values using SetLongAt, and do a sendmessage of LVM_SUBITEMHITTEST. This will return us the number of the subitem selected, and we extract it using GetLongAt. If the subitem returned is 0, it means the user has clicked on the item as opposed to the subitem. The next task is to 'highlight' the item or subitem. VB6 uses the 'rect' structure...

Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Using a sendmessage of LVM_GETSUBITEMRECT, we get the coordinates of the sub item. This is now where I get a bit lost. According to MSDN, "The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one window to a coordinate space relative to another window." It may well do, but as it was in Brads code, it needs to be in ours. We get back the coordinates, and move the text box to those coordinates. We then take the value from the grid, and enter it in the text box, and finally, make the text box visible.

A menu is provided in the demo code, so that you can see the effect of switching on gridlines etc.

In conclusion

Phew - that is it. Not the easiest of solutions, but in the worst case above, we have created a solution that is 70 TIMES QUICKER, and even in the best case, we are 9 TIMES QUICKER!

If anybody can suggest improvements on the code, or any ideas to make the grid perform as quickly as the listview control, I am sure we would all be pleased to take it on board. Maybe one idea is to use method 3, but clip the grid every 100 records or so, as constantly adding to the string will affect performance.

Meanwhile, I am steering clear of the grid control.

Thanks to articles written by Yaroslav Goncharov, Chris Tacke and Brad Martinez.

As a final aside, I did some testing on my 'real world' app. This read and formatted 2623 records each containing 19 fields, and displayed them. The test was run 10 times.

The average time using a grid, and the .clip method was 102.1 seconds per run.

The average time using the listview control was 71.9 seconds per run.

Previous Page