初始化殼層延伸模組處理常式
Shell 延伸模組處理常式物件的大部分實作是由其類型所決定。 不過,有一些常見的元素。 本主題討論所有 Shell 延伸模組處理常式所共用實作的各個層面。
所有 Shell 延伸模組處理常式都是進程元件物件模型, (COM) 物件。 它們必須指派 GUID 並註冊,如 註冊殼層延伸模組處理常式中所述。 它們會實作為 DLL,而且必須匯出下列標準函式:
- DllMain。 DLL 的標準進入點。
- DllGetClassObject。 公開物件的類別處理站。
- DllCanUnloadNow。 COM 會呼叫此函式,以判斷物件是否為任何用戶端提供服務。 如果沒有,系統可以卸載 DLL 並釋放相關聯的記憶體。
如同所有 COM 物件,Shell 延伸模組處理常式必須實作 IUnknown 介面和 類別處理站。 大部分也必須在 Windows XP 或更早版本中實作 IPersistFile 或 IShellExtInit 介面。 這些由 Windows Vista 中的 IInitializeWithStream、 IInitializeWithItem 和 IInitializeWithFile 取代。 Shell 會使用這些介面來初始化處理常式。
IPersistFile介面必須由下列專案實作:
- 圖示處理常式
- 資料處理程式
- 卸載處理常式
IShellExtInit介面必須由下列專案實作:
- 快捷方式功能表處理常式
- 拖放處理常式
- 屬性工作表處理常式
本主題其餘部分將討論下列主題:
實作 IPersistFile
IPersistFile介面的設計目的是要允許從磁片檔案載入或儲存物件。 除了IUnknown之外,它還有六個方法、五個自己的方法,以及繼承自IPersist的GetClassID方法。 使用 Shell 延伸模組時, IPersist 只會用來初始化 Shell 延伸模組處理常式物件。 因為通常不需要從磁片讀取或寫入磁片,所以只有 GetClassID 和 Load 方法需要非Ken 實作。
Shell 會先呼叫 GetClassID ,而函式會傳回擴充處理常式物件的 clSID) (類別識別碼。 Shell 接著會呼叫 Load 並傳入兩個值。 第一個 pszFile是 Unicode 字串,其名稱為 Shell 即將運作的檔案或資料夾。 第二個是 dwMode,表示檔案存取模式。 因為通常不需要存取檔案, 所以 dwMode 通常是零。 方法會視需要儲存這些值,以供稍後參考。
下列程式碼片段說明一般 Shell 延伸模組處理常式如何實作 GetClassID 和 Load 方法。 其設計目的是要處理 ANSI 或 Unicode。 CLSID_SampleExtHandler是擴充處理常式物件的 GUID,而 CSampleShellExtension 是用來實作介面的類別名稱。 m_szFileName和m_dwMode變數是用來儲存檔案名和存取旗標的私人變數。
class CSampleShellExtension : public IPersistFile
{
// Method declarations not included
private:
WCHAR m_szFileName[MAX_PATH]; // The file name
DWORD m_dwMode; // The file access mode
}
IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
*pCLSID = CLSID_SampleExtHandler;
}
IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
m_dwMode = dwMode;
return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile);
}
// The implementation sample is continued in the next section.
實作 IShellExtInit
除了IUnknown之外,IShellExtInit介面只有一個方法IShellExtInit::Initialize。 方法有三個參數,Shell 可用來傳入各種類型的資訊。 傳入的值取決於處理常式的類型,而有些值可以設定為 Null。
- pidlFolder 會保存專案識別碼清單的資料夾指標, (PIDL) 。 這是絕對 PIDL。 對於屬性工作表延伸模組,此值為 Null。 針對快捷方式功能表延伸模組,它是資料夾的 PIDL,其中包含正在顯示其快捷方式功能表的專案。 對於非預設拖放處理常式,它是目的檔案夾的 PIDL。
- pDataObject 會保存資料物件 IDataObject 介面的指標。 資料物件會以 CF_HDROP 格式保存一或多個檔案名。
- hRegKey 會保存檔案物件或資料夾類型的登錄機碼。
IShellExtInit::Initialize方法會視需要儲存檔案名、IDataObject指標和登錄機碼,以供稍後使用。 下列程式碼片段說明 IShellExtInit::Initialize的實作。 為了簡單起見,本範例假設資料物件只包含單一檔案。 一般而言,資料物件可能包含多個檔案,每個檔案都需要擷取。
// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.
class CSampleShellExtension : public IShellExtInit
{
// Method declarations not included
private:
// IDList of the folder for extensions invoked on the folder, such as
// background context menu handlers or nondefault drag-and-drop handlers.
PIDLIST_ABSOLUTE m_pidlFolder;
// The data object contains an expression of the items that the handler is
// being initialized for. Use SHCreateShellItemArrayFromDataObject to
// convert this object to an array of items. Use SHGetItemFromObject if you
// are only interested in a single Shell item. If you need a file system
// path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
IDataObject *m_pdtobj;
// For context menu handlers, the registry key provides access to verb
// instance data that might be stored there. This is a rare feature to use
// so most extensions do not need this variable.
HKEY m_hRegKey;
}
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.
IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
__in_opt IDataObject *pDataObject,
__in_opt HKEY hRegKey)
{
// In some cases, handlers are initialized multiple times. Therefore,
// clear any previous state here.
CoTaskMemFree(m_pidlFolder);
m_pidlFolder = NULL;
if (m_pdtobj)
{
m_pdtobj->Release();
}
if (m_hRegKey)
{
RegCloseKey(m_hRegKey);
m_hRegKey = NULL;
}
// Capture the inputs for use later.
HRESULT hr = S_OK;
if (pidlFolder)
{
m_pidlFolder = ILClone(pidlFolder); // Make a copy to use later.
hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
// If a data object pointer was passed into the method, save it and
// extract the file name.
if (pDataObject)
{
m_pdtobj = pDataObject;
m_pdtobj->AddRef();
}
// It is uncommon to use the registry handle, but if you need it,
// duplicate it now.
if (hRegKey)
{
LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey);
hr = HRESULT_FROM_WIN32(result);
}
}
return hr;
}
資訊提示自訂
有兩種方式可以自訂資訊提示。 其中一種方式是實作支援 IQueryInfo 的物件,然後在登錄中的適當子機碼下註冊物件, (請參閱下列) 。 或者,您可以指定要顯示的固定字串或特定檔案屬性的清單。
若要顯示命名空間延伸模組的固定字串,請在命名空間延伸模組的 CLSID 索引鍵下方建立名為 InfoTip 的子機碼。 將該子機碼的資料設定為您想要顯示的字串。
HKEY_CLASSES_ROOT
CLSID
{CLSID}
InfoTip = InfoTip string for your namespace extension
若要顯示檔案類型的固定字串,請在您要提供資訊提示之檔案類型的ProgID索引鍵下方,建立名為InfoTip的子機碼。 將該子機碼的資料設定為您想要顯示的字串。
HKEY_CLASSES_ROOT
ProgID
InfoTip = InfoTip string for all files of this type
如果您想要 Shell 在特定檔案類型的資訊提示中顯示特定檔案屬性,請在該檔案類型的ProgID索引鍵下方建立名為InfoTip的子機碼。 將該子機碼的資料設定為標準屬性名稱或 {fmtid}的分號分隔清單,其中 propname 是標準屬性名稱,pid 是標準屬性名稱和 {fmtid},pid 是 FMTID/PID 組。
HKEY_CLASSES_ROOT
ProgID
InfoTip = propname;propname;{fmtid},pid;{fmtid},pid
您可以使用下列屬性名稱。
屬性名稱 | 描述 | 擷取自 |
---|---|---|
作者 | 檔的作者 | PIDSI_AUTHOR |
標題 | 檔的標題 | PIDSI_TITLE |
主旨 | 主旨摘要 | PIDSI_SUBJECT |
註解 | 檔批註 | PIDSI_COMMENT 或資料夾/磁片磁碟機屬性 |
PageCount | 頁面數目 | PIDSI_PAGECOUNT |
名稱 | 易記名稱 | 標準資料夾檢視 |
OriginalLocation | 原始檔案的位置 | 公事包資料夾和回收站資料夾 |
DateDeleted | 刪除日期檔案 | 回收站資料夾 |
類型 | 檔案類型 | 標準資料夾詳細資料檢視 |
大小 | 檔案大小 | 標準資料夾詳細資料檢視 |
SyncCopyIn | 與 OriginalLocation 相同 | 與 OriginalLocation 相同 |
修改日期 | 上次修改日期 | 標準資料夾詳細資料檢視 |
建立時間 | 建立日期 | 標準資料夾詳細資料檢視 |
存取方式 | 上次存取的日期 | 標準資料夾詳細資料檢視 |
InFolder | 包含檔案的目錄 | 檔搜尋結果 |
排名 | 搜尋比對的品質 | 檔搜尋結果 |
FreeSpace | 可用的儲存空間 | 磁碟機 |
NumberOfVisits | 瀏覽次數 | 我的最愛資料夾 |
屬性 | 檔案屬性 | 標準資料夾詳細資料檢視 |
公司 | 公司名稱 | PIDDSI_COMPANY |
類別 | 檔類別 | PIDDSI_CATEGORY |
著作權 | 媒體著作權 | PIDMSI_COPYRIGHT |
HTMLInfoTipFile | HTML 資訊提示檔案 | 資料夾Desktop.ini檔案 |
相關主題