Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Creating and Using the System Folder View Object

software


Creating and Using the System Folder View Object

Author: EdwardS

Creating and Using the System Folder View Object 



Overview

About the FolderViewImpl Sample

Getting Started - Implementing IShellFolder Methods 

IShellFolder::CreateViewObject

IShellFolder2::GetDetailsOf & GetDefaultColumnState 

IShellFolder2::MapColumnToSCID

IShellFolder2::GetDetailsEx

IShellFolder::CompareIDs

Context Menus and Categories

Item Menu

Background Context Menu

Categories

ICategoryProvider

ICategorizer

Overview


When fully implem 636j91g enting a Shell namespace extension, a developer must implement the IShellView interface. However, Microsoft® Windows® provides a default implementation of IShellView known as the System Folder View Object (colloquially known as DefView), that can be used in place of a custom implementation. This is the same view object used by Windows Explorer to display the details of an item. The System Folder View Object is a wrapper around standard list view functionality, providing integration with a Shell namespace extension as demonstrated in the FolderViewImpl sample.

While the System Folder View Object can also be hosted in dialogs, the scope of this document is limited to creating and using it within Windows Explorer.

It is assumed that the reader is already familiar with basic Shell namespace programming. This document attempts to address all of the necessary steps to use the System Folder View Object in a Shell namespace.

About the FolderViewImpl Sample

One purpose of the FolderViewImpl sample, which is a full implementation of a Shell namespace extension, is to demonstrate the interactions between the System Folder View Object and a Shell namespace extension. It does not represent any real data! All of the complications of accessing real data have been bypassed in an effort to concentrate solely on the interactions between the namespace and System Folder View Object. For the purposes of this sample, the information that results in the view that appears in the illustration above has been packed into Item Identifier List (PIDL) structures, making it easy to access information in relation to a PIDL at any time. The illustration shows the structure of the PIDL as defined in FolderViewImpl_ShellFolder.h.

The basic procedures and main interfaces that are discussed in the remainder of this topic are:

  1. IShellFolder::CreateViewObject is called by the Shell to create the System Folder View Object.
  2. The System Folder View Object queries IShellFolder for IShellFolder2, through which it gets its display information.
  3. Grouping in the view is attained through the implementation of ICategoryProvider, which in turn creates instances of ICategorizer as needed for each set of groups.
  4. IShellFolder::GetUIObjectOf and IShellFolder::CreateViewObject are used to implement and return an IContextMenu interface.

The System Folder View Object supports callbacks for various purposes such as returning handles or sending notification when certain actions are complete. However, this functionality is not discussed in this document since it is not necessary for basic functionality.

This document was written for and the sample tested on Windows XP Service Pack 2 (SP2). Though no guarantee can be made concerning future design decisions, an attempt has been made to make this sample forward compatible.

Getting Started - Implementing IShellFolder Methods

When implementing a Shell namespace extension with a view, you must implement IShellFolder and, preferably, IShellFolder2. This section discusses particular interface methods that may be implemented differently when using the System Folder View Object, or information that you should know about how the System Folder View Object works.

IShellFolder::CreateViewObject

IShellFolder::CreateViewObject is called when Windows Explorer is asked to display your view object. To use the System Folder View Object rather than a custom IShellView implementation, call one of two Shell functions - SHCreateShellFolderView or SHCreateShellFolderViewEx - in the implementation of CreateViewObject. The two functions are very similar but differ in how they handle associated callback functions. This sample uses SHCreateShellFolderView.

The section of sample code in FolderViewImpl_ShellFolder.cpp used to create the System Folder View Object is shown here.

Creating the System Folder View Object

The CreateViewObject implementation should also be used to instantiate the ICategoryProvider, IDropTarget and IContextMenu interfaces, which provide standard functionality for the view.

Note that the IContextMenu instantiated in CreateViewObject represents the context menu for the background of the view itself. Requests for a context menu for individual items in the view go to IShellFolder::GetUIObjectOf. This, as well as ICategoryProvider, is discussed in detail in the Context Menus and Categories section of this article.

Also note that the FolderViewImpl sample does not instantiate IDropTarget, which means that nothing can be dragged to the view and dropped.

IShellFolder2::GetDetailsOf & GetDefaultColumnState

When using the System Folder View Object, the Shell makes an initial call to GetDetailsOf, using a null PIDL, to retrieve the column count, column titles, and basic formatting information. It also makes a call to IShellFolder2::GetDefaultColumnState [KT1] before the initial enumeration of the columns, ensuring that at least one column (Col 0) is visible. GetDefaultColumnState is then called after each column is enumerated. If the call to GetDetailsOf/GetDetailsEx can be slow to retrieve a certain property, pass the SHCOLSTATE_SLOW flag in the SHCOLUMNINFO structure to move that retrieval to a background thread.

After the System Folder View Object has enumerated the columns, it proceeds with further calls to GetDetailsOf to fill in the data with valid PIDLs and column numbers.

IShellFolder2::MapColumnToSCID [KT2] 

A SHCOLUMNID structure, known colloquially as a SCID (pronounced "skid") contains a format ID and a property ID (PID). The combination of the format ID, a globally unique identifier (GUID) also used to identify a property group, and a PID uniquely defines a column. SHCOLUMNID structures are used by categorizers (ICategoryProvider) and IShellFolder2::GetDetailsEx, among others.

The FolderViewImpl sample uses its implementation of IShellFolder2::MapColumnToSCID to convert the column number to a SHCOLUMNID structure. FolderViewImpl then calls a helper function named _GetColumnDisplayName that accepts a PIDL and a SHCOLUMNID as parameters and returns a user-friendly string to use as the column label.

Note that the more common column names have been given standard set identifiers and property IDs. You should use those identifiers when defined rather than defining your own. See https://msdn.microsoft.com/library/default.asp?url=/library/en-us/indexsrv/html/ixrefint_7wc3.asp.

IShellFolder2::GetDetailsEx [KT3] 

IShellFolder2::GetDetailsEx is used to retrieve the same information as IShellFolder2::GetDetailsOf, but generally in different formats. IShellFolder2::GetDetailsOf retrieves a display string, where IShellFolder2::GetDetailsEx, which is the preferred method, retrieves a variant with a raw value. By implementing both functions, your data is available in both ways.

The FolderViewImpl sample provides a generic helper function called _GetColumnDisplayName which retrieves a column's display text. GetDetailsEx simply calls the function using the SHCOLUMNID passed to it while GetDetailsOf must first call MapColumnToSCID to form a SHCOLUMNID before calling the helper function.

IShellFolder::CompareIDs [KT4] 

Double-clicking a column heading sorts the view based on that column. The sorting is done through the IShellFolder::CompareIDs method. The column number is contained in the low word of that method's lParam parameter. It should be noted that two PIDLs compared by this method might not be single level and a comparison of the entire PIDL may be necessary. Multilevel PIDLs must be compared by binding to the IShellFolder at each level and then letting that IShellFolder instance's CompareIDs method do the comparison. The _ILCompareRelIDs function is provided in the FolderViewImpl_ShellFolder.cpp file for this purpose.

Context Menus and Categories

There are two context menus that must be considered: item menus - those menus that are specific to an item in a list view - and the background menu, used to set the view mode and categories. This section is not meant to be a full set of instructions on the use of context menus, but only for folder navigation (including Open and Explore) for items and groups in the System Folder View Object.

Item Menus

When a request is made for the context menu for an item, a cascade of calls to your implementation of the following methods is initiated by the System Folder View Object. The result of these calls is that you obtain the System Folder View Object's IUnknown pointer.

  1. IShellFolder::GetUIObjectOf is called to obtain an IContextMenu interface.
  2. IContextMenu::QueryInterface is called to request a pointer to IObjectWithSite.
  3. IObjectWithSite::SetSite is called, using the IUnknown pointer of the System Folder View Object. Your implementation of SetSite should store that IUnknown pointer for later use.

With that IUnknown pointer in hand, you can provide your own cascade of calls.

  1. Call IUnknown::QueryInterface for IServiceProvider.
  2. Call IServiceProvider::QueryService to retrieve an IShellBrowser (as shown in the following snippet). IShellBrowser allows communication and interaction with the Windows Explorer frame.
  3. Use IShellBrowser::BrowseObject to implement your Open and Explore functions, duplicating the standard Shell behavior.

Background Context Menu

The System Folder View Object adds three entries to the background context menu: View, which contains the same entries as the standard View menu on the toolbar; Refresh, which provides the normal refresh functionality; and Arrange Icons By.

Choosing Arrange Icons By displays a submenu of options by which to arrange the items in category view. The first options listed are those associated with particular visible columns. Below those entries are the special categories, in this case only Value. This is followed by Show in Groups, Auto Arrange, and Align to Grid. Show in Groups instructs the System Folder View Object to use the current categorizer to display the data in groups. The remainder of this document examines the steps that the System Folder View Object uses to fill the Arrange Icons By submenu.

Categories

To better understand the concept of categories, look at My Computer, which is implemented using the System Folder View Object. To display the context menu, right-click on the view's background. From that menu, choose Arrange Icons By and check Show in Groups. Then, from that same menu, select different columns to sort by and watch the groups change based on the column selected.

Each column is represented by a SHCOLUMNID and mapped in your code to a category GUID representing the set of groups. The groups themselves are represented by DWORD values. Each category (represented by the GUID), therefore, has a list of DWORD values representing the groups. In the table below, the DWORD values are presented as defined constants such as Small or Numerical.

So far our discussion has dealt only with mapping categories to columns. However, it is not required that categories map to a column. This is discussed in the ICategoryProvider section below.

The remainder of this document explores these issues based on an implementation using the following model.

Column

NA

Title

Name

Size

Sides

SHCOLUMNID

SCID_NAME

SCID_SIZE

SCID_SIDES

SCID_LEVEL

CAT_GUID_VALUE

Category GUID

CAT_GUID_NAME

CAT_GUID_SIZE

CAT_GUID_SIDES

CAT_GUID_LEVEL

CAT_GUID_VALUE

Category/Groups

Alphabetical

Small

Circle

Numerical

Less Than Five

Med

Triangle

Five or Greater

Large

Square

Polygon

ICategoryProvider

The first thing the System Folder View Object attempts to do is query your implementation of IShellFolder::CreateViewObject for a pointer to an instance of ICategoryProvider. If this succeeds, the System Folder View Object iterates through the visible columns, passing each column's SHCOLUMNID to ICategoryProvider::CanCategorizeOnSCID to determine whether the column can be categorized. If you have defined the column such that it can be categorized, its name is added to the list in the top section of the submenu. The illustration shows the result of success for all four of the sample columns.

As mentioned above, you can define categories that do not map to columns. The System Folder View Object requests, though ICategoryProvider::EnumCategories, a standard enumerator in the form of an IEnumGuid interface. This interface enumerates those categories that you've defined beyond those that map to columns. The illustration shows that it has processed the GUID for one additional category. ICategoryProvider::GetCategoryName was called to resolve that category's name as "Value". The remaining standard entries are enabled or disabled depending on the current view type. At this point the System Folder View Object has all of the information necessary to display the context menu.

ICategorizer

When one of the categories is selected from the context menu, that category's GUID is passed to ICategoryProvider::CreateCategory in a request for an ICategorizer.

Once the categorizer is created, it is used to organize the items into groups. First, the PIDLs are passed to ICategorizer::GetCategory to retrieve the DWORD representation of the categories (the category identifiers). Next, ICategorizer::GetCategoryInfo is called to retrieve the display names of the categories. Finally, the listing order of the groups is determined by the ICategorizer::CompareCategory method.


 [KT1]Use SHCOLSTATE_SLOW to tell the view to call GetDetailsOf/GetDetailsEx from a background thread

 [KT2]Forward thinking shell extension should use well known guid/pid pairs where it makes since such as PSGUID_STORAGE, PID_STG_NAME.

 [KT3]GetDetailsOf generally should produce a formatted string for display. GetDetailsEx (which is preferred generally produces variants with the raw value. You can use SHCOLSTATE_PREFER_VARCMP and we will compare the property values using GetDetailsEx (comparing the raw values)

 [KT4]I would be nice to point out the correct implementation of SHCIDS_CANONICALONLY and SHCIDS_ALLFIELDS. SHCIDS_CANONICALONLY should only test if the identify of 2 items is the same. If it compare 2 different items to be the same or compares to same items to be different XP/XP2 Defview will get confused and can AV.


Document Info


Accesari: 6270
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )