首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MFC GetGlyphOutline 取得字形輪廓:需有效 HDC 且字體選入 DC 才能運作

     編輯:程式設計疑難解答

問題現象

在 CTextDialog::GetOutline() 中呼叫 GetGlyphOutline,SelectObject 字體後失敗,疑似 DC 權限問題。

核心修正點

1. 必須使用螢幕 DC 或相容 DC,不可用按鈕控制項 DC

// 錯誤:按鈕 DC 可能無字體支援、裁剪區異常
CWnd* pWnd = GetDlgItem(IDC_BUTTON);
CDC* pDC = pWnd->GetDC();  // 不穩定

// 正確:建立記憶體 DC,相容螢幕
CClientDC screenDC(this);  // 或 CWindowDC
CDC memDC;
memDC.CreateCompatibleDC(&screenDC);

2. 字體建立與選入順序

LOGFONT lf = {0};
_tcscpy_s(lf.lfFaceName, _T("微軟正黑體")); // 字體名稱
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = -MulDiv(18, screenDC.GetDeviceCaps(LOGPIXELSY), 72); // 18 pt

CFont font;
font.CreateFontIndirect(&lf);

CFont* pOldFont = memDC.SelectObject(&font);  // 必須選入 DC
// 此時 memDC 擁有正確字體,可呼叫 GetGlyphOutline
// ...
memDC.SelectObject(pOldFont); // 恢復

3. GetGlyphOutline 正確呼叫

GLYPHMETRICS gm = {0};
MAT2 mat2 = {{0,1},{0,0},{0,0},{0,1}}; // 單位矩陣
DWORD size = GetGlyphOutline(memDC.m_hDC, 'A', GGO_NATIVE, &gm, 0, NULL, &mat2);
if (size == GDI_ERROR) { /* 處理錯誤 */ }

std::vector buffer(size);
GetGlyphOutline(memDC.m_hDC, 'A', GGO_NATIVE, &gm, size, buffer.data(), &mat2);
// buffer 即為輪廓資料 (TTPOLYGONHEADER 串列)

4. 完整可運作範例

void CTextDialog::GetOutline() {
    CClientDC screenDC(this);
    CDC memDC;
    memDC.CreateCompatibleDC(&screenDC);

    LOGFONT lf = {0};
    _tcscpy_s(lf.lfFaceName, _T("微軟正黑體"));
    lf.lfHeight = -MulDiv(18, screenDC.GetDeviceCaps(LOGPIXELSY), 72);

    CFont font;
    font.CreateFontIndirect(&lf);
    CFont* pOldFont = memDC.SelectObject(&font);

    // 取得字形 '中' 的輪廓
    GLYPHMETRICS gm = {0};
    MAT2 mat2 = {{0,1},{0,0},{0,0},{0,1}};
    DWORD size = GetGlyphOutline(memDC.m_hDC, _T('中'), GGO_NATIVE, &gm, 0, NULL, &mat2);
    if (size != GDI_ERROR) {
        std::vector buf(size);
        GetGlyphOutline(memDC.m_hDC, _T('中'), GGO_NATIVE, &gm, size, buf.data(), &mat2);
        // 解析 TTPOLYGONHEADER -> TTPOLYCURVE -> 點座標...
    }

    memDC.SelectObject(pOldFont);
}

常見坑

問題解決
GetGlyphOutline 回傳 GDI_ERROR字體未正確選入 DC、字元不在字體表、DC 不支援
輪廓座標偏移gm.gmCellIncX, gm.gmBlackBoxX/Y 為進位寬高,需配合 gm.gmptGlyphOrigin 計算實際座標
中文字形無輪廓確認字體支援該字元 (如「微軟正黑體」支援常用中文)

總結

GetGlyphOutline 需要**有效的 HDC 且已選入目標字體**。請使用 CClientDC + CreateCompatibleDC 建立記憶體 DC,建立 CFont 並 SelectObject 後再呼叫。按鈕控制項 DC 不穩定,不可用於字形查詢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved