Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Windows Explorer Mimic 4

Status
Not open for further replies.

fischadler

Programmer
May 31, 2002
258
0
0
MT
Hello folks,
I was trying to find a control that mimics the Windows Explorer (something like a suped up version FileListBox with file type icons and details etc). Having failed to find any, I resorted to write my own code using the ListView Control.
I managed to get the icon that windows explorer would display for each file type to be shown in a picturebox but I can't get it to an ImageList control so that it can be used by the ListView control. I am getting an error 481 "invalid picture" on the line that adds pictures to the ImageList (see code).
Is there some other way to do it? The code below uses SHGetFileInfo and ImageList_Draw APIs to get the file icon inside the picturebox.

Thanks!


Code:
Private Const MAX_PATH = 260
Private Const SHGFI_DISPLAYNAME = &H200         ' get display name
Private Const SHGFI_EXETYPE = &H2000           ' return exe type
Private Const SHGFI_LARGEICON = &H0           ' get large icon
Private Const SHGFI_SHELLICONSIZE = &H4         ' get shell size icon
Private Const SHGFI_SMALLICON = &H1           ' get small icon
Private Const SHGFI_SYSICONINDEX = &H4000        ' get system icondex
Private Const SHGFI_TYPENAME = &H400           ' get type name
Private Const ILD_BLEND50 = &H4
Private Const ILD_BLEND25 = &H2
Private Const ILD_TRANSPARENT = &H1
Private Const CLR_NONE = &HFFFFFFFF
Private Const CLR_DEFAULT = &HFF000000
Private Type SHFILEINFO
    hIcon As Long           ' : icon
    iIcon As Long     ' : icondex
    dwAttributes As Long        ' : SFGAO_ flags
    szDisplayName As String * MAX_PATH ' : display name (or path)
    szTypeName As String * 80     ' : type name
End Type
Private Declare Function SHGetFileInfo Lib "shell32.dll" Alias "SHGetFileInfoA" (ByVal pszPath As String, ByVal dwFileAttributes As Long, psfi As SHFILEINFO, ByVal cbFileInfo As Long, ByVal uFlags As Long) As Long
Private Declare Function ImageList_Draw Lib "comctl32.dll" (ByVal himl As Long, ByVal i As Long, ByVal hdcDst As Long, ByVal x As Long, ByVal y As Long, ByVal fStyle As Long) As Long
Private Declare Function ImageList_DrawEx Lib "comctl32.dll" (ByVal himl As Long, ByVal i As Long, ByVal hdcDst As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal rgbBk As Long, ByVal rgbFg As Long, ByVal fStyle As Long) As Long

Private Sub Form_Load()
    Dim hImage As Long, udtFI As SHFILEINFO
    'get the handle of the system image list that contains the large icon images
    hImage = SHGetFileInfo("c:\myfile.txt", ByVal 0&, udtFI, Len(udtFI), SHGFI_SYSICONINDEX Or SHGFI_LARGEICON)
    
    Picture1.AutoRedraw = True
    ImageList_Draw hImage, udtFI.iIcon, Picture1.hDC, 0, 0, ILD_TRANSPARENT
    
    ImageList1.ListImages.Add 1, "fileico", Picture1.Picture
End Sub


-Fischadler
 
What's the utimate aim of having this file explorer.. if its opening or saving a file, have you considered the "GetOpenFileNameA" api?

Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Boolean

------------------------
Hit any User to continue
 
I need to make a simple FTP client that lets me choose multiple files for upload.

-Fischadler
 
Instead of adding Picture1.Picture, try adding Picture1.Image.

[tt]ImageList1.ListImages.Add 1, "fileico", Picture1.Image[/tt]

Besides this, there are other ways too, to do this thing in more efficient way.

Instead of drawing the file icon to a picture box, and adding that image to your imagelist, you can associate your listview to system image list and use the system icons directly, without having an imagelist on your form.

See the following code...

Add Microsoft Windows Common Controls 5.0 to your controls toolbox, and add a place a listview control on your form. Try running this code.
___
[tt]
Option Explicit
Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
Const HKEY_CLASSES_ROOT = &H80000000

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
Const LVM_FIRST = &H1000
Const LVM_SETIMAGELIST = (LVM_FIRST + 3)
Const LVM_SETITEM = (LVM_FIRST + 6)
Const LVSIL_SMALL = 1
Const LVIF_IMAGE = &H2
Private Type LV_ITEM
mask As Long
iItem As Long
iSubItem As Long
State As Long
StateMask As Long
lpszText As Long
cchTextMax As Long
iImage As Long
lParam As Long
End Type


Private Declare Function SHGetFileInfo Lib "shell32" Alias "SHGetFileInfoA" (ByVal pszPath As String, ByVal dwFileAttributes As Long, psfi As SHFILEINFO, ByVal cbFileInfo As Long, ByVal uFlags As Long) As Long
Const SHGFI_SYSICONINDEX = &H4000
Const SHGFI_SMALLICON = &H1
Const MAX_PATH = 260
Const FILE_ATTRIBUTE_NORMAL = &H80
Const SHGFI_USEFILEATTRIBUTES = &H10
Const SHGFI_TYPENAME = &H400
Private Type SHFILEINFO
hIcon As Long
iIcon As Long
dwAttributes As Long
szDisplayName As String * MAX_PATH
szTypeName As String * 80
End Type
Private Sub Form_Load()
Dim sfi As SHFILEINFO, lvi As LV_ITEM
'set view and add columns
ListView1.View = lvwReport
ListView1.ColumnHeaders.Add , , "Extension", 600
ListView1.ColumnHeaders.Add , , "Description", 3000
'associate the system image list (small icons) to the list view
SendMessage ListView1.hWnd, LVM_SETIMAGELIST, LVSIL_SMALL, ByVal _
SHGetFileInfo("C:\", 0, sfi, Len(sfi), SHGFI_SYSICONINDEX Or SHGFI_SMALLICON)
Dim Index As Long, sName As String * 1000
lvi.mask = LVIF_IMAGE
'enumerate all file extensions from registry
While RegEnumKeyEx(HKEY_CLASSES_ROOT, Index, sName, Len(sName), ByVal 0, vbNullString, ByVal 0, ByVal 0&) = 0
If Asc(sName) = 46 Then
'retrieve icon index and type description
SHGetFileInfo sName, FILE_ATTRIBUTE_NORMAL, sfi, Len(sfi), SHGFI_USEFILEATTRIBUTES Or SHGFI_SMALLICON Or SHGFI_SYSICONINDEX Or SHGFI_TYPENAME
'add the item (and subitem) to the listview
ListView1.ListItems.Add(, , sName).SubItems(1) = sfi.szTypeName
'set the icon index of the listitem
lvi.iImage = sfi.iIcon
lvi.iItem = ListView1.ListItems.Count - 1
SendMessage ListView1.hWnd, LVM_SETITEM, 0, lvi
End If
Index = Index + 1
Wend
End Sub
Private Sub Form_Resize()
ListView1.Move 0, 0, ScaleWidth, ScaleHeight
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Disassociate the listview from the system imagelist.
'this MUST be done on Win98 otherwise the system listimage crashes.
'and all icons in the shell are gone!.
'WinXP/2K does not require this.
SendMessage ListView1.hWnd, LVM_SETIMAGELIST, LVSIL_SMALL, ByVal 0&
End Sub[/tt]
___

See also VB Explorer.
 
Thanks Hypetia!
The code was very informative and I also learned about about a few new commands! All I need to do now is adapt this code to show the contents of a folder.

Thanks again!

-Fischadler
 
>find a control that mimics the Windows Explorer

Why not use Windows Explorer itself?

A key word search against ... um ... "Josh" and "folder" and "view" should find some stuff from me posted in January on how to do this (spread over several different threads, though). At a bare minimum you can get a fully-fledged Windows Explorer embedded in your app in about 4 lines of code ...
 
Cool! It didn't even cross my mind I could use the web browser control to display the contents of a local folder. That saves a lot of work!
Reading through Strongm's previous post to Josh, I noticed Josh had enquired about removing that blue XP folder options box on the left, or, even better for me, replace it with a folders list. Is there some way to do it?
Also, how do I get a list of the files that the user has selected?

-Fischadler
 
>That saves a lot of work!

Quite so

As to the other points you raise, I'll try to answer them when I'm near a PC ...
 
>list of files

ShellFolderView's SelectedItems collection ...
 
>removing that blue XP folder options box on the left

Sadly, removing it is done by a global Windows Explorer setting (Tools/Folder Options/General/Tasks) - and I don't at the moment have a way of setting this via code

>or, even better for me, replace it with a folders list

Now this should be easy, using the ShowBrowserBar method. Unfortunately, ShowBrowserBar seems terminally broken (at least from VB) ...
 
strongm said:
A key word search against ... um ... "Josh" and "folder" and "view"

LOL - just read this thread... ;-)

For a folder list look here:
(*Note: I have to turn off the reference for "Debug Object for AddressOf Subclassing")

Or here:

As far as the blue box... No luck so far...
(If you can get the window down to a certain size, it will disappear...)

Good Luck,
-Josh

Visit My Site
PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Hello Strongm and Cube101,
The real reason I needed to remove the folder options box was because I thought that by removing it I would solve the problem I am having right now about the fact that when I double click a folder, it's contents are displayed in a new window rather than in the same control in my VB app. I managed to remove the band using Folder Options approach but this did not help. In Windows Explorer, when I open a folder using "Explore" rather than "Open" (Win XP) subsequent folders are opened in the same window. This does not happen when the folder options blue band is visible. Perhaps there is a simpler solution I am overlooking. Also the amount of space the band eats from the control is kind of wasted.

I will search in Google about ShellFolderView since I am very unfamiliar with how to use it.

Thanks again!

-Fischadler
 
O...K...

I did a little registry hacking and found the Key to turn off the Task Pane...
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\WebView
0 = Classic View (No Blue Bar)
1 = Common TaskBar (Blue Bar)

The idea I had was this:
Using a Directory Box (Dir1)
And a Web Browser control (WebBrowser1)
Code:
[i][b]'Registry Key Path[/b][/i]
Private Const TASKKEY = "[b][COLOR=blue]HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\WebView[/color][/b]"
[i][b]'Value retainer variable, to reset the key when done...[/b][/i]
Private OldKeyVal As String

Private Sub Dir1_Change()
  [i][b]'Navigate to the folder[/b][/i]
  WebBrowser1.Navigate Dir1.Path
End Sub

Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean)
  With CreateObject("WScript.Shell")
    [i][b]'Get current value of Key[/b][/i]
    OldKeyVal = .RegRead(TASKKEY)
    [i][b]'Set New value (OFF)[/b][/i]
    .RegWrite TASKKEY, "0"
  End With
End Sub

Private Sub WebBrowser1_NavigateComplete2(ByVal pDisp As Object, URL As Variant)
  With CreateObject("WScript.Shell")
    [i][b]'Reset value of Key (Comment out for testing)[/b][/i]
    .RegWrite TASKKEY, OldKeyVal
  End With
End Sub

This did not quite work as desired...

You have to right click and refresh to hide the task pane before the Value is reset...

I tried placing both .Refresh & .Refresh2 before the code to reset the value, but with no luck...

However, you can comment out the reset code and run it, and manually Right Click>Refresh to see that the key does do the trick, implenting it is the problem now...

PLEASE POST BACK if you figure this out...

Thanks,
Josh S

Visit My Site
PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
OK. I'll check it out and let you know but it might take some time.

Thanks though!!

-Fischadler
 
CubeE101,
I tried your code and I encountered the same problem. However, once someone refreshes the screen manually, then the setting starts taking effect on every sub sequent running of the app. I will make some more research about it and let you know if I find something useful.

P.S. I still get the folders to open in a new window. Would love to find a way to force them to open in the same browser control.

-Fischadler
 
That is a windows setting too...

Tools
>Folder Options
>General
>Browser Folders
>Open each folder in the same window

(It is the frame right under the Common Task Bar option)

Not sure where it is kept in the registry, or how to set it programmatically...

Visit My Site
PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Windows was set up that way all the time (I wouldn't want it any other way).
Still it opens in a new window. [sad]

-Fischadler
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top