| ||
|
To see the Favorites 1 Demo click TreeView Control.
For a simpler ListView click ListView Demo. | ||
|
This is the second in the series on Internet Explorer Favorites. The first demonstrated how to load all the favorite folders in a TreeView. This demo takes the next step and displays the Favorites in a ListView Control.
Although shown here as a demo, the compiled project can actually be useful. The reason for developing this program was to rapidly place URL's in the Clipboard. You will find if you click on a Tree Node or a ListView ListItem you will see that the item text is placed in the Textbox. The text is also copied to the clipboard. This is valuable as a speedy way to get your Favorite URL's. If after you compile it, you drag the EXE icon from Windows Explorer to the Desktop or QuickLaunch ToolBar you will have rather fast way of placing a URL in the ClipBoard. | ||
|
If you watch when you first start the program, it takes a while before your favorite folder Tree and ListView favorites are displayed. This is because a recursive directory search is made to find every folder and every favorite.URL file must be opened and read until the URL is found.
Since this takes such a long time, this program is designed to automatically save all this information in a separate .ini file in the App.Path. Subsequently when you load this program the information will appear almost instantly from the .ini file. If you have updated your favorites in IExplorer you can force a new search by clicking "Refresh" which will automatically overwrite the .ini file with the new search info. Now you know one of the reasons it takes a while for IExplorer to load before you can run it. | ||
|
You may have noticed that some URL's you have seen have the %20 packed in them instead of spaces. This protects against the URL string being delimited (ended) at the space. To accomodate this quirk, the %20 has been saved to the .ini file. Although the %20 in not displayed in the textbox if you click on an URL, it is placed in the ClipBoard. | ||
| ||
| To find the TreeView Control click on the VB Menu->Project->Components and select Microsoft Windows Common Controls 6. After you click OK the TreeView Control (and some others) will appear in the toolbar usually on the left of the VB IDE (Integrated Development Environment). | ||
| ||
Option Explicit
'===========================================================
' Declarations for the file searching operations
'===========================================================
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * 260
cAlternate As String * 14
End Type
Private Declare Function FindFirstFile _
Lib "kernel32" Alias "FindFirstFileA" ( _
ByVal lpFileName As String, _
lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile _
Lib "kernel32" Alias "FindNextFileA" ( _
ByVal hFindFile As Long, _
lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" _
(ByVal hFindFile As Long) As Long
'===========================================================
' Declarations for Clicking ListView SubItems
'===========================================================
Private Type lvwMsgInfo
x As Long
y As Long
Flgs As Long
Itm As Long
SubItm As Long
End Type
Private Declare Function SendMessage _
Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal lMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Dim lvwMsg As lvwMsgInfo
'===========================================================
' Declarations to Store the Favorites in Memory
'===========================================================
Const DIMINCR = 32
Private Type favType
Key As String
Name As String
URL As String
End Type
Dim fav() As favType
Dim favCnt%, dimCntr%, iniFile$
'===========================================================
' Procedures for Finding Favorite Folders and URL files
'===========================================================
'The Recursive Procedure to find all favorite folders
' and favorite URL's (files)
Private Sub GetFavorites(ByVal oldPath$, ByVal newFolder$, _
Optional start As Boolean)
Dim fFirst&, fNext&, found$, curPath$
Dim w As WIN32_FIND_DATA
curPath = AddSlash(oldPath) & newFolder
'Add the folder as a node
If start Then
'Needed for the first node only
TreeView1.Nodes.Add , , curPath, newFolder
Else
'Subsequent nodes
TreeView1.Nodes.Add oldPath, tvwChild, _
curPath, newFolder
End If
DoEvents
'Now search the folder
fFirst = FindFirstFile(AddSlash(curPath) & "*", w)
If fFirst = 0 Then Exit Sub 'Empty folder
Do
found = TrimNull(w.cFileName)
If w.dwFileAttributes And _
FILE_ATTRIBUTE_DIRECTORY Then
If found <> "." And found <> ".." Then
'A folder is found so call this Sub
' recursively to add the node
GetFavorites curPath, found
End If
Else
If Len(found) > 4 Then
If LCase$(Right$(found, 4)) = ".url" Then
'A favorite (file) is found
found = Left$(found, Len(found) - 4)
AddFavorite curPath, found
End If
End If
End If
DoEvents
fNext = FindNextFile(fFirst, w)
Loop While fNext
fNext = FindClose(fFirst)
End Sub
Private Sub AddFavorite(favKey$, favName$, Optional favURL$)
favCnt = favCnt + 1
If favCnt >= dimCntr Then
dimCntr = dimCntr + DIMINCR
ReDim Preserve fav(dimCntr)
End If
fav(favCnt).Key = favKey
fav(favCnt).Name = favName
fav(favCnt).URL = favURL
If favURL = "" Then
'The URL is not supplied so
' open the file and get it
fav(favCnt).URL = getURL(AddSlash(favKey) & favName)
End If
End Sub
'===========================================================
' The typical contents of a favorite file follows:
' (stored in the C:\Windows\Favorites directory)
'===========================================================
' [Default]
' BASEURL=http://www.yahoo.com/
'
' [InternetShortcut]
' URL=http://www.yahoo.com/
' Modified=807340260326C10144
'===========================================================
Private Function getURL(fPath$)
Dim j%, f%, s$, t$
Dim gotHeader As Boolean
'First open the URL file
f = FreeFile
Open fPath & ".url" For Input As f
Do Until EOF(f)
Line Input #f, s
s = MyTrim(s)
t = LCase$(s)
If InStr(t, "netshortcut") Then gotHeader = True
'Line Input until the [InternetShortcut] section
If gotHeader Then
'See if the specifier is in the string
j = InStr(t, "url=")
If j Then
'If it is then get the portion
' after the specifier
j = Len(s) - j
If j > 3 Then
s = Right$(s, j - 3)
Else
s = ""
End If
Exit Do
End If
End If
Loop
Close f
getURL = s
End Function
'===========================================================
' Clicking Events
'===========================================================
Private Sub Command1_Click()
Static working
'Do not allow click while loading
If working Then Exit Sub
working = True
'Initialize memory storage of favorites
favCnt = 0
dimCntr = 0
Erase fav
TreeView1.Nodes.Clear
'Do the work
GetFavorites "C:\Windows\", "Favorites", True
ShowMyFolder
SaveINIFavorites
working = False
End Sub
' Interestingly ListView does not have a built in way
' to tell if a subitem has been clicked. This sub does it.
'
' Also, if you click the first column slightly off the text
' (to the right) no click event happens unless you use set
' the ListView.FullRowSelect = True
Private Sub ListView1_MouseDown(Button As Integer, _
Shift As Integer, x As Single, y As Single)
lvwMsg.x = x / Screen.TwipsPerPixelX
lvwMsg.y = y / Screen.TwipsPerPixelY
SendMessage ListView1.hwnd, 4153, 0, lvwMsg
If lvwMsg.Flgs And 14 Then
ShowLabel lvwMsg.Itm + 1, lvwMsg.SubItm
End If
End Sub
' Inconveniently:
' There is no .SubItem(0) allowed so there is always extra
' code for the first Item that is not a SubItem.
'
' Additionally:
' A key field is assigned to the ListItem so that the
' fav().URL could be retrieved (remember the "%20" in the
' string is shown as a space). To put the data with the %20
' into the ClipBoard (mentioned in the opening comments),
' ListItems(i).Key holds the pointer to the fav() array for
' the item displayed.
'
' Interestingly, the Key is a string and will not accept a
' number, so an "L" is concatenated in front of the
' CStr(number) when adding (see Sub ShowInListView) -
' thus requiring the Right$ function here.
Private Sub ShowLabel(ByVal i%, ByVal s%)
Clipboard.Clear
With ListView1.ListItems(i)
Select Case s
Case 0
Text1 = .Text
Dim j%
j = CInt(Right$(.Key, Len(.Key) - 1))
Clipboard.SetText fav(j).URL
Case 1
Text1 = .SubItems(s)
Clipboard.SetText Text1
End Select
End With
End Sub
'Clicking on a TreeView item
Private Sub TreeView1_NodeClick( _
ByVal Node As MSComctlLib.Node)
'Populate the ListView
ShowInListView Node.Key
'Places TreeView item in TextBox & ClipBoard
Text1 = Node.Key
Clipboard.SetText Text1
End Sub
'Populate the ListView from the fav() array
Private Sub ShowInListView(ky$)
Dim j%, l As ListItem
With ListView1
.ListItems.Clear
'Run through the whole fav() array and look for
' the saved string that matches this node's .Key
For j = 1 To favCnt
If fav(j).Key = ky Then
'Show the URL
Set l = .ListItems.Add(, "L" & CStr(j), _
Replace(fav(j).URL, "%20", " "))
'Show the Name (fav name = file name)
l.SubItems(1) = fav(j).Name
End If
Next
End With
End Sub
'===========================================================
' General String Handling Procedures
'===========================================================
Private Function AddSlash$(ByVal s$)
If Len(s) Then
If Right$(s, 1) <> "\" Then s = s & "\"
End If
AddSlash = s
End Function
Private Function TrimNull$(ByVal s$)
Dim pos As Integer
pos = InStr(s, Chr$(0))
If pos Then s = Left$(s, pos - 1)
TrimNull = s
End Function
'The intrinsic Trim$ Function does NOT strip all
' Chars <= Asc(32) - so I wrote my own
Private Function MyTrim$(ByVal s$)
Dim j&, k&, l&
l = Len(s)
For j = 1 To l
If Asc(Mid$(s, j, 1)) > 32 Then Exit For
Next
For k = l To 1 Step -1
If Asc(Mid$(s, k, 1)) > 32 Then Exit For
Next
s = IIf(k > j, Mid$(s, j, k - j + 1), "")
MyTrim = s
End Function
'===========================================================
' Procedures to Save and Load the Nodes and ListItems
'===========================================================
Private Sub LoadINIFavorites()
Dim j%, f%, nd%
Dim favName$, favKey$, favURL$
Dim ndKey$, ndParent$, ndText$
f = FreeFile
Open iniFile For Input As f
'First get the number of nodes
Input #f, nd
'Next get the first node - special case
' because it does not have a parent
Input #f, ndParent, ndKey, ndText
TreeView1.Nodes.Add , , ndKey, ndText
'Get the rest of the nodes
For j = 2 To nd
Input #f, ndParent, ndKey, ndText
TreeView1.Nodes.Add ndParent, tvwChild, ndKey, ndText
Next
'Get the favorites
Do Until EOF(f)
Input #f, favKey, favName, favURL
AddFavorite favKey, favName, favURL
Loop
Close f
End Sub
Private Sub SaveINIFavorites()
Dim j%, f%, favName$, favKey$, favURL$, tmp$
f = FreeFile
Open iniFile For Output As f
'First save the number of nodes so we know
' how many to retrieve in LoadINIFavorites
Write #f, TreeView1.Nodes.Count
'Save the nodes (favorite folders)
For j = 1 To TreeView1.Nodes.Count
If j = 1 Then
'The first node does not have a parent
tmp = "first"
Else
tmp = TreeView1.Nodes(j).Parent.Key
End If
Write #f, tmp, TreeView1.Nodes(j).Key, _
TreeView1.Nodes(j).Text
Next
'Save the favorites
For j = 1 To favCnt
Write #f, fav(j).Key, fav(j).Name, fav(j).URL
Next
Close f
End Sub
'===========================================================
' Form Initialization
'===========================================================
Private Sub Form_Load()
'Size and place the controls
Move 1000, 1000, 9400, 4800
Caption = "Internet Explorer Favorites"
TreeView1.Move 120, 120, 2300, 3400
ListView1.Move 2480, 120, 6700, 3400
Command1.Move 500, 3700, 1200, 375
Command1.Caption = "Refresh"
Text1.Move 2480, 3700, 6700, 375
Text1 = ""
'Add the ListView Columns
With ListView1.ColumnHeaders
.Add , , "Favorite URL", 3500
.Add , , "Favorite Name", 3100
End With
iniFile = AddSlash(App.Path) & App.EXEName & ".ini"
'Check if the .ini file exists
If Dir$(iniFile) = "" Then
'No - do the recursive search
Command1_Click
Else
'Yes - load from the .ini file
LoadINIFavorites
ShowMyFolder
End If
End Sub
'Expand the TreeView for the favorite folder specified
' and populate the ListView for that folder's favorites
Private Sub ShowMyFolder()
Dim j%, mf$
'Note: You can specify the folder as
' a command line parameter
mf = Command$
If mf = "" Then
'***********************************************************
' Edit here for the Folder you want Automatically Opened
' perhaps like: mf = "C:\Windows\Favorites\Channels"
'
mf = "C:\Windows\Favorites"
'***********************************************************
End If
mf = LCase$(mf)
'Search for the node specified
For j = 1 To TreeView1.Nodes.Count
If mf = LCase$(TreeView1.Nodes(j).Key) Then
Exit For
End If
Next
'Exit if node is not found (nothing is expanded)
If j > TreeView1.Nodes.Count Then Exit Sub
With TreeView1.Nodes(j)
.Expanded = True
.EnsureVisible
.Selected = True
Text1 = .Key
Clipboard.SetText Text1
ShowInListView .Key
End With
End Sub
|