2026/06/18

倉頡五代升級攻略:Win 10/11 使用者的完美解決方案 (2026 加入一鍵更換、含倉頡三代升級)

作者:吳祐賓

 

 

你使用倉頡打字的時候,有沒有感受到奇怪的味道:

* 晚上的「晚」永遠都排在第二個字

* 「卜竹竹手一」打不出「産」?而「木中中女」打不出「樓」?

 

這代表你也是微軟倉頡四代的受災戶

 

很多被倉頡四代折磨的使用者,第一直覺都是改用『微軟新倉頡』(我也是)

 

但這其實只是在繞遠路——新倉頡早已年久失修,在現代應用程式 (如底層採用 WinUI 3.0 的軟體) 中完全無法運作

 

其實,你根本不需要拋棄熟悉的習慣,只要升級一下碼表,就能讓現在的微軟倉頡脫胎換骨

 

在這裡,我想邀請你,試試看這篇的解決方案,失敗了再找微軟新倉頡也不遲

 

在學習倉頡五代後,一直覺得微軟倉頡和新倉頡的倉頡四代碼表很不友善,一直到最近看到倉頡之友的【替換微軟倉頡碼表,盡享倉頡補完計劃的樂趣】,才知道原來微軟倉頡也可以更新碼表,終於能享受到輸入文字的樂趣了!

 

首先,本篇文章適用範圍:Windows 10 2004 版以上。記得,Windows 更新有時會覆蓋原來倉頡四代的碼表,記得要再回來更新 (2026/03/18 文末追加:一鍵更換 DLC)

 

 

倉頡碼表下載點

 

下載:MSCJData_Cangjie 開頭字樣檔案

例如:

 

 

給倉頡三代的使用者 (習慣打法為:「木中田女」=樓;「戈土心」=應) 

 

倉頡三代補完計劃替換碼表下載地址:https://github.com/Arthurmcarthur/Cangjie3-Plus/releases

 

 

GitHub 上 Cangjie3 倉頡三代碼表 20230909 版本的釋出與下載頁面截圖

 

 

給倉頡五代的使用者 (習慣打法為:「木中中女」=樓;「戈人土心」=應)

 

倉頡五代補完計劃替換碼表下載地址:https://github.com/Jackchows/Cangjie5/releases

 


GitHub Jackchows/Cangjie5 專案 Releases 頁面,顯示 v4.1-beta 最新版本與更新內容

 

安裝步驟

 

  1. 任務管理器裏結束兩個Microsoft IME進程。
  2. 進入 C:\Windows\System32\zh-hk 目錄,刪除
    • ChtCangjie.sdc
    • ChtCangjie.spd
    • ChtCangjieExt.lex
    三個文件(刪除前請備份),然後將此處提供的 ChtCangjieExt.lex,複製到該目錄。




  3. 打開「包含香港增補字符集字元(HKSCS)」開關。

 

 

完成上述步驟後請重新開機,接下來就可以好好體驗倉頡五代所帶來的暢快輸入感!

 

相信更多愛用倉頡的愛好者不滿足於預設的內容。不過因為我個人沒用到進階設定,想要了解更多細節的倉頡愛好者,歡迎再閱讀補完計畫說明檔。


總結

 

使用倉頡補完計畫優點

 

  • 字碼編排最貼近符合倉頡歷代改版標準。
  • 可以使用倉頡五代輸入方式。 
  • 重難(ZX)符號輸入完整呈現。
  • 還有微軟倉頡獨門快速鍵 100% 保留,例如:
    Ctrl+, ,
    Ctrl+' 、
    Ctrl+. 。
    Ctrl+; ;
    Ctrl+Shift+; :

    `+ +
    `- -
    `/ /
    `/ 向下鍵 ÷
    `* 向下鍵 ×
    `+ 向下鍵 ±

    Ctrl+[ 【 向下鍵 「...
    Ctrl+] 】 向下鍵 」...

    Ctrl+Alt+, 叫出特殊符號表 (輸入法整合器) 

 

使用倉頡補完計畫缺點


  • Z開頭的符號碼無法使用,只能使用微軟輸入法的符號快速輸入鍵輸入。 (20220904 MSCJData 版本已解決此問題)
  • 由於微軟倉頡的排序邏輯寫死在程序中,與碼表沒有關聯。補完計畫在調整此問題已將部首、筆畫、兼容區字符移除,RIME 則無此問題

 

整體來說優點大於缺點,能暢快享受輸入文字的樂趣,在這邊分享給大家。

 

2026/03/03 附記:

為什麼我執意要使用微軟輸入法引擎?

1. PIME 容易當機 (Python 不知道為什麼就閃退) 

2. 小小輸入法在 WinUI (Win App 2.0) 是不能用的,它只能在傳統應用程式下使用

3. 其它的自由倉頡、RIME 等輸入法引擎,操作習慣都要重新熟悉,新設備也需要另外安裝。但熟悉微軟輸入法引擎下,新環境我只需要忍耐字碼位置就好,比較不會換了新設備就變智缺化 (笑)

 

 

【2026/03/19 重大更新】一鍵修復 Windows 內建倉頡(三代/五代)選字排序、補完缺字!

 


 

 

上述人工步驟在每次被 Window Update 陰了後,就很懶得重複做,於是我讓 AI 寫了批次檔來做自動更新,原始碼已在 Github 開源供各位取用

 

Github 專案網址:https://github.com/Eden5Wu/Windows-Cangjie-Updater 


三大特色

  • 自動升權:因為會修改註冊檔,所以會要求使用者提供系統管理員權限 
  • 互動式選單:官方有四款需求導向目錄,為此寫了選單,預設為「台灣優先」
  • 自動備份 :腳本會自動備份舊碼表,改壞了就換回來即可


原本是寫 bat 批次檔,但倉三和倉五來源目錄皆以中文命名,剛好又是 bat 的罩門,為避免另外說明造成你我困擾,我決定改為 PowerShell (ps1) 來處理


視 bat 為本命的愛好者,也可以在上述 Github 中下載 bat 來使用,程式碼固定為「台灣優先」,有需要再自行修改

 

 

實現一鍵安裝的倉頡更新,感覺真是太好啦!

若是哪天又被天殺的微軟「更新」蓋掉,只要再對  .ps1 檔案按右鍵 ->「用 PowerShell 執行」來安裝,3 秒鐘就修復完成!

 

真是爽快!

 

常見問題

💡 Q:執行時一閃而過,或是出現「禁止執行指令碼」的紅字報錯?

A: 這是因為 Windows 預設基於安全考量鎖定了 PowerShell 腳本執行。請照以下步驟解鎖:

  1. 按下 Win + X 鍵,選擇 「終端機 (系統管理員)」。(就是Windows PowerShell)

  2. 貼上指令:Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 並按 Enter。

  3. 輸入 Y 並按確認。

完成後再次對著腳本按「右鍵 -> 使用 PowerShell 執行」即可正常運作

 


 

2026/06/01

【踩坑】Delphi DBX 的底層幽靈:SQL Server 空字串如何引爆 Range Check Error?

作者:吳祐賓  

 

 


 

 

—— 可以理解為什麼 dbExpress 要被列 Deprecated,因為高階物件和低階抽象完全是兩個風景

 

在老系統現代化(Legacy Modernization)這條宛如「走出埃及」的路上,最恐怖的從來不是程式碼有多爛,而是在這條路上遇上問題時,無人能指引解惑。更恐怖的是,哪怕你選擇留在埃及,這些幽靈依舊存在

 

這次差點被搞到懷疑人生的經歷是:

 

專案從 DataSnap 轉向 Horse,資料透過 dbExpress (DBX) 底層與 Devart 驅動程式拉出來,準備轉成 JSON API

 

這本是走出埃及的日常,結果就在最簡單的一行判斷上,我被狠狠教做人了

 

if TDBXValue(Value).IsNull then  // ← 就在這裡直接噴 Range check error

 

而且只在特定資料庫、特定欄位上發生



黑夜降臨:案發現場的詭異症狀


問題欄位是老掉牙的 TEXT 型態,內容看起來明明是空字串
 

但只要碰到這欄位,所有常識判斷全部失效:

  • IsNull 直接爆炸
  • 改用 GetString、GetStream、GetBytes 也會收到 Devart 各種型別衝突的錯誤 (TDBXTypes.BLOB value type cannot be accessed as TDBXTypes.BYTES value type)

 

雖然這和埃及日常沒什麼區別,但那一刻我還真的有慌。這不是單純的 Null 判斷問題,而是某種更底層、更邪門的東西在作祟

 

因為,同樣的 SQL,使用 TSQLQuery / TSQLDataSet 時,完全沒有這問題啊! 

 

 

守衛睜眼 —— 查出真正的狼人

 

由於這和歷史經驗不同, 理所當然往資料庫挖

 

對出問題的資料表下了診斷 SQL:

 

SELECT 
    NotesField,
    DATALENGTH(NotesField) AS DataLen,
    TEXTPTR(NotesField) AS Ptr
FROM LegacyOrderTable
WHERE CategoryCode = 'BUG_TEST';

 

 

結果出來的那一刻,我整個人傻掉


這筆資料的狀態極度詭異:

  • DATALENGTH(NotesField) = 0
  • 但 TEXTPTR(NotesField) 居然是有效的 8 Bytes 指標(像 0xFBFFC67A... 這種)


 

原來,這根本不是什麼無辜的空資料,而是一頭「披著空字串外皮的狼」

 

這東西通常出現在很久以前的資料轉檔、批次匯入,或是老系統某些特殊的寫入行為

 

SQL Server 在行外(Out-of-row)幫它配置了 LOB 指標,但實際上什麼資料都沒塞進去。就像一具只剩下指標的空殼。 

 

 

預言家睜眼:不是追兵,是自己人崩潰 —— Devart 驅動程式的精神分裂

 

最要命的是 Devart 看到這頭「披著空字串外皮的狼」之後的處理方式

 

它偵測到有 TEXTPTR(長度 8),就很「聰明」地把這個欄位標記成 WideStringType,並且把 Size 設為 8

 

而 Delphi 這邊在準備讀取的時候,卻認為這是長度為 0 的空資料。於是在底層 DBXRow_GetBytes 裡,出現了類似這樣的致命操作:

 

PBuf := @Value[ValueOffset];  // Value 是長度 0 的陣列 → 直接 Range check error!

 

 

因為專案有開 {$R+}(範圍檢查),Delphi 非常乾脆地下殺手


這就是典型的「兩個黑盒子互相誤會,所引爆的災難現場」

 


女巫睜眼:三顆解藥


第一顆解藥:SQL 層釜底抽薪


乾淨利落,不讓 Devart Driver 看到那頭「披著空字串外皮的狼」

 

// 1. Alter Table
ALTER TABLE LegacyOrderTable
ALTER COLUMN NotesField NVARCHAR(MAX);

// 2. CAST
SELECT 
    CAST(NotesField AS NVARCHAR(MAX)) AS NotesField,
    CAST(AnotherTextField AS NVARCHAR(MAX)) AS AnotherTextField
FROM LegacyOrderTable

 

只要轉成 NVARCHAR(MAX),Devart 立刻恢復正常,不再亂認 Size = 8

 

這一招幾乎零成本,卻直接斬斷了問題根源 

 


第二顆解藥:程式碼硬控

 

動資料庫其實蠻傷及筋骨的,所以並不是一個好選擇

 

既然只是為了把資料轉成 JSON API,我們大可在轉換的迴圈裡加上防護罩,直接攔截這個怨靈:

 

try
  Result := Value.IsNull;
except
  Result := TJSONNull.Create;
end;

 

 

犧牲一點 except 效能與 Debug 的雜訊,至少 API 不會再半夜隨機暴斃

 

 

第三顆解藥:修改 Driver 原始碼 


很妙的是,Devart 不含原始碼的 DLL 版並沒有這方面的問題,我分析是 {+R} 在封裝 DLL 時被關掉了,同時也沒有吐出任何例外,這 Bug 就與世無爭地活了數十年


但不想依賴 DLL 過活的我,選擇的是含原始碼的版本

 

若你和我一樣有 Devart 的 Source Code 授權,而且真的很想把根治了,可以直接進到 DBXRow_GetBytes 之類的核心方法,加上防護: 

 

if (Value <> nil) and (System.Length(Value) > ValueOffset) then
  PBuf := @Value[ValueOffset]
else
  PBuf := nil;   // 神之一手,拯救無數 Range check error

 

這顆解藥很硬,但一旦改完,整個 Devart Driver 在面對 SQL Server 老 TEXT 時都會變得更穩

 

當然,這問題我已提交給 Devart,目前的版號是 9.5.0 版,未來可以關心之後新版的 History 有沒有相關的記錄出現 



白晝到來:傷害力不高,汙辱性極強


回到開頭說的:dbExpress 之所以被列為 Deprecated,不是沒有原因


更有趣的是,同樣使用 dbExpress,傳統的 TSQLQuery/TSQLDataSet 並未重現此問題;只有直接操作 TDBXReader/TDBXValue 時才踩中地雷。這表示高階 DataSet 與底層 DBX 抽象層在處理 LOB 欄位時,很可能走的是不同路徑。究竟是透過 Stream、額外緩衝層,還是其他容錯機制避開了這個缺陷,仍有待進一步驗證;但可以確定的是,當我直接面對 DBX 最底層抽象時,這頭狼人終於現出原形。 

 

所以:就算你不走出埃及,留在舒適圈裡,這些狼人依然會在正式環境半夜等著你


老系統的坑,從來不是一次就能填完的。它考驗的不是你會不會寫 Code,而是當所有常識都失效時,你願不願意把屍體挖出來解剖。

 

如果你也正在 DataSnap 轉 Horse、DBX 操作踩雷、或任何 Legacy Modernization 的路上,歡迎在留言區分享你的戰場故事

 

願我們一起在走出埃及的路上,相互扶持