2.編譯並測試:
a.打開一個命令行窗口,並且將目錄(cd)切換到SLUtil.exe所在的位置。
b.打開緊鄰命令行窗口的庫Shell文件夾,你將會看到你使用SLUtil工具所做的變 化.
c.在命令行窗口中,測試SLUtil命令。
d.試著為你的MyLib庫使用一個與Pictures庫相同的圖標。
e.試著將你的庫在文件管理面板中鎖定和解鎖。
f.改變庫的默認存儲位置,將這個位置移到文件系統中另外的位置,並且測試默認的存 儲位置是否解決了這個變化。
任務 6 –添加FolderType 命令
每個庫都有一個文件夾模板類型。這個類型定義了Shell庫窗口的樣子和感覺,例如,圖 片和音樂就有不同的模板。IShellLibrary SetFolderType()方法則使用GUID的方式來表示 文件夾的類型id。GetFolderType()方法則能返回當前文件夾的id。默認情況,用戶創建的 庫,都是一般文件夾類型。
為了讓用戶使用文本類型而不是使用GUID,我們需要使用一個幫助類。 CfolderTypeIdNameConverter這個類知道如何將Pictures, Music, Documents, Videos, 和 Generic轉換成相應的FOLDERTYPEID_*,同樣,反之亦然。同時,這個方法還知道取名稱的 一部分,比如vid 就是 Videos。這些都將使設置庫文件夾的類型變得簡單:SLUtil FolderType MyLib doc
1.向項目中添加FolderTypeIdNameConverter.h 和 FolderTypeIdNameConverter.cpp文 件。你可以從Starter文件夾中找到它們。
2.添加 #include "FolderTypeIdNameConverter.h"
3.添加下面的代碼片段,來實現FolderType命令:
C++ (SLUtil.cpp)
//Set or get the library's folder template
void FolderType(const CCommand &command, const vector<PCWSTR> &arguments)
{
IShellLibrary *shellLibrary = NULL;
HRESULT hr = S_OK;
FOLDERTYPEID folderTypeId;
CFolderTypeIdNameConverter converter;
//Show current folder type
if (arguments.size() == 1)
{
//Open library with read permissions
IShellLibrary *shellLibrary =
OpenLibrary(L"FolderType", arguments[0]);
hr = shellLibrary->GetFolderType(&folderTypeId);
if (FAILED (hr))
{
wcerr <<
L"FolderType: Can't get the library's folder template."
<< endl;
exit(5);
}
wcout << L"Library " << arguments[0] << L": Folder template is: " << converter.GetFolderTypeIdName(folderTypeId) << endl;
}
else //Set the current folder type
{
//Open library with read/write permissions
IShellLibrary *shellLibrary =
OpenLibrary(L"FolderType", arguments[0], false);
hr = converter.GetFolderTypeIdFromName(arguments[1],
&folderTypeId);
if (FAILED (hr))
{
wcerr << L"FolderType: Invalida folder template name." <<
endl;
exit(6);
}
hr = shellLibrary->SetFolderType(folderTypeId);
if (FAILED (hr))
{
wcerr <<
L"FolderType: Can't set the library's folder template,"
<< endl;
exit(7);
}
//Commit the library changes
shellLibrary ->Commit();
}
if (shellLibrary != NULL)
shellLibrary ->Release();
}
COMMAND(L"FolderType",
L"SLUtil FolderType LibraryName [Documents|Pictures|Music|Videos|Generic]",
L"Set or get the library's folder template", L"SLUtil MyLib Documents", 1,
FolderType);
4.編譯和測試:
a.打開一個命令行窗口,並且將目錄(cd)切換到SLUtil.exe所在的位置。
b.打開緊鄰命令行窗口的庫Shell文件夾,你將會看到你使用SLUtil工具所做的變 化.
c.在命令行窗口中,測試SLUtil命令。
d.嘗試將Pictures庫的文件夾類型,賦給你的MyLib庫。
任務 7 –添加ListFolders 命令
GetFolders() 方法將一個文件夾的數組返回到COM對象中,這個對象用來實現 IShellItemArray。IShellItemArray有一個 GetCount()方法,這個方法能夠返回數組的長 度,GetItemAt()返回一個實現IShellItem並且代表一個Shell文件夾的COM 對象。應用程序 可以使用Shell文件夾的ParsingPath屬性來獲取文件夾的路徑。它能夠通過IShellItem2接 口的 GetString()方法來讀取基於字符串的屬性。這就是為什麼我們需要將從 IShellItemArray獲取到的IShellItem接口,轉換成 IShellItem2接口。另外一個復雜的問 題是,我們不得不注意我們所處理的是否被重命名,移動或者刪除了。我們需要使用 ResolveFolder()方法來解決這些問題。
1.添加下面的代碼片段:
C++ (SLUtil.cpp)
//List all library folders
void ListFolders(const CCommand &command, const vector<PCWSTR> &arguments)
{
IShellLibrary *shellLibrary = OpenLibrary (L"ListFolders", arguments[0]);
HRESULT hr = S_OK;
IShellItemArray *shellItemArray = NULL;
shellLibrary->GetFolders(LFF_ALLITEMS, IID_PPV_ARGS(&shellItemArray));
if (FAILED(hr))
{
wcerr << L"ListFolders: Can't get the library's folder list." <<
endl;
exit(5);
}
wcout << L"Folder list of " << arguments[0] << L" library:" << endl;
DWORD count;
shellItemArray->GetCount (&count);
//Iterate through all library folders
for (DWORD i = 0; i < count; ++i)
{
IShellItem *shellItem;
IShellItem2 *shellItem2;
hr = shellItemArray->GetItemAt(i, &shellItem);
if (FAILED (hr))
continue;
//Convert IShellItem to IShellItem2
shellItem- >QueryInterface(IID_PPV_ARGS(&shellItem2));
shellItem- >Release();
IShellItem2 *shellItemResolvedFolder = NULL;
//Fix folder path changes
hr = shellLibrary->ResolveFolder(shellItem2, 5000,
IID_PPV_ARGS(&shellItemResolvedFolder));
if (SUCCEEDED(hr))
{
//Point to the fixed folder
shellItem2->Release();
shellItem2 = shellItemResolvedFolder;
}
//else we will show the unfixed folder
PWSTR folderPath;
hr = shellItem2->GetString(PKEY_ParsingPath, &folderPath);
if (SUCCEEDED(hr))
{
wcout << folderPath << endl;
}
CoTaskMemFree(folderPath);
shellItem2- >Release();
}
shellItemArray->Release();
shellLibrary->Release();
}
COMMAND(L"ListFolders", L"SLUtil ListFolders LibraryName", L"List all library folders.", L"SLUtil ListFolders Documents", 1, ListFolders);
2.編譯並且測試:
a.打開一個命令行窗口,並且將目錄(cd)切換到SLUtil.exe所在的位置。
b.打開緊鄰命令行窗口的庫Shell文件夾,你將會看到你使用SLUtil工具所做的變 化.
c.在命令行窗口中,測試SLUtil命令。
d.列出庫中的內容。
e.嘗試去重命名,移動或刪除文件夾,並且看一看庫是如何來解決這些問題的。
任務 8 – 添加ManageUI 命令
最後,完成SLUtil的最終命令是ManageUI命令。這個命令將會顯示一個Shell庫的管理窗 口:
SHShowManageLibraryUI()API將獲取一個能夠代表Shell庫的Shell元素,並且展示一個 庫管理對話框。你只需要提供父窗體的句柄,標題的文本和說明。你同時也可以決定是否允 許添加一個可能會降低庫操作速度、不能索引的網絡文件夾。
1.添加下面的代碼:
C++ (SLUtil.cpp)
//Show the Shell Library management UI
void ManageUI(const CCommand &command, const vector<PCWSTR> &arguments)
{
PWSTR libraryFullPath = NULL;
HRESULT hr = GetLibraryFromLibrariesFolder(arguments[0], NULL, false,
&libraryFullPath);
if (FAILED(hr))
{
wcerr << L"ManageUI: Can't get library." << endl;
exit(4);
}
IShellItem *shellItem = NULL;
hr = SHCreateItemFromParsingName (libraryFullPath, 0,
IID_PPV_ARGS (&shellItem));
if (FAILED(hr))
{
wcerr << L"ManageUI: Can't create COM object." << endl;
exit(5);
}
PCWSTR title = arguments[0];
PCWSTR instruction = L"Manage Library folders and settings";
if (arguments.size() > 1)
title = arguments[1];
if (arguments.size() > 2)
instruction = arguments[2];
SHShowManageLibraryUI(shellItem, NULL, title, instruction,
LMD_ALLOWUNINDEXABLENETWORKLOCATIONS);
shellItem->Release();
CoTaskMemFree(libraryFullPath);
}
COMMAND(L"ManageUI", L"SLUtil ManageUI LibraryName [Title] [Instruction]", L"Show the Shell Library management UI", L"SLUtil ManageUI Documents", 1, ManageUI);
2.編譯並測試:
a.SLUtil ManageUI Pictures "Manage Picture Library" "Add or Remove folders from the Pictures Library"
你可以在最終的解決方案文件夾中找到該實驗的最終版。干得漂亮!