首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

ATL 實作 Shell 擴展之 Context Menu Handler:右鍵選單註冊 DLL 元件

     編輯:關於VC++

Windows Shell 擴展讓我們能將自訂功能整合到總管右鍵選單、屬性頁、拖放操作等系統介面。本系列首篇以 Context Menu Handler(右鍵選單處理器) 為例,示範如何用 ATL 開發一個針對 .dll 檔案的右鍵選單擴充,提供「註冊元件」與「反註冊元件」功能,免去手動輸入 regsvr32 的麻煩。

Shell 擴展類型總覽

處理器類型觸發時機對應 COM 介面
Context Menu Handler右鍵點擊檔案/資料夾IContextMenu
Property Sheet Handler右鍵→屬性IShellPropSheetExt
Drag & Drop Handler右鍵拖放檔案IContextMenu + 註冊表
Drop Handler檔案被拖放到目標IDropTarget
QueryInfo Handler (Shell 4.71+)滑鼠懸停檔案IQueryInfo

專案建立步驟

  1. 新建 ATL COM AppWizard 專案,名稱 SimpleExt
  2. 選擇 Dynamic Link Library (DLL)(Shell 擴展必須為 In-process Server)
  3. ATL 物件精靈新增簡單物件 SimpleShlExt

核心介面實作

1. IShellExtInit — 初始化,取得右鍵點選的檔案路徑

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;
}

2. 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 對應表與註冊表腳本


// 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'
                    }
                }
            }
        }
    }
}

偵錯技巧

  • 專案設定 → Debug → 執行檔指定為 explorer.exe
  • 或使用 regsvr32 SimpleExt.dll 註冊後,直接在總管測試

效果展示

DLL 右鍵選單效果

WinRAR 右鍵選單參考

系列預告

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

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved