📄 cb200006dc_f.asp.htm
字号:
for each item. Many folders expose this interface to allow applications (namely
Windows Explorer) to extract the information that appears in the supplementary
columns of the Explorer's folder view. For file-system folders, these fields
typically indicate the size, type, modification date, and attributes of each
object. For virtual folders, this data usually indicates folder-specific
attributes. For example, the Control Panel folder presents the "Description"
column, where each field yields information about the purpose of the associated
applet. </p>
<p class=BodyText> </p>
<p class=BodyText> The <i
style='mso-bidi-font-style:normal'>IShellDetails</i> interface can be used to
retrieve the supplementary information for each shell object, including the
captions of each column header. A pointer to this interface is retrieved via
the <i>IShellFolder::CreateViewObject</i> member function (specifying the <i
style='mso-bidi-font-style:normal'>IID_IShellDetails</i> interface identifier).
Supplementary information is then retrieved via the <i>IShellDetails::GetDetailsOf</i>
member function: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>HRESULT
GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, </span></p>
<p class=Code><span class=Code> LPSHELLDETAILS pDetails); </span></p>
<p class=BodyText> </p>
<p class=BodyText> The
first parameter to this function is the relative PIDL of the object whose
information we are interested in. For column headers, this parameter is set to
NULL. The <i>iColumn</i> parameter specifies
the zero-based index of the target column. The retrieved information is returned
via the <i>pDetails</i> parameter, a pointer
to a SHELLDETAILS structure: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>typedef</b>
<b>struct</b> _SHELLDETAILS</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> int</b>
fmt; </span></p>
<p class=Code><span class=Code> <b> int</b>
cxChar; </span></p>
<p class=Code><span class=Code> STRRET str; </span></p>
<p class=Code><span class=Code>} SHELLDETAILS,
*LPSHELLDETAILS; </span></p>
<p class=BodyText> </p>
<p class=BodyText> The <i
style='mso-bidi-font-style:normal'>fmt</i> data member indicates the text
alignment of the column header and its entries, while the <i>cxChar</i> data member indicates the number of characters in the column
header. The caption (field entry) for the particular column (shell object) is
stored in the <i>str</i> data member. This
STRRET-type member can be converted to a character array via the <i
style='mso-bidi-font-style:normal'>BufferFromSTRRET</i> utility function (from
the "pidlhelp" library). <a href="#ListingFour">Listing Four</a>
provides the implementation of our <i>DoHandleShellDetails</i>
member function, which uses the <i>IShellDetails</i>
interface to prepare the column headers. </p>
<p class=BodyText> </p>
<p class=BodyText> For
those folders that do not expose the <i>IShellDetails</i>
interface, we have no choice but to hard-code the column headers. To retrieve
the field entries for the objects within the folder, we use the <i
style='mso-bidi-font-style:normal'>SHGetDataFromIDList</i> API function. This
function simply fills a WIN32_FIND_DATA structure with information contained in
the PIDL itself. If such information is not available, we default to the more
conventional <i>FindFirstFile</i> API
function. These tasks are handled via our <i>DoFillShellExtraInfo</i>
member function, whose implementation is shown in <a href="#ListingFive">Listing Five</a>.</p>
<p class=BodyText> </p>
<p class=BodyText> Finally,
it should be mentioned that for Windows 2000 and later systems, the <i
style='mso-bidi-font-style:normal'>IShellDetails</i> interface has been
superceded by the <i>IShellFolder2</i>
interface. This latter interface also presents the <i>GetDetailsOf</i> member function with an identical signature (and
identical functionality) as that of its <i>IShellDetails</i>
counterpart. </p>
<p class=BodyText> </p>
<p class=BodyText> To help
fortify the techniques of using the <i>IShellDetails</i>
interface, refer to the DemoShellDetails sample project (included with the
downloadable source code; see end of article for details). In this project, the
task of retrieving the "details information" for a particular shell folder is
isolated from the rest of the <i>TExpListView</i>
implementation. </p>
<p class=BodyText> </p>
<p class=Subheads>Providing
Sorting Capabilities</p>
<p class=BodyText> Fortunately,
since we're working with the <i>IShellFolder</i>
interface, we can use the <i>IShellFolder::CompareIDs</i> member function to
provide support for sorting the items. The function takes an integer value as
its first parameter, and a pair of relative PIDLs as its second and third
parameters: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>HRESULT
CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, </span></p>
<p class=Code><span class=Code> LPCITEMIDLIST pidl2); </span></p>
<p class=BodyText> </p>
<p class=BodyText> The
value specified by the <i>lParam</i>
argument determines the criterion by which to sort the objects indicated by the
<i>pidl1</i> and <i>pidl2</i> parameters. For example, to sort by display name, we pass 0
as the <i>lParam</i> parameter. To sort by
file size, file type, or modification date, we set <i>lParam</i> to 1, 2, or 3, respectively. We support this functionality
in our component via the public <i>DoCustomSort</i>
member function, as shown in <a href="#ListingSix">Listing Six</a>.</p>
<p class=BodyText> </p>
<p class=BodyText> Our <i
style='mso-bidi-font-style:normal'>DoCustomSort</i> member function uses the <i
style='mso-bidi-font-style:normal'>TCustomListView::CustomSort</i> member function, and our <i>ExpCustomSortProc</i> callback function. We make this latter function a
friend of our class, so it can access the private <i>m_FInitialSort</i> member. Access to this member is crucial, because
the contents of the folder need to initially be sorted in ascending order. This
is accomplished by reversing the sign of the return value of the <i
style='mso-bidi-font-style:normal'>CompareIDs</i> function call. Once initially
sorted, the direction of the sort can be toggled by calling the <i
style='mso-bidi-font-style:normal'>CustomSort</i> member function successively.
Moreover, this initialization needs to be performed when the <i
style='mso-bidi-font-style:normal'>lParam</i> argument of the <i
style='mso-bidi-font-style:normal'>CompareIDs</i> member function is changed.
That is, even if the contents have been initially sorted according to name, we
are still required to initially reverse the sign of the return value, if we
need to sort by any other criterion. </p>
<p class=BodyText> </p>
<p class=Subheads>Displaying
the Context Menu</p>
<p class=BodyText> The
context menu of a shell object (see Figure 3) is handled via the <i
style='mso-bidi-font-style:normal'>IContextMenu</i> and <i>IContextMenu2</i> interfaces. </p>
<p class=BodyText> </p>
<p class=Captions><img width=333 height=275
src="images/cb200006dc_f_image004.jpg" tppabs="http://www.cbuilderzine.com/features/2000/06/cb200006dc_f/cb200006dc_f_image004.jpg" align=left hspace=12><b>Figure 3:</b> A shell object's context menu. </p>
<p class=BodyText> </p>
<p class=BodyText> A
pointer to the former is retrieved via the <i>IShellFolder::GetUIObjectOf</i> member function,
which takes six parameters: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>HRESULT
GetUIObjectOf(</span></p>
<p class=Code><span class=Code> HWND hwndOwner, </span></p>
<p class=Code><span class=Code> UINT cidl, </span></p>
<p class=Code><span class=Code> LPCITEMIDLIST *apidl, </span></p>
<p class=Code><span class=Code> REFIID riid, </span></p>
<p class=Code><span class=Code> UINT *prgfInOut, </span></p>
<p class=Code><span class=Code> LPVOID *ppvOut</span></p>
<p class=Code><span class=Code>);</span></p>
<p class=BodyText> </p>
<p class=BodyText> The <i
style='mso-bidi-font-style:normal'>hwndOwner</i> parameter indicates the handle
of the window that is to own any dialog boxes that may be displayed. The <i
style='mso-bidi-font-style:normal'>cidl</i> parameter indicates the number of
PIDLs present in the PIDL array passed as the <i>apild</i> parameter. This array specifies the shell objects for which
the context menu should apply. The <i>riid</i>
parameter is used to specify the interface whose pointer we are interested in
retrieving. Here, we pass the <i>IID_IContextMenu</i>
identifier, indicating that we want a pointer to the <i>IContextMenu</i> interface. This pointer is returned via the <i
style='mso-bidi-font-style:normal'>ppvOut</i> parameter. The <i
style='mso-bidi-font-style:normal'>prgfInOut</i> is reserved, and is set to
NULL. </p>
<p class=BodyText> </p>
<p class=BodyText> With a
pointer to the <i>IContextMenu</i>
interface, we grab a pointer to the <i>IContextMenu2</i>
interface via the <i>IContextMenu::QueryInterface</i> member function.
Strictly speaking, the <i>IContextMenu2</i>
interface isn't necessary. The interface is simply an extension of the <i
style='mso-bidi-font-style:normal'>IContextMenu</i> interface that provides
support for owner-drawn menu items. In this case, we use the <i
style='mso-bidi-font-style:normal'>IContextMenu2</i> interface to allow for
display of items in the Send To sub-menu. </p>
<p class=BodyText> </p>
<p class=BodyText> Once we
have a pointer to the <i>IContextMenu2</i>
interface, we create a popup menu, then use the <i>QueryContextMenu</i> member function to fill this menu with relevant
items. The amount and type of menu items that are added are determined by the
array of PIDLs initially passed to the <i>GetUIObjectOf</i>
member function. Once the menu has been successfully filled, we display the
popup menu via the <i>TrackPopupMenu</i> API
function. When used with the TPM_RETURNCMD flag, this latter function returns a
DWORD value indicating the command of the menu item that was selected. We use
this value with the <i>IContextMenu::InvokeCommand</i> member function
to instruct the shell to invoke the selected command. </p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -