Tommy 碎碎念

Tommy Wu's blog

« 上一篇 | 下一篇 »

讓 wscitecm.dll 支援 unicode
post by tommy @ 25 二月, 2013 11:03

不久前發現, 一直以來用來與 SciTE 搭配使用的 wscitecm.dll 在並無法處理 unicode 的路徑與檔名 (用了這麼多年才發現, 也算不容易....).

其實原本程式裡頭多數的寫法都有考量到 unicode 的問題, 所以實際改起來應該並不會太難 (不過由於改用 VS2012 來編譯, 所以 source code 也整理過了, 與原作者的版本有一些差異).

主要對於 unicode 檔名與路徑的支援與否的差異是出現在 IContextMenu::InvokeCommand() 這個函式的處理.

由於傳入的是一個指標, 就函式的定差來看, 是一個指向 CMINVOKECOMMANDINFO 這個結構的指標, 所以直接拿來使用時, 這個結構裡頭就只有包含 ANSI 的檔名與路徑, 自然無法做到 unicode 的支援. 而在 MSDN 上頭關於這個函式的說明中, 有提到,在 unicode 的環境, 那個指標實際上是一個指向 CMINVOKECOMMANDINFOEX 這個結構的指標, 裡頭除了原本的 ANSI 相關的檔名與路徑外, 還有額外儲存 unicode 版本的檔名與路徑.

我們只要先檢查 cbSize 的值, 與 fMask 是否含有 CMIC_MASK_UNICODE (在某些情形下, 雖然大小不是 CMINVOKECOMMANDINFO, 但似乎 fMask 會是 0, 所以用這個來判斷反而會有問題),來判斷這個指標實際指向的結構, 是否有支援 unicode, 如果有, 就直接 cast 成 CMINVOKECOMMANDINFOEX 的指標, 就可以得到 unicode 的檔名與路徑, 這樣就能對 context menu 加上 unicode 的支援了.

如:

STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
HRESULT hr = E_INVALIDARG;
 
if (!HIWORD(lpcmi->lpVerb)) {
UINT idCmd = LOWORD(lpcmi->lpVerb);
switch(idCmd) {
case 0:
#ifdef _UNICODE
if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO)) {
LPCMINVOKECOMMANDINFOEX lpcmiex = (LPCMINVOKECOMMANDINFOEX)lpcmi;
hr = InvokeRealCommand(lpcmiex->hwnd, lpcmiex->lpDirectoryW, lpcmiex->lpVerbW, lpcmiex->lpParametersW, lpcmiex->nShow);
}
else {
wchar_t dir[_MAX_DIR+1];
wchar_t verb[1025];
wchar_t param[1025];
 
MultiByteToWideChar(CP_ACP, 0, lpcmi->lpDirectory, -1, dir, _MAX_DIR);
MultiByteToWideChar(CP_ACP, 0, lpcmi->lpVerb, -1, verb, 1024);
MultiByteToWideChar(CP_ACP, 0, lpcmi->lpParameters, -1, param, 1024);
 
hr = InvokeRealCommand(lpcmi->hwnd, dir, verb, param, lpcmi->nShow);
}
#else
hr = InvokeRealCommand(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow);
#endif
break;
}
}
return hr;
}

當然除了這個地方外, 原本的程式有些字串並沒有加上 _T() 來處理, 型別也還是用 char, 不是 TCHAR, 把這些地方改一改後, 就會得到一個完整支援 unicode 的程式了.

產生的 dll 檔案與 source 都可以在這兒抓到: http://www.teatime.com.tw/~tommy/files/wscitecm_2.0.0.7z

安裝與移除的方法可以參考原作者的說明. 裡頭的 wscitecm.dll 是 x86 的版本 (Windows XP 或之後的版本應該都可以用). 而 wscitecm64.dll 是 x64 的版本 (應該是 Windows Vista 之後的版本都能用).

對於, 程式運作需要 msvcr110.dll, 如果你的系統沒有, 請裝上 Visual C++ Redistributable for Visual Studio 2012 就應該可以用了.

Del.icio.us Furl HEMiDEMi Technorati MyShare
迴響
暱稱:
標題:
個人網頁:
電子郵件:
迴響

  

Bad Behavior 已經阻擋了 68 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS