早期開發者常嘗試自行解析 TrueType 字型檔(.ttf)繪製中文,但 Apple 持有 TrueType hinting 專利,FreeType 專案曾面臨法律風險。事實上,Windows 95/NT 內建完整的 Unicode 文字輸出支援,只需將多位元組字串(ANSI/CP936)轉為 Unicode(UTF-16),再呼叫 TextOutW 即可正確繪製中文,無需自行解析字型檔。
BOOL bResult = m_Font.CreateFont(
-16, 0, 0, 0, 400, 0, 0, 0,
134, // CHARSET: GB2312 (簡體中文)
3, 2, 1, 50,
"SimSun" // 字型名稱:新細明體/宋體
);
char *pText = "Test中文顯示測試Test";
wchar_t wBuffer[256];
// 1. 多位元組轉 Unicode(代碼頁 936 = GB2312)
int nLength = MultiByteToWideChar(
936, // Code Page: GB2312
MB_PRECOMPOSED, // 合成字元旗標
pText, -1, // 來源字串,-1 表以 null 結尾
wBuffer, 256 // 目標緩衝區
);
CDC *pDC = GetDC();
CFont *pFontTemp = (CFont *)pDC->SelectObject(&m_Font);
// 2. 必須呼叫 TextOutW(寬字元版),不可用 dc.TextOut()
TextOutW(pDC->m_hDC, 80, 80, wBuffer, nLength - 1); // -1 排除結尾 null
pDC->SelectObject(pFontTemp);
ReleaseDC(pDC);
簡體中文 Windows 內定代碼頁為 936(GB2312)。MultiByteToWideChar 的第一個參數必須指定正確代碼頁,才能正確將「中文 ANSI 字串」轉為 Unicode。繁體中文環境則使用 950(Big5)。
dc.TextOut() 是 MFC 封裝,內部呼叫 TextOutA(ANSI 版),會依專案字元集設定再轉換一次,導致雙重轉換錯誤。TextOutW 直接接收 wchar_t*,繞過 ANSI 層,確保 Unicode 字形正確送達 GDI。早期 Windows 95/98 若未安裝簡體中文支援,系統可能缺少 cp_936.nls。解決方法:
cp_936.nls 至 Windows\System。HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Nls\CodePage 新增 936 = "cp_936.nls"。...\Nls\Locale 新增 00000804 = "Chinese(PRC)"。現代 Windows(XP 以上)預設已內建,無需手動設定。
| 參數 | 值 | 說明 |
|---|---|---|
| 高度 | -16 | 負值表字元高度(含內部間距),單位邏輯單位 |
| CharSet | 134 | GB2312_CHARSET,指定字型字符集 |
| OutPrecision | 3 | OUT_TT_PRECIS,優先使用 TrueType 字型 |
| ClipPrecision | 2 | CLIP_DEFAULT_PRECIS |
| Quality | 1 | DEFAULT_QUALITY |
| PitchAndFamily | 50 | DEFAULT_PITCH | FF_DONTCARE |
| 現象 | 原因 | 解決 |
|---|---|---|
| 中文顯示為方框/亂碼 | 字型不支援中文或 CharSet 錯誤 | 確認字型含中文字形,CharSet=134(簡體)/136(繁體) |
| 英文正常、中文消失 | 用 TextOutA 而非 TextOutW | 強制呼叫 TextOutW,傳入 wchar_t 緩衝區 |
| MultiByteToWideChar 回傳 0 | 代碼頁未安裝或字串含無效序列 | 檢查 cp_936.nls,改用 MB_ERR_INVALID_FLAGS 除錯 |
若專案設定為「使用 Unicode 字元集」(VC++ 2005 以降預設),CString、TCHAR 皆為 wchar_t,可直接使用:
CString str = _T("Test中文測試");
pDC->TextOut(80, 80, str); // 自動呼叫 TextOutW
無需手動 MultiByteToWideChar,編譯器自動處理字面常數與字串轉換。
掌握 MultiByteToWideChar + TextOutW 的經典組合,不僅能解決舊專案相容性問題,更能深入理解 Windows 文字輸出管線的核心運作機制。