右鍵取得當前檔案路徑

調教電腦

Hyno
8 min readApr 6, 2024

前言

Windows疑似沒有提供這種功能,而且"內容"裡面也沒有相關的東西

所以想要拿到檔案絕對路徑就會變得特別麻煩

那就來自己寫吧

正文

目標大略如下:

  1. 弄個右鍵選單
  2. 按下時複製路徑到剪貼簿

弄個右鍵選單

再複習一下我之前寫的”Open CMD Here”之後,我發現reg是這樣寫的:

  1. 資料夾背景/桌面:HKEY_CLASSES_ROOT\Directory\Background\shell
  2. 資料夾:HKEY_CLASSES_ROOT\Directory\shell
  3. 檔案:HKEY_CLASSES_ROOT\*\shell or HKEY_CLASSES_ROOT\[副檔名]\shell

這些是按右鍵的對象,然後如果想要新增一個選項

就在某個shell下新增一個key,假設叫做MyOption ,以資料夾背景對象作範例:

這個key的(Default)值就會是右鍵選單中的名稱:

再來是這個選項的圖標,在剛剛的MyOption裡面新增一個String,名字叫做Icon,值可以是你圖標的路徑或是用imgeres.dll
這裡介紹imgeres.dll

imgeres.dll 就是一個包含各種windows常用圖標的dll檔,這邊有人很好心幫你列出所有圖標:Icons in imageres.dll

用的時候是:imageres.dll,[序號] ,我用207當範例,注意逗號後沒有空格

最後是這個選項要幹嘛,在MyOption下創一個”command”的key,這裡名稱一定是command

他的(Default)值就是要跑的指令,舉例如下:

那當我按下去的時候就會跳出explorer.exe
又或者你可以用自己的程式(路徑中有空格要加雙引號),但是需要絕對路徑,他好像只讀C:\Windows\System32

之類的,可以自己玩玩看

順帶一提,重寫過註冊碼後,不用重啟explorer,直接測試就可以

比較特殊的是檔案、資料夾對象,他會要填參數:

%1是指第1個參數,多個參數我就不知道怎麼填了

按下時複製路徑到剪貼簿

用C++寫,雖然說python可能比較好用,但效能問題還是算了

Windows中剪貼版的操作大抵如下:

  1. OpenClipboard
  2. EmptyClipboard
  3. SetClipboardData
  4. CloseClipboard

但是,這裡會用到GlobalAlloc ,這甚麼呢,我也不知道

但是有人幫我解釋了,而且我不想看:关于Clipboard和GlobalAlloc函数的关系

將文字複製到剪貼簿的程式碼長這樣的:

void writeToClipboard(std::wstring str) {
if (!OpenClipboard(NULL)) return;

EmptyClipboard();
size_t size_m = sizeof(wchar_t) * (str.length() + 1);
HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, size_m);
if (!hClipboardData) return;

wchar_t* pchData;
pchData = (wchar_t*)GlobalLock(hClipboardData);
if (!pchData) return;

wcscpy_s(pchData, str.length(), str.c_str());
GlobalUnlock(hClipboardData);

SetClipboardData(CF_UNICODETEXT, hClipboardData);
CloseClipboard();
}

所以接下來只要取得資料夾、檔案路徑就好了

全部程式碼:

#include <windows.h>
#include <locale>
#define BUFFER_SIZE 2048
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"wmainCRTStartup\"")

wchar_t path[BUFFER_SIZE];
void writePathToClipboard();

int wmain(int argc, wchar_t* argv[]) {
setlocale(LC_ALL, ".UTF8");

if (argc >= 2) {
size_t size_m = wcslen(argv[1]) + 1;
wcscpy_s(path, size_m, argv[1]);
} else {
GetCurrentDirectory(BUFFER_SIZE, path);
}

writePathToClipboard();
}

void writePathToClipboard() {
if (!OpenClipboard(NULL)) return;

EmptyClipboard();
size_t size_m = sizeof(wchar_t) * (wcslen(path) + 1);
HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, size_m);
if (!hClipboardData) return;

wchar_t* pchData;
pchData = (wchar_t*)GlobalLock(hClipboardData);
if (!pchData) return;

wcscpy_s(pchData, size_m / sizeof(wchar_t), path);
GlobalUnlock(hClipboardData);

SetClipboardData(CF_UNICODETEXT, hClipboardData);
CloseClipboard();
}

這是有Unicode支持,在搞定Unicode之前花了我超多時間,因為單純的wchar_t 是沒辦法好好展示Unicode的

所以編譯之後就丟到想要的地方,然後註冊表改一下就好

結果

我寫的註冊表

Windows Registry Editor Version 5.00

; https://medium.com/@Hyno/%E5%8F%B3%E9%8D%B5%E5%8F%96%E5%BE%97%E7%95%B6%E5%89%8D%E6%AA%94%E6%A1%88%E8%B7%AF%E5%BE%91-2fca6fc8e3d0
; by Hyno

[HKEY_CLASSES_ROOT\Directory\shell\path2clip]
@="Get Folder Path"
"Icon"="imageres.dll,241"

[HKEY_CLASSES_ROOT\Directory\shell\path2clip\command]
@="\"C:\\path\\to\\path2clip.exe\" \"%1\""

[HKEY_CLASSES_ROOT\Directory\Background\shell\path2clip]
@="Get Folder Path"
"Icon"="imageres.dll,241"

[HKEY_CLASSES_ROOT\Directory\Background\shell\path2clip\command]
@="\"C:\\path\\to\\path2clip.exe\""

[HKEY_CLASSES_ROOT\*\shell\path2clip]
"Icon"="imageres.dll,241"
@="Get File Path"

[HKEY_CLASSES_ROOT\*\shell\path2clip\command]
@="\"C:\\path\\to\\path2clip.exe\" \"%1\""

看在我這麼好心的份上多給我拍幾次手不過分吧

--

--

Hyno

隨便寫寫,把發現、作品、學習內容分享出來