|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| Visual Basic Common
Control API Routines SHGetFileInfo: ListView Demo 4 - Adding the Associated Icons Last of four pages to create a ListView application to retrieve files from a specified folder. |
||
| Posted: | Sunday March 1, 1997 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB4-32, VB5, VB6 | |
| Developed with: | VB4-32, Windows 95 | |
| OS restrictions: | None | |
| Author: | VBnet - Randy Birch | |
| Related: | SHGetFileInfo: ListView Demo 1 - Obtaining the File Path SHGetFileInfo: ListView Demo 2 - Populating the ListView SHGetFileInfo: ListView Demo 3 - Adding Sorting Functionality SHGetFileInfo: ListView Demo 4 - Adding the Associated Icons |
|
| Prerequisites |
| SHGetFileInfo: ListView Demo 3 - Adding Sorting Functionality
This method is intended for Visual Basic 5 or Visual Basic 6 where the Common Control library used is the MSComCtl 5 version (comctl32.ocx). Because the VB6-specific mscomctl.ocx (Common Controls 6) is a complete implementation of comctl32.dll and not reliant on the version of comctl32.dll installed, this routine may not work when applied to a listview created from the VB6-specific mscomctl.ocx. 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. |
|
|
By
far the most complicated code yet, this page adds the code necessary to retrieve the Windows associated icon for a given file, assign it to
an imagelist dynamically, and use it to display with the file in the listview. Among the features of the method detailed here is the reuse of
an icon if it has already been added to the imagelist, improving both performance and resource issues.
When the demo is completed, the final app will retrieve the users selection and populate the listview with selected files from that folder, complete with associated icons, file name, file type, file size and created date. To the project form, add the following new controls:
Before using the picture boxes and imagelist, a couple of preparation steps are required. Set the properties for both picture boxes to the following:
If you've kept the form's ScaleMode as Twips, then 240 is equivalent to 16 pixels. Finally, set:
Image lists can not be bound to an object (the ListView) if it is empty. Similarly, it can not be cleared if it is bound to a control. To circumvent these limitations, add any 16x16 icon to the imagelist as picture 1. The Key and Tag properties can be left empty. However, because an icon is required when dynamically clearing then reassigning the imagelist, a dummy icon is needed to place into picture 1 through code. Therefore to pixDummy, assign a 16x16 icon or bitmap as well. The icons or bitmaps used above can be any as long as they are 16x16 pixels in size, as they are actually never shown. An imagelist cannot contain bitmaps (images) of different sizes; the size of the first bitmap assigned determines the size of all bitmaps in the imagelist. Therefore you must assign a 16x16 bitmap to the imagelist, and a 16x16 image to pixDummy for the images to display properly in the ListView. If your ListView shows the icons as stretched 32x32 icons, check the original image size again. Align lbIconCount under the listview to the left. Set its AutoSize property to True. Align lbItemCount under the listview to the right. Set its AutoSize property to True, and its alignment to Right Justify. With the preparation out of the way, you can begin to add the code required. |
| BAS Module Code |
| There are no changes to the general declarations area of the project's bas module. |
|
|
| Form Code |
|
|
| Make the following additions to the form code: |
|
|
Option Explicit In the form's general declarations, add:
Dim DOSExeIconLoaded As Boolean
In the form code, make the following bolded changes:
Private Sub Form_Load()
Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2
With Combo1
.AddItem "All Files and Folders (*.*)"
.AddItem "Applications (*.exe)"
.AddItem "Device Drivers (*.drv)"
.AddItem "Documents (*.doc)"
.AddItem "Dynamic Link Libraries (*.dll)"
.AddItem "Rich Text Format Documents (*.rtf)"
.AddItem "System Files (*.sys)"
.AddItem "Visual Basic Modules (*.bas)"
.AddItem "Visual Basic Forms (*.frm)"
.AddItem "Visual Basic 3 Projects (*.mak)"
.AddItem "Visual Basic 4 Projects (*.vbp)"
.AddItem "Postscript Printer Font Metrics (*.pfm)"
.AddItem "Text Files (*.txt)"
.AddItem "True Type Fonts (*.ttf)"
.AddItem "Windows Help Files (*.hlp)"
.AddItem "Windows Shortcuts (*.lnk)"
.ListIndex = 0
End With
With ListView1
.SortKey = 0
.SmallIcons = ImageList1
End With
UpdateFrequency = 25
prevOrder = 0
End Sub
Add the following new code to the form:
Function HiWord(dw As Long) As Integer
If dw And &H80000000 Then
HiWord = (dw \ 65535) - 1
Else
HiWord = dw \ 65535
End If
End Function
Private Function InitializeImageList() As Boolean
On Local Error GoTo InitializeError
Set ListView1.SmallIcons = Nothing
ImageList1.ListImages.Clear
ImageList1.ListImages.Add , "dummy", pixDummy.Picture
Set ListView1.SmallIcons = ImageList1
InitializeImageList = True
Exit Function
InitializeError:
InitializeImageList = False
End Function
Private Function vbAddFileItemIcon(hImgSmall&) As Long
Dim r As Long
pixSmall.Picture = LoadPicture()
r& = ImageList_Draw(hImgSmall&, shinfo.iIcon, pixSmall.hDC, 0, 0, ILD_TRANSPARENT)
pixSmall.Picture = pixSmall.Image
vbAddFileItemIcon& = hImgSmall&
End Function
Make the following modifications to the routines
vbGetFileList and vbAddFileItemView:
Private Sub vbAddFileItemView(WFD As WIN32_FIND_DATA)
Dim sFileName As String
Dim ListImgKey As String
Dim fType As String
sFileName = TrimNull(WFD.cFileName)
If sFileName <> "." And sFileName <> ".." Then
Dim r As Long
Dim tExeType As Long
Dim itmX As ListItem
Dim hImgSmall As Long
Dim hExeType As Long
Dim imgX As ListImage
On Local Error GoTo AddFileItemViewError
hImgSmall& = SHGetFileInfo(fPath & sFileName, _
0&, shinfo, Len(shinfo), _
BASIC_SHGFI_FLAGS Or SHGFI_SMALLICON)
fType$ = LCase$(TrimNull(shinfo.szTypeName))
ListImgKey = fType
If fType = "application" Or fType = "shortcut" Then
If fType = "application" Then
tExeType = SHGetFileInfo(fPath & sFileName, _
0&, shinfo, Len(shinfo), SHGFI_EXETYPE)
hExeType = HiWord(tExeType)
End If
If hExeType > 0 Or fType = "shortcut" Then
r = vbAddFileItemIcon(hImgSmall)
Set imgX = ImageList1.ListImages.Add(, sFileName, pixSmall.Picture)
ListImgKey = sFileName
Else
ListImgKey = "DOSExeIcon"
If DOSExeIconLoaded = False Then
r = vbAddFileItemIcon(hImgSmall)
Set imgX = ImageList1.ListImages.Add(, ListImgKey, pixSmall.Picture)
DOSExeIconLoaded = True
End If
End If
End If
Set itmX = ListView1.ListItems.Add(, , LCase$(sFileName))
itmX.SmallIcon = ImageList1.ListImages(ListImgKey).Key
itmX.SubItems(1) = vbGetFileSizeKBStr(WFD.nFileSizeHigh + WFD.nFileSizeLow)
itmX.SubItems(2) = fType
itmX.SubItems(3) = vbGetFileDate(WFD.ftCreationTime)
End If
Exit Sub
AddFileItemViewError:
If vbAddFileItemIcon(hImgSmall) Then
Set imgX = ImageList1.ListImages.Add(, fType, pixSmall.Picture)
End If
Resume
End Sub
Private Sub vbGetFileList()
Dim hFile As Long
Dim fName As String
Dim fExt As String
Dim counter As Integer
Dim WFD As WIN32_FIND_DATA
Me.MousePointer = vbArrowHourglass
DoEvents
fExt = vbGetComboFileSpec()
If Len(fPath) > 0 And Len(fExt) > 0 Then
fName$ = fPath & fExt
DisplayName = fName
DoEvents
If InitializeImageList() Then
ListView1.ListItems.Clear
DoEvents
hFile& = FindFirstFile(fName, WFD)
If hFile& > 0 Then
counter = 1
vbAddFileItemView WFD
While FindNextFile(hFile, WFD)
counter = counter + 1
vbAddFileItemView WFD
If counter = UpdateFrequency Then
Call UpdateWindow(ListView1.hwnd)
counter = 0
End If
Wend
End If
FindClose hFile
End If
End If
lbIconCount = "The ImageList for this target file type view contains " & _
ImageList1.ListImages.Count - 1 & IIf(ImageList1.ListImages.Count - 1 > 1, _
" different images.", " image.")
lbItemCount = ListView1.ListItems.Count & " files"
cmdSelect(1).Enabled = False
DOSExeIconLoaded = False
Me.MousePointer = vbDefault
End Sub
|
| Comments |
| Run the project, and click the Select Folder button.
Browse to any folder, and hit OK. The folder selected and the file type from the combo box should be returned in the DisplayName label as a
fully-qualified path and filespec. The listview should populate with all the files in the selected directory matching the selected file type,
and the Windows associated icons should appear with each file. The two labels at the bottom will detail the number of actual icons used, and the number of files listed. For executables, this generally means an icon per file. When these differ, it is probably due to the reusing of the Windows DOS icon. By right-clicking over the listview control, you can select from the popup menu. As well, the clicking the column headers will also sort the items. Note however that the numeric sorting of the file size is inaccurate; a ListView normally calls a special routine via callbacks to sort non-alpha items. This ability to use a callback is not available in VB4; VB5 owners see SendMessage: Controlling a ListView Sort Using Callbacks. |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |