解決頻繁需求:在總管右鍵選單加入「取得檔案路徑存入剪貼簿」,支援多選檔案、Ctrl+點擊輸出程式碼格式路徑 (\ → \\)。
IShellExtInit::Initialize:取得選取項目清單 (IDataObject → CF_HDROP)IContextMenu::QueryContextMenu:插入自訂選單項目IContextMenu::InvokeCommand:執行複製邏輯IContextMenu::GetCommandString:返回 E_NOTIMPLCAtlArray<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;
}
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);
}
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/UnicodeDragQueryFile(hDrop, -1, ...) 取得檔案總數GetKeyState(VK_CONTROL) 偵測修飾鍵實現進階功能