Windows Shell 擴展讓我們能將自訂功能整合到總管右鍵選單、屬性頁、拖放操作等系統介面。本系列首篇以 Context Menu Handler(右鍵選單處理器) 為例,示範如何用 ATL 開發一個針對 .dll 檔案的右鍵選單擴充,提供「註冊元件」與「反註冊元件」功能,免去手動輸入 regsvr32 的麻煩。
| 處理器類型 | 觸發時機 | 對應 COM 介面 |
|---|---|---|
| Context Menu Handler | 右鍵點擊檔案/資料夾 | IContextMenu |
| Property Sheet Handler | 右鍵→屬性 | IShellPropSheetExt |
| Drag & Drop Handler | 右鍵拖放檔案 | IContextMenu + 註冊表 |
| Drop Handler | 檔案被拖放到目標 | IDropTarget |
| QueryInfo Handler (Shell 4.71+) | 滑鼠懸停檔案 | IQueryInfo |
SimpleExtSimpleShlExtIShellExtInit — 初始化,取得右鍵點選的檔案路徑STDMETHODIMP CSimpleShlExt::Initialize(LPCITEMIDLIST pidlFolder,
LPDATAOBJECT pDataObj, HKEY hkeyProgID) {
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
if (FAILED(pDataObj->GetData(&fmt, &stg))) return E_INVALIDARG;
HDROP hDrop = (HDROP)GlobalLock(stg.hGlobal);
if (!hDrop) return E_INVALIDARG;
UINT nCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
if (nCount == 1) { // 僅處理單檔案
TCHAR szFile[MAX_PATH];
DragQueryFile(hDrop, 0, szFile, MAX_PATH);
m_strFile = szFile; // 成員變數保存檔案路徑
}
GlobalUnlock(stg.hGlobal);
ReleaseStgMedium(&stg);
return S_OK;
}
IContextMenu — 建立選單項、狀態列提示、執行命令
// 1. 加入選單項
STDMETHODIMP CSimpleShlExt::QueryContextMenu(HMENU hmenu, UINT indexMenu,
UINT idCmdFirst, UINT idCmdLast, UINT uFlags) {
InsertMenu(hmenu, indexMenu, MF_STRING | MF_BYPOSITION,
idCmdFirst, _T("註冊元件 (&R)"));
InsertMenu(hmenu, indexMenu + 1, MF_STRING | MF_BYPOSITION,
idCmdFirst + 1, _T("反註冊元件 (&U)"));
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 2); // 回傳加入項目數
}
// 2. 狀態列提示
STDMETHODIMP CSimpleShlExt::GetCommandString(UINT_PTR idCmd, UINT uFlags,
UINT* pwReserved, LPSTR pszName, UINT cchMax) {
if (uFlags & GCS_HELPTEXT) {
if (idCmd == 0) lstrcpyn(pszName, "註冊此 DLL 元件到系統", cchMax);
else if (idCmd == 1) lstrcpyn(pszName, "從系統移除此 DLL 元件註冊", cchMax);
}
return S_OK;
}
// 3. 執行命令
STDMETHODIMP CSimpleShlExt::InvokeCommand(LPCMINVOKECOMMANDINFO pici) {
UINT idCmd = LOWORD(pici->lpVerb);
if (HIWORD(pici->lpVerb) != 0) return E_INVALIDARG; // 非數字 ID
CString cmd = (idCmd == 0) ? _T("regsvr32 /s \"") + m_strFile + _T("\"")
: _T("regsvr32 /u /s \"") + m_strFile + _T("\"");
WinExec(cmd, SW_HIDE);
return S_OK;
}
// COM_MAP
BEGIN_COM_MAP(CSimpleShlExt)
COM_INTERFACE_ENTRY(ISimpleShlExt)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellExtInit)
COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP()
// 註冊表資源
HKCR {
NoRemove dllfile {
NoRemove ShellEx {
NoRemove ContextMenuHandlers {
ForceRemove SimpleShlExt = s '{YOUR-CLSID-GUID}'
}
}
}
}
// WinNT 權限:Approved 列表
HKLM {
Software {
Microsoft {
Windows {
CurrentVersion {
Shell Extensions {
Approved = s '{YOUR-CLSID-GUID}' = s 'Simple Shell Extension'
}
}
}
}
}
}
explorer.exeregsvr32 SimpleExt.dll 註冊後,直接在總管測試

後續文章將介紹 Property Sheet Handler、Drop Handler、DeskBand 等更多 Shell 擴展類型。歡迎交流指正!