I'm looking for some help or pointers here. I want to put the functionality
of BrowseFolderDialog in a non-modal treeview, a la the left side of Windows Explorer. From reading MSDN, it seems like IShellFolder is where to, in proper parlance, navigate the shell namespace. From MSDN, "The simplest way to start is to have your application call SHGetDesktopFolder to retrieve the desktop's IShellFolder interface. Then, to navigate downward through the namespace, your application can follow these steps: 1. Enumerate the folder's contents. 2. Determine which objects are subfolders, and select one. 3. Bind to the subfolder to retrieve its IShellFolder interface. Repeat these steps as often as necessary to reach the target." Per a 2/29/99 post by Blair, evaluating "pDesktopFolder := ShellLibrary default getDesktopFolder" returns an IShellFolder instance. This instance represents the namespace root, the desktop. Proceding with #1 just above, again from MSDN, "Enumerating the Contents of a Folder: The first thing you usually want to do with a folder is to find out what it contains. You must first call the folder's IShellFolder::EnumObjects method. The folder will create a standard OLE enumeration object and return its IEnumIDList interface. This interface exposes four standard methods-Clone, Next, Reset, and Skip-that can be used to enumerate the contents of the folder. The basic procedure for enumerating a folder's contents is: 1. Call the folders IShellFolder::EnumObjects method to retrieve a pointer to an enumeration object's IEnumIDList interface. 2. Pass an unallocated PIDL to IEnumIDList::Next. Next takes care of allocating the PIDL, but the application must deallocate it when it is no longer needed. When Next returns, the PIDL will contain just the object's item ID and the terminating NULLs. In other words, it is a single-level PIDL, relative to the folder, not a fully-qualified PIDL. 3. Repeat step 2 until Next returns S_FALSE to indicate that all items have been enumerated. 4. Call IEnumIDList::Release to release the enumeration object." I see that IShellFolder has a method #EnumObjects:grfFlags:ppenumIDList:, but how to use it, I don't know. It looks like the first parameter (a Windows handle) can be nil, and the flags parameter can be some number (0,1,2, etc -- I don't have the actual enumeration constants definitions), but the third parameter, ppenumIDList, an "address that receives a pointer to the IEnumIDList interface of the enumeration object created by this method", egads. I see that class IENumXXX responds to #clone, #next, #reset and #skip, so I figured there's some sort of connection between that and the IEnumIDList interface. I'm basically spinning my wheels at this point. Has anyone implemented this functionality? If not, any pointers on how to proceed would be greatly appreciated. -- Louis |
Louis,
> I see that IShellFolder has a method #EnumObjects:grfFlags:ppenumIDList:, > but how to use it, I don't know. It looks like the first parameter (a > Windows handle) can be nil, and the flags parameter can be some number > (0,1,2, etc -- I don't have the actual enumeration constants definitions), > but the third parameter, ppenumIDList, an "address that receives a pointer > to the IEnumIDList interface of the enumeration object created by this > method", egads. I see that class IENumXXX responds to #clone, #next, #reset > and #skip, so I figured there's some sort of connection between that and the > IEnumIDList interface. > > I'm basically spinning my wheels at this point. Has anyone implemented this > functionality? If not, any pointers on how to proceed would be greatly > appreciated. Start with Dolphin's EnumRECT sample, which appears to be installed under the Samples directory in 4.0. Look at that, and you'll know more than I do :) Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill,
> Start with Dolphin's EnumRECT sample, which appears to be installed under > the Samples directory in 4.0. Look at that, and you'll know more than I do > :) Thanks for the pointer. I looked at it -- Isn't that about creating COM servers? ... as opposed to using an existing COM server (IShellFolder interface). (Hmm, like I know what I'm talking about.) I'll be posting something soon along another path I'm trying to tread. -- Louis |
In reply to this post by Louis Sumberg-2
As a followup to my last post on navigating the Shell namespace, I didn't
get far, but here's what I have in a workspace: "Return an IShellFolder instance that points to the desktop folder." pDesktopFolder := ShellLibrary default getDesktopFolder. "Allocate a pointer to external memory for the 'enumeration object'." enumAddress := WindowsShellMemory new. "Set flags for the enumeration." grfFlags := 32 | 64 | 128. "folders, includeHidden, nonFolders" "Set enumAddress to, per MSDN, 'Address that receives a pointer to the IEnumIDList interface of the enumeration object created by this method [IShellFolder::EnumObjects]'. Answer 0 if successful." result := pDesktopFolder EnumObjects: nil grfFlags: grfFlags ppenumIDList: enumAddress. "Return an IEnumIDList instance based on enumAddress." iEnumIDList := IEnumIDList fromAddress: enumAddress. "Start enumerating folders. Return an instance of ITEMIDLIST." itemIDList := iEnumIDList nextAvailable. "Create STRRET structure to hold folder's display name." strret := STRRET new uType: 2. "uType = 2 means return string in STRRET cStr" "Get display name." pDesktopFolder GetDisplayNameOf: itemIDList uFlags: 1 lpName: strret. The last line returns a walkback with "The parameter is incorrect" which makes some sense, considering lpvoids are expected for the first and third parameters. I tried passing them in with asParameter and then with yourAddress but got the same walkback. Some more info: I found a type library on the Net (from the CCRP project) and used that to generate the classes for IEnumIDList, ITEMIDLIST, STRRET, and SHITEMID (just don't try to say that last one out loud). The package with these classes is at http://www.mindspring.com/~lsumberg/Dolphin/LasShellAddons.pac. Methods I added (in the package) are: IEnumIDList class>>elementClass, which returns ITEMIDLIST. IEnumIDList>>newElement, which returns ITEMIDLIST new: 264. I know this is hokey, but without ": 264" I get a walkback "Invalid access to memory location. Reading ..." At least this kept me alive for another line or two of code. IEnumIDList>>nextAvailable, which I just copied from IEnumXXX. ITEMIDLIST>>new, which returns a pointer. Bottom line is the wheels are still spinning but I'm stumped, in this just and noble cause. -- Louis |
I tried "translating" some C examples (in MSDN and on the Net) into Dolphin.
One is at http://www.mindspring.com/~lsumberg/Dolphin/EnumerateFolders1.rtf. I copied the MSDN text into a workspace and then constructed the Dolphin equivalent, interspersed between the C code. The rtf file can be opened in a workspace and the code viewed and evaluated there. The C code is all in red. The Dolphin code and comments are in the familiar black, blue and green. The class definition for IEnumIDList, is at http://www.mindspring.com/~lsumberg/Dolphin/IEnumIDList.cls. This is a plain vanilla wrapper (around the COM interface IEnumIDList) that was generated from a typelib. I'm not sure what my question is, other than "How come it doesn't work?" It could be a case of Pointer Disorder Syndrome. The comments sort of indicate what I think is going on and show where it bombs. This time around I just used the structures (i.e., IEnumIDList in this example) generated by Dolphin through the typelib. I was hoping that using WindowsShellMemory as a pointer would be sufficient, used in combination with other Windows methods that would extract the "real" values. I suspect that the first few lines are ok, but that ppenum, isn't really doing the trick. I'm hoping that someone who knows C and COM can take a look and help here. Thanks in advance. -- Louis |
Free forum by Nabble | Edit this page |