New
#1
Can I access them like regular folders in .NET? (in the System.IO directive)
More...This is the fifth post about Windows 7 Libraries. By now, you should be familiar with Windows 7 Libraries (Understanding Windows 7 Libraries) and understand the internal structure of Libraries and how they integrate into the Windows Shell (Libraries Under the Hood). In the previous post, we explained the different programming models and ways to work with Windows 7 Libraries. In this post, we focus on the Windows Shell Programming model that you can use to access libraries even without using the latest IShellLibrray APIs.
In the previous post, we talked about the importance of using the right version of the Common File Dialog (CFD) to enable the complete Libraries user experience in Windows 7. In this post we will further explorer the opportunities to let users select and consume Libraries as if they where regular folders. Let’s imagine the case of a slideshow application that presents users' pictures. By using the Pictures Library, users are essentially telling the system that their important pictures are stored in the Pictures Library, and therefore, our slideshow application can simply be pointed directly to the Pictures Library and show the users' entire pictures collections. Furthermore, from developers’ point of view, using the Libraries system can eliminate the need to maintain a separate configuration file or database, since developers can rely on the Libraries System. But before we dive into the Shell Libraries programming APIs, we need to understand the few concepts regarding the Shell Programming Model.
Shell Programming Model
- IShellItem, commonly referred to as an item, is the currency of the Shell UI model and its programming model. Items are individual, self-contained content sources. Take for example the above-mentioned Common File Dialogs. Quite few of the interface methods used for controlling the file dialogs use Shell items to refer to folders instead of file system paths. This is important because the CFD can communicate information about both file system folders and other virtual folders that you find in the shell, such as the Control Panel or the Computer folder.
- IShellFolder interface represents shell folder objects from the shell namespace. Using IShellFolder you can traverse through the contents of a folder, to retrieve the display name of an item in a folder, parse a display name relative to the folder, and obtain an item ID list.
- IShellLink interface represents a link, usually to a file, folder, or an executable.
- IPropertyStore interface can be used to manage the property store associated with various shell objects.
- IShellLibrary interface represents a Windows 7 Library, which we will cover in depth in future posts.
Now that we have defined the different players in the Shell Programming Model, we can see how Libraries fit into this model. Since Libraries are not file system locations, you cannot use file system-specific APIs. Therefore, you have two main options to consume library contents - the Shell Programming Model and the new IShellLibrary API.
Using the Shell Programming Model
You can use the IShellItem and IShellFolder interfaces and a bunch of helper functions to enumerate the contents of Libraries just as if they were regular folders. This means that applications can consume Libraries contents without using the new Libraries API and with very little change to their existing code.
The following code snippet shows how to use the IShellFolder interface to enumerate through the entire contents of the Picture library.
IShellItem *psi;
HRESULT hr = SHGetKnownFolderItem(
FOLDERID_PicturesLibrary,
KF_FLAG_CREATE,
NULL,
IID_PPV_ARGS(&psi));
if(SUCCEEDED(hr))
{
IShellFolder *psf;
hr = psi->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&psf));
if(SUCCEEDED(hr))
{
IEnumIDList *penumIDList;
psf->EnumObjects(NULL, SHCONTF_FOLDERS, IID_PPV_ARGS(&penumIDList));
//use penumIDList to enumarte the content of the folder
}
}
Here you can see that by using the helper function SHGetKnownFolderItem, we can retrieve the correct library location by passing the FOLDERID_PicturesLibrary, which is a GUID representing the known folder, in our case the Picture Library. A successful call will fill the IShellItem *psi with the correct information about the Library represented as a Shell Item. From this point the rest of the code is standard Windows Shell programming, where we use the BindToHandler to bind the previously obtained Shell Item to a Shell folder. Next, we enumerate through the different items in the Shell folder, which in case of a library can be either files or folders. The SHGetKnownFolderItem is a Shell Helper function and is part of a larger group of helper functions that can be found in the shlobj.h header file in the Windows 7 RC SDK.
Using the New IShellLibrary API
You can achieve the same functionality as the code above by using the new Windows 7 IShellLibrary API as shown by the next code snippet.
IShellLibrary *pslLibrary;
HRESULT hr = SHLoadLibraryFromKnownFolder(
FOLDERID_PicturesLibrary,
STGM_READ,
IID_PPV_ARGS(&pslLibrary));
if(SUCCEEDED(hr))
{
IShellItemArray *psiaFolders;
hr = pslLibrary->GetFolders(
LFF_STORAGEITEMS,
IID_PPV_ARGS(&psiaFolders));
IEnumShellItems *penumShellItems;
psiaFolders->EnumItems(&penumShellItems);
//work with penumShellItem to enumerate the items in the library
}
Here you can see that we used another helper function SHLoadLibraryFromKnownFolder to create the IShellLibrary object from which we can call the GetFolders method to return an IShellItemArray that later is used to obtain an enumerator to traverse through the entire library contents.
In the next post we will focus more on the IShellLibrary API.
Can I access them like regular folders in .NET? (in the System.IO directive)