首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

《VC++技術內幕》學習筆記(八):色彩與字體 — RGB/COLORREF、CFont::CreateFont 21 參數詳解、可縮放字體繪製實戰

     編輯:VC++

Day 8 核心主題:色彩與字體

色彩模型:從 16 色到真彩色

  • 標準 VGA:8 位調色板寄存器 → 262,144 種色彩 (6-bit RGB),但視訊記憶體限制僅能同時顯示 16 色 (4-bit 索引)。
  • 現代顯示卡:24/32 位真彩色 (1677 萬色),RGB(r,g,b) 宏將 8-bit R/G/B 合成為 32-bit COLORREF (0x00BBGGRR)。
  • CDC::SetTextColor/SetBkColor 接受 COLORREF;若裝置不支援該色彩,系統自動**抖動**或**映射到最近純色**。

色彩實戰:自定義文字前景/背景

void CMyView::OnDraw(CDC* pDC) {
    pDC->SetBkColor(RGB(255, 0, 0));       // 紅色背景
    pDC->SetTextColor(RGB(198, 198, 198)); // 淺灰文字
    pDC->TextOut(10, 10, "雷神祝大家在新的一年萬事如意!");
}

字體:GDI 物件中的「變形金剛」

  • 字體同樣是 CGdiObject 派生類,支援縮放、裁剪、選入 DC、釋放刪除。
  • CFont::CreateFont **21 參數** — 史上最長構造函數,逐一解析:

參數 15-21 為保留/內部用,通常傳 0/NULL。

可縮放字體繪製完整實戰 (MM_ANISOTROPIC + Twips)

目標

在視窗縮放時,文字**保持物理尺寸不變** (如 12pt 永遠是 12pt),而非像素級縮放。

核心代碼

// 1. OnPrepareDC — 設定 Twips 映射模式 (1 邏輯單位 = 1/1440 英吋)
void CMyView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) {
    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetWindowExt(1440, 1440); // 邏輯單位 = 1 twip
    // 視口範圍 = 每邏輯英寸的像素數 (GetDeviceCaps)
    pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),
                        -pDC->GetDeviceCaps(LOGPIXELSY)); // 負號翻轉 Y 軸
}

// 2. 輔助函數:繪製指定磅值文字
void CMyView::ShowFont(CDC* pDC, int& nPos, int nPoints) {
    TEXTMETRIC tm;
    CFont font;
    // 創建字體:高度 = -nPoints * 20 (twips)
    font.CreateFont(-nPoints * 20, 0, 0, 0, 400, FALSE, FALSE, 0,
                    ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                    DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, "Tahoma");

    CFont* pOldFont = pDC->SelectObject(&font);
    pDC->GetTextMetrics(&tm); // 獲取字體度量

    CString str;
    str.Format("%d磅 WINDOWS 中文字體範例 1234567890", nPoints);
    CSize size = pDC->GetTextExtent(str);

    pDC->TextOut(0, nPos, str); // nPos 為邏輯座標 Y 位置 (twips)

    pDC->SelectObject(pOldFont); // 還原字體

    // 更新下一行 Y 位置:字體高度 + 外部導行
    nPos -= tm.tmHeight + tm.tmExternalLeading;
}

// 3. OnDraw — 循環繪製 12pt 到 24pt
void CMyView::OnDraw(CDC* pDC) {
    int nPos = 0;
    for (int i = 12; i <= 24; i += 2) {
        ShowFont(pDC, nPos, i);
    }
}

關鍵點解析

  1. MM_ANISOTROPIC + SetWindowExt(1440,1440) + SetViewportExt(LOGPIXELSX, -LOGPIXELSY) 建立 **1 邏輯單位 = 1 twip** 的映射,與印表機單位一致。
  2. CreateFont 高度參數用 **負值** (-nPoints * 20) 表示「字符高度」(不含內部導行),符合排版標準。
  3. TEXTMETRIC 提供 tmHeight (字體高度)、tmExternalLeading (行間距) 等度量,用於精確換行定位。
  4. 視窗縮放時,OnPrepareDC 重新計算 SetViewportExt,文字物理尺寸自動保持不變。

字體度量結構 TEXTMETRIC 速查

typedef struct tagTEXTMETRIC {
    int tmHeight;          // 字體高度 (含內部導行)
    int tmAscent;          // 基線以上高度
    int tmDescent;         // 基線以下高度
    int tmInternalLeading; // 內部導行 (重音符空間)
    int tmExternalLeading; // 外部導行 (行間距建議值)
    int tmAveCharWidth;    // 平均字符寬度
    int tmMaxCharWidth;    // 最大字符寬度
    int tmWeight;          // 粗細
    BYTE tmItalic;         // 斜體標誌
    BYTE tmUnderlined;     // 下劃線標誌
    BYTE tmStruckOut;      // 刪除線標誌
    BYTE tmFirstChar;      // 首字符
    BYTE tmLastChar;       // 末字符
    BYTE tmDefaultChar;    // 預設字符
    BYTE tmBreakChar;      // 換行字符
    BYTE tmPitchAndFamily; // 間距與家族
    BYTE tmCharSet;        // 字符集
    int tmOverhang;        // 合成粗體/斜體額外寬度
    int tmDigitizedAspectX; // 水平縱橫比
    int tmDigitizedAspectY; // 垂直縱橫比
} TEXTMETRIC;

雷神心法:字體選擇指南

  • **UI 介面**:「微軟正黑體」 (Win7+)、"Microsoft YaHei" (Vista+)、"Segoe UI" (Win10+) — 系統預裝、渲染優化、支援 ClearType。
  • **程式碼編輯/終端機**:「Consolas」、「Cascadia Code」、「Fira Code」 — 等寬、連字符支援、可讀性強。
  • **列印/報表**:「Times New Roman」、「標楷體」 — 經典襯線/無襯線,列印效果穩定。
  • **跨平台/嵌入式**:嵌入 TTF 字體檔案 (用 AddFontResourceEx 載入),避免系統缺字。
    (MFC 中用 CFont::CreateFontIndirect + LOGFONT 結構更靈活)。

下一篇預告

Day 9:模態對話框與通用控件 (上) — 資源編輯器設計對話框、ClassWizard 綁定變數/消息、DDX/DDV 機制、體育彩票選號器完整實戰 (隨機數種子、去重、排序、UpdateData)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
參數名稱說明常用值
1nHeight字體高度 (邏輯單位),負值 = 字符高度 (不含內部導行),正值 = 字符盒高度-nPoints * 20 (twips 轉換)
2nWidth平均字符寬度,0 = 自動按比例0
3nEscapement字符基線與水平軸夾角 (0.1 度單位)0
4nOrientation字符盒與水平軸夾角,通常同 nEscapement0
5nWeight粗細 (0-1000),400=Normal, 700=Bold400 / 700
6bItalic斜體TRUE/FALSE
7bUnderline下劃線TRUE/FALSE
8cStrikeOut刪除線TRUE/FALSE
9nCharSet字符集ANSI_CHARSET / DEFAULT_CHARSET / GB2312_CHARSET
10nOutPrecision輸出精度OUT_DEFAULT_PRECIS / OUT_TT_PRECIS
11nClipPrecision裁剪精度CLIP_DEFAULT_PRECIS
12nQuality輸出品質DEFAULT_QUALITY / PROOF_QUALITY / CLEARTYPE_QUALITY
13nPitchAndFamily間距與字體家族DEFAULT_PITCH | FF_ROMAN / FF_SWISS / FF_MODERN
14lpszFace字體名稱 (如 "Tahoma", "微軟正黑體", "Consolas")字串指針