Got stuck with large amounts of files

The place for threads about version 1.x of TimoSoft ExplorerTreeView.
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

I'm talking about Visual Studio 2005. C#, C++, VB.net and so on share the same IDE. I don't remember how to debug foreign processes with Visual C++ 6.0, but it is possible, too.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

If I understand the pIDL and SHITEMID structures right, I could do this:

Code: Select all

  Dim pIDL As Long, pp As Long
  Dim s%, i%
  Dim b(1024) As Byte
  Dim a$
  
  SHGetFolderLocation Me.hWnd, CSIDL_DesktopDirectory, 0&, 0&, pIDL
  If pIDL Then
     pp = pIDL
     Do
        MoveMemory s, ByVal pp, 2 'get size of pIDL
        If s Then
           MoveMemory b(0), ByVal pp + 2, s - 2
           pp = pp + s
           a$ = ""
           For i = 1 To s: a$ = a$ + Chr$(b(i)): Next
           debug.print a$
        End If
     Loop Until s = 0
  End If
  SHFree pIDL
But it prints garbage. What am I doing wrong?
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

Nothing. I get this output, which is quite normal:

Code: Select all

PàOÃ
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

Oh. Understood. Yes thats about what I get too now. Only my output before stopped at the first null char.
Is this information structure documented somewhere?
I can see where it is from unpredictable size...
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

WoF wrote:Is this information structure documented somewhere?
No. You are supposed to use the Shell API.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

Oh. I see. That's Microsoft for you. :roll: Well, you live and learn...

However, thanks again for your help and for the nice new feature in ExplorerTreeView. Nice to chat with you about shell items. ;) Maybe I am to get more into that.
Keep up the good work.
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

WoF wrote:Oh. I see. That's Microsoft for you. :roll:
Well, I think it's better to not document this structure. The Shell API is relative abstract. You use COM interfaces for almost everything. IMHO this is a good design.
Documenting the layout of a pIDL wouldn't be possible anyway, because different namespaces use different layouts. If you're writing a shell namespace extension, you can store everything you like in the pIDL. The format is up to you. Isn't this freedom great? ;)
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

Sounds crazy. How would the Shell API know about the ID format I create for my namespace extension?

Ok. Maybe I'm still to ignorant on the matter of shell namespace and shellfolder stuff, but I would expect that there are some standards e.g. how to retrieve a name string or similar from an ID in a pIDL, but I can see there are different requirements for nonFS and FS objects, so the ID format may vary.

Maybe the filename sorting problem which is still waiting in the background will bring me back to pIDLs and shell objects. :)
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

WoF wrote:Sounds crazy. How would the Shell API know about the ID format I create for my namespace extension?
It doesn't and there's no need for it to do so. When writing a shell extension, you implement the shell interfaces like IShellFolder and so on. So if a shell browser calls e. g. IShellFolder::GetDisplayNameOf to retrieve the display name of a pIDL that identifies an item within your namespace, your code is called. An API function like SHGetPathFromIDList() uses the shell interfaces internally, too.
WoF wrote:Ok. Maybe I'm still to ignorant on the matter of shell namespace and shellfolder stuff, but I would expect that there are some standards e.g. how to retrieve a name string or similar from an ID in a pIDL
There aren't. The only standard about pIDLs is, that a pIDL points to an array of SHITEMID structures, the first 2 byte of such a SHITEMID structure hold its size and the last SHITEMID structure has a size of 0. Everything else is up to the namespace implementations.
Name strings are retrieved through IShellFolder::GetDisplayNameOf. A namespace extension has to implement the IShellFolder interface for each (virtual) folder it wants to display. Of course you can write generic implementations.
WoF wrote:Maybe the filename sorting problem which is still waiting in the background will bring me back to pIDLs and shell objects. :)
File sorting is done through IShellFolder::CompareIDs.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

TiKu wrote:File sorting is done through IShellFolder::CompareIDs.
That's what intrigues me. How should a compare routine know how a pIDL is greater or less than another one, when the format of the ID is somehow unknown.
Ok. Ok. I forget there's that interface which has to return the name... so the IShellFolder::CompareIDs must somehow identify the ID to know whom to call...

But anyway I can't use this routine beause I don't have pIDLs. I only have the filenames in my ListView.
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

WoF wrote:
TiKu wrote:File sorting is done through IShellFolder::CompareIDs.
That's what intrigues me. How should a compare routine know how a pIDL is greater or less than another one, when the format of the ID is somehow unknown.
The implementation of IShellFolder, whose CompareIDs method you're calling, knows the format, because it created the pIDLs.
Each folder-like shell item implements the IShellFolder interface. To get the Desktop's IShellFolder you use the SHGetDesktopFolder API function. Then you use this IShellFolder implementation's BindToObject method to browse to other folder-like shell items. BindToObject will give you a new IShellFolder implementation - that one of the folder whose pIDL you passed.
To enumerate the content of a folder-like shell item, you call IShellFolder::EnumObjects. This will give you an IEnumIDList implementation which you use to iterate through the sub-items.
To retrieve a shell item's name, you take the parent item's IShellFolder implementation and call its GetDisplayNameOf method.
To compare two shell items, you take the parent item's IShellFolder implementation and call its CompareIDs method.
To retrieve all columns that a folder-like shell item defines for its sub-items, you query its IShellFolder implementation for an IShellFolder2 implementation (or IShellDetails as a fallback) and call this implementation's GetDetailsOf method. You can also use IShellFolder2 to retrieve the search engines this folder implements for its sub-items.

I hope now it's more clear how the shell is working
TiKu
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

Yes a little more. Seems quite a clever concept once you get deeper into it.
I halso had a look to your ExplorerClone program you kindly provided some time ago, to understand how sorting is done there.

Code: Select all

Private Sub lvwFiles_CompareItems(ByVal firstItem As ExLVwLibUCtl.IListViewItem, ByVal secondItem As ExLVwLibUCtl.IListViewItem, result As ExLVwLibUCtl.CompareResultConstants)
  Dim Flags As SHCIDSConstants
  Dim pIDLToParent1 As Long
  Dim pIDLToParent2 As Long

  pIDLToParent1 = ILFindLastID(firstItem.ItemData)
  pIDLToParent2 = ILFindLastID(secondItem.ItemData)

  Flags = SHCIDSConstants.SHCIDS_ALLFIELDS
  result = ISHFParent.CompareIDs(Flags, pIDLToParent1, pIDLToParent2)
End Sub
I undertsand, you take two items which have to be compared, retrieve there pIDLs with ILFindLastID and call their parents CompareID. Clever. But it depends on using a listview which has custom sort facility...
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: Unterföhring
Contact:

Post by TiKu »

WoF wrote:I undertsand, you take two items which have to be compared, retrieve there pIDLs with ILFindLastID
Almost. PIDLs are somewhat like paths, i. e. they usually start at the root (which is the Desktop), but can also be relative to an other IShellFolder implementation. So something like C:\Windows\system32 can be expressed as pIDL as well as Windows\system32. The only thing that can't be done is something like ..\Windows\system32.
In the ExplorerClone sample I store the item's fully qualified pIDL (i. e. starting at the Desktop) in the ItemData property. The pIDLs that you pass to IShellFolder::CompareIDs must be relative to this IShellFolder implementation. So I use ILFindLastID to retrieve the address of the last SHITEMID structure (before the terminating one which has a size of 0) within the fully qualified pIDL. The result is still a pIDL - it points to an array of SHITEMID structures and is terminated by two NULL byte.
WoF wrote:But it depends on using a listview which has custom sort facility...
Right.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
WoF
Lt. Commander
Posts: 43
Joined: 04 Aug 2005, 13:18

Post by WoF »

I see. So the last ID is that of the file itself and the parent, which in this case is a folder, provides the CompareID procedure apropriate for files.
I'm afraid the chances for me to make use of this intelligent sorting are remote.
I remember there were a couple of problems which made it quite improbable for me to use your ExplorerListView...
Post Reply