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

Shell 擴充:自訂右鍵選單「複製檔案完整路徑」

     編輯:關於C++

實作 Shell Context Menu 擴充:一鍵複製多檔完整路徑至剪貼簿

解決頻繁需求:在總管右鍵選單加入「取得檔案路徑存入剪貼簿」,支援多選檔案、Ctrl+點擊輸出程式碼格式路徑 (\ → \\)。

COM 介面實作架構

  • IShellExtInit::Initialize:取得選取項目清單 (IDataObject → CF_HDROP)
  • IContextMenu::QueryContextMenu:插入自訂選單項目
  • IContextMenu::InvokeCommand:執行複製邏輯
  • IContextMenu::GetCommandString:返回 E_NOTIMPL

關鍵實作細節

1. 初始化:解析 HDROP 取得路徑陣列

CAtlArray<CString> m_arrFilePath;

STDMETHODIMP Initialize(LPCITEMIDLIST, IDataObject* pDataObj, HKEY) {
    m_arrFilePath.RemoveAll();
    if (pDataObj) {
        STGMEDIUM medium = {}; FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
        if (SUCCEEDED(pDataObj->GetData(&fe, &medium))) {
            HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);
            UINT count = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
            for (UINT i = 0; i < count; ++i) {
                TCHAR path[MAX_PATH];
                DragQueryFile(hDrop, i, path, MAX_PATH);
                m_arrFilePath.Add(path);
            }
            GlobalUnlock(medium.hGlobal);
            ReleaseStgMedium(&medium);
        }
    }
    return S_OK;
}

2. 建立選單項目

STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT index, UINT idFirst, UINT, UINT) {
    CString text = _T("取得檔案路徑並存入剪貼簿");
    InsertMenu(hMenu, index++, MF_STRING | MF_BYPOSITION, idFirst + ID_COPY_PATH, text);
    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, ID_COPY_PATH + 1);
}

3. 執行命令:組裝字串並寫入剪貼簿

STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pInfo) {
    bool ctrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;  // Ctrl 鍵狀態
    if (LOWORD(pInfo->lpVerb) == ID_COPY_PATH) {
        CString all;
        for (int i = 0; i < m_arrFilePath.GetCount(); ++i) {
            CString item = m_arrFilePath[i];
            if (ctrl) item.Replace(_T("\\"), _T("\\\\"));  // 程式碼格式
            all += item + _T("\r\n");
        }
        if (OpenClipboard(NULL)) {
            EmptyClipboard();
            HGLOBAL hMem = GlobalAlloc(GPTR, (all.GetLength() + 1) * sizeof(TCHAR));
            LPTSTR p = (LPTSTR)GlobalLock(hMem);
            _tcscpy_s(p, all.GetLength() + 1, all);
            SetClipboardData(CF_TEXT_FORMAT, hMem);
            GlobalUnlock(hMem);
            CloseClipboard();
        }
    }
    return S_OK;
}

註冊機制

在登錄 HKEY_CLASSES_ROOT\*\ShellEx\ContextMenuHandlers\{YourGUID} 建立項目,值為 COM 類別的 CLSID。ATL 專案在 .rgs 腳本配置:

HKCR {
    NoRemove * {
        NoRemove ShellEx {
            NoRemove ContextMenuHandlers {
                ForceRemove 'GetFilePath' = s '{YOUR-CLSID-GUID}'
            }
        }
    }
}

實用技巧

  • CF_TEXT_FORMAT 宏自動切換 ANSI/Unicode
  • DragQueryFile(hDrop, -1, ...) 取得檔案總數
  • GetKeyState(VK_CONTROL) 偵測修飾鍵實現進階功能
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved