使用印表機裝置字型

印表機中的字型有時會很有用,而且難以在應用程式程式代碼中使用。 本文說明如何判斷哪些印表機常駐裝置字型可用於 Win32 印表機裝置內容。 本文也會說明當您嘗試在應用程式程式代碼中使用這些印表機字型時,可能會發生的幾個問題。

原始產品版本: Win32 印表機裝置
原始 KB 編號: 201978

摘要

在大部分情況下,軟體開發人員依賴操作系統來提供將用於其繪圖的字型。 若要這樣做,您可以透過應用程式開發介面 (API) 或透過通用的 [選擇字型] 對話框, 取作業系統提供的字型。 不過,應用程式通常與所使用的特定字型無關,只有它符合特定需求,而且使用者偏好該字型。 這些要求包括:

  • 字型必須是特定大小。
  • 字型必須包含字元 (也稱為字元) 。
  • 字型必須具有特定樣式。

一般而言,當應用程式列印檔時,字型 (或類似它的字型) 會在印表機上使用,而不會從應用程式執行任何特定動作。 這通常是應用程式的正確結果,而且這會以合理的速度產生良好的列印結果。

不過,有時候應用程式開發人員可能只需要從目標印表機中選取特定字型。 在過去,這對於影響類型印表機而言是必要的 (例如,點矩陣印表機) 取得特定格式或加速列印。

目前,大部分的印表機基本上都是設計為點陣裝置,而且可以在紙張的任何部分繪製點 (圖元) ,就像所有字元字元一樣有效率。 對於大部分的應用程式而言,字元圖像是從印表機常駐定義繪製為整個表單,或是繪製為操作系統提供的圖元集合,都不是問題。 不過,您可能仍然想要使用只有印表機提供的字型。 例如,這可能是因為字型是唯一的,而且操作系統中沒有類似的替代專案,或是因為您想要避免將字型定義下載到印表機的額外負荷。

裝置字型

基於本文的目的,裝置字型是其定義永久或暫時存在於印表機記憶體中的任何字型。 這些裝置字型提供字元字元定義,可由印表機的頁面點陣化工具硬體將圖形筆跡到紙張上,以針對每個字元進行尋址。

裝置字型可分類為三種基本類型:

  • True 裝置字型。 基於本文的目的,這些是只有印表機硬體提供的字型,而且您只能在印表機上使用。

  • 裝置字型替代。 存在於操作系統中的字型,以及印表機硬體也提供的字型。 在此情況下,印表機硬體可以取代操作系統的字型。

  • 可下載的字型。 操作系統所提供的字型,但其定義可以下載到印表機,並在印表機上使用,就像印表機硬體直接提供字型一樣。

可下載的字型

操作系統提供可下載的字型,也稱為軟字型。 當您列印檔時,字型的定義會在列印作業中提供。 當印表機處理列印作業時,字型定義會安裝在印表機記憶體中,讓字型定義可以墨蹟顯示在檔的列印頁面上。

有些人認為,因為印表機正在繪製字型的字元字元,所以這些字型是裝置字型。 不過,下載字型定義或透過點陣圖將圖像繪製到印表機時,只會儲存一些額外負荷或列印作業多任務緩衝處理大小。 此程式會以透明的方式對應用程式進行,讓操作系統中的字型可以在螢幕上和印表機上使用。 因為本文著重於如何使用只有印表機提供的裝置字型,所以本文不會說明如何使用可下載的字型。

裝置字型替代

當有兩個不同的字型定義時,就會發生裝置字型替代:一個是操作系統所使用的,另一個是印表機所使用的。 也就是說,應用程式會在螢幕上的檔中選取並使用作業系統中的字型。 當您列印檔時,會使用印表機所提供的類似定義字型來繪製印輸出。 因此,操作系統中的字型已在印表機上以印表機定義的字型取代。

使用通用的 Windows TrueType 字型時,通常會在 PostScript 印表機上發生這種情況。 例如,在大部分 PostScript 裝置上,通常會使用 Helvetica 字型的 PostScript 字型定義列印的 TrueType Arial 字型。 這是使用字型名稱不同之類似字型的替代範例。 在此情況下,您通常可以直接尋找並使用這個類似的字型定義,因為類似的字型定義也會公開為真正的裝置字型。 本文稍後會討論這個問題。

當印表機上的字型與操作系統提供的字型名稱相同時,也會發生裝置字型替代。 這通常會發生在印表機上,例如 Hewlett-Packard LaserJet 印表機。 這些印表機通常有自己的 Windows 核心字型版本,例如 Arial 和 Times New Roman。 雖然這些字型通常也可藉由尋找真正的裝置字型來找到,但有時無法保證其使用方式,因為印表機驅動程序經常自行選取,或是透過使用者設定選取,是否改為使用操作系統提供的字型。

True 裝置字型

True 裝置字型是印表機上只有定義的字型。 應用程式可以使用這些字型的唯一方式,是讓應用程式特別識別字型,並建立它以供印表機裝置內容使用。

如果您知道裝置的足夠資訊,您可以在結構中 LOGFONT 建立邏輯字型描述,以實現裝置字型。 特別是,請務必為 lfFacename 該成員、 lfHeight 成員和字型的字元集提供正確的資訊。 此外, lfOutPrecision 成員應該包含旗標 OUT_DEVICE_PRECIS 來影響字型對應程式,以選擇裝置字型,而不是類似命名的系統字型。

如果字型的描述未知,您可以列舉字型來探索裝置字型。 若要取得印表機支援的裝置字型清單,請使用其中一個字型列舉函式,例如 EnumFontFamiliesEx。 放入回調函式中的應用程式程式代碼可以檢查交給回調函式的數據,以判斷哪些字型實例描述裝置字型。

使用真正的裝置字型

在印表機裝置內容中使用裝置字型的程式遵循下列一般步驟:

  1. 藉由列舉印表機裝置內容中的字型來識別真實的裝置字型。
  2. 選取旗標和刪除程式所 FontType 指出的僅限裝置字型。
  3. 在對應模式中 MM_TEXT 使用印表機特定計量,以使用裝置字型正確放置繪製的文字。

列舉印表機裝置內容的字型

若要列舉裝置內容中可用的所有字型,您可以從 Win32 應用程式開發介面使用回調函式和 EnumFontFamiliesEx 函式, (API) 。 若要列舉裝置內容的所有字型,您必須呼叫 EnumFontFamiliesEx 兩次:第一次取得字型系列清單,第二次取得每個字體系列中的所有相異字型。

若要尋找印表機裝置內容上的所有裝置字型,您必須列舉印表機裝置內容的所有字型。 當每個字型傳遞至回呼函式時,會檢查字型以判斷它是否為裝置字型。 下列範例程式代碼中的 和 PrinterDeviceFontEnumPrinterDeviceFontFamiliesEnum 回調函式會執行此作業。

// Data structure to pass data through the font enumeration callbacks.
typedef struct PrintEnumFontData
{
    HDC             hPrinterDC;
    HDC             hEnumDC;
    int             curx, cury;
    ENUMLOGFONTEX   elf;
} PRINTENUMFONTDATA;

int CALLBACK PrinterDeviceFontEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    // Crack the data out of the enumeration parameter.
    PRINTENUMFONTDATA *     ppeft = (PRINTENUMFONTDATA*) lParam;

    // Printing information
    TEXTMETRIC              tm;
    HFONT                   hfont, holdfont;
    int                     pagecx, pagecy;

    // Data to determine where this font came from
    ENUMEDFONT      df = { FontType, lpelfe };  // To look for a system version

    // What is the printable area of the page?
    pagecx = GetDeviceCaps(ppeft->hPrinterDC, HORZRES);
    pagecy = GetDeviceCaps(ppeft->hPrinterDC, VERTRES);

    // Is it a device font?
    // If it is, make sure that it is also not a TrueType font because
    // that is most likely a downloaded font.
    // Also, look for any system-provided fonts that are also
    // masquerading as printer device fonts. This implies that they will be
    // downloaded to the printer as is the case with Adobe Type 1 fonts.
    // If they are downloaded, you do not want to include them in this demonstration.
    if (FontType & DEVICE_FONTTYPE &&
        !(FontType & TRUETYPE_FONTTYPE) &&
        !IsSystemFont(&df))
    {
        TCHAR           Buffer[MAX_PATH];           // description of font
        LPTSTR          szFontType;                 // description of type
        LPTSTR          pStyle = "Regular";         // Fonts Style defaults to Regular

        // At this point in this code, the lpelfe parameter has been examined
        // and found to describe a printer device font.
        // Do something interesting with it as follows:

        // Build a sample string that describes the font.
        if (lpelfe->elfLogFont.lfItalic)
        {
            pStyle = "Italic";
            if (lpelfe->elfLogFont.lfWeight > FW_NORMAL)
                pStyle = "Bold Italic";
        }
        else if (lpelfe->elfLogFont.lfWeight > FW_NORMAL)
            pStyle = "Bold";

        // Determine if the font is scalable or a bitmap font.
        if (FontType & RASTER_FONTTYPE)
            szFontType = TEXT("Bitmap Font");
        else
        {
            // This is an instance of a scalable font, 
            // use 12 pt because it is easy to read.
            szFontType = TEXT("Scalable Font");
            lpelfe->elfLogFont.lfHeight = MulDiv(12, GetDeviceCaps(ppeft->hPrinterDC, LOGPIXELSY), 72);
            lpelfe->elfLogFont.lfWidth = 0;
        }

        // Skip all fonts after this font that are the same scale as the last one.
        // However, let different sizes of 'bitmap' fonts through.
        // This is a cheat that relies on enumeration order.
        // Really, you should keep a 'used' list and compare against the list.
        if (FontType & RASTER_FONTTYPE || !CompareLogFontEx(&ppeft->elf, lpelfe))
        {

            hfont = CreateFontIndirect(&lpelfe->elfLogFont);
            holdfont = (HFONT)SelectObject(ppeft->hPrinterDC, hfont);
            GetTextMetrics(ppeft->hPrinterDC, &tm);

            // If beyond bottom of page, get a new page.
            if (pagecy < ppeft->cury + tm.tmExternalLeading + tm.tmHeight)
            {
                EndPage(ppeft->hPrinterDC);
                StartPage(ppeft->hPrinterDC);
                ppeft->cury = 0;
            }

            // Draw our sample text.
            wsprintf(Buffer, "%s %s [%s]  FontType: %s", lpelfe->elfFullName, pStyle, lpelfe->elfScript, szFontType);
            ppeft->cury += tm.tmExternalLeading;
            TextOut(ppeft->hPrinterDC, ppeft->curx, ppeft->cury, Buffer, lstrlen(Buffer));
            ppeft->cury += tm.tmHeight;

            // Clean up.
            SelectObject(ppeft->hPrinterDC, holdfont);
            DeleteObject(hfont);

            // Make a note of the font that you used so that the next time
            // this callback is called, you can skip different scales of
            // the same font.
            CopyMemory(&ppeft->elf, lpelfe, sizeof(ENUMLOGFONTEX));
        }
    }
    // Otherwise, continue enumeration without doing anything with this
    // particular font.

    return 1;
}

int CALLBACK PrinterDeviceFontFamiliesEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    PRINTENUMFONTDATA * ppeft = (PRINTENUMFONTDATA*) lParam;

    ZeroMemory(&ppeft->elf, sizeof(ppeft->elf));

    // Is it a device font?
    // If it is, make sure that it is also not a TrueType font because
    // that is most likely a downloaded font.
    if (FontType & DEVICE_FONTTYPE && !(FontType & (TRUETYPE_FONTTYPE)))
    {

        // Enumerate all of the font instances that are part of this
        // font family.
        return EnumFontFamiliesEx(ppeft->hEnumDC,
            &lpelfe->elfLogFont,
            (FONTENUMPROC)PrinterDeviceFontEnum,
            lParam,
            0);
    }

    // Otherwise, if you are not interested in this particular font, 
    // continue enumeration so that you can find more.
    return 1;
}

BOOL CALLBACK AbortProc(HDC hdc, int iError)
/*
    This minimal AbortProc implementation stops the print
    job when an error occurs.
 */
{
    if (iError)
        return FALSE;
    return TRUE;
}

BOOL PrintDeviceFontList(HDC hPrinterDC)
{
    int ret;
    LOGFONT             lf;     // Describes the start of the font enumeration
    PRINTENUMFONTDATA peft =
    {
        hPrinterDC,             // Device Context on which to print
        hPrinterDC,             // Device Context to enumerate
        0, 0,                   // Current print location
        NULL                    // Last device font that is used to print
    };
    DOCINFO di;                 // Description of the print job

    // Start the print job.
    ZeroMemory(&di, sizeof(di));
    di.cbSize = sizeof(di);
    di.lpszDocName = TEXT("Printer Font List");

    // Set a minimal AbortProc because there should always be one.
    ret = SetAbortProc(hPrinterDC, (ABORTPROC) AbortProc);
    if (ret < 1) return false;

    ret = StartDoc(hPrinterDC, &di);
    if (ret < 1) return false;

    ret = StartPage(hPrinterDC);
    if (ret < 1)
    {
        AbortDoc(hPrinterDC);
        return false;
    }

    // Enumerate everything to start, weed out non-device fonts, 
    // and then print non-device fonts during enumeration.
    ZeroMemory(&lf, sizeof(lf));
    lf.lfCharSet = DEFAULT_CHARSET;

    // Call the enumeration with your callback function that prints
    // the device fonts that it finds.
    ret = EnumFontFamiliesEx(hPrinterDC,
        &lf,
        (FONTENUMPROC)PrinterDeviceFontFamiliesEnum,
        (LPARAM)&peft,
        0);

    // The value 1 is returned by the callback functions to continue
    // the enumeration. When the enumeration completes, EnumFontFamiliesEx
    // returns the last value that the callback returns.
    // Therefore, you succeed if you get 1. Let it print.
    if (ret == 1)
    {
        EndPage(hPrinterDC);
        EndDoc(hPrinterDC);
        return true;
    }

    // Otherwise, exit because you failed somewhere in the process.
    AbortDoc(hPrinterDC);
    return false;
}

您可以在範例程式代碼 EnumFontFamiliesEx 中看到函式被呼叫兩次。 第一次呼叫是在函式中 PrintDeviceFontList 進行。 第二個呼叫是在回調函式中 PrinterDeviceFontFamiliesEnum

PrintDeviceFontList 是最上層函式。 PrintDeviceFontList 執行兩個工作的方式是在印表機裝置內容上啟動列印作業,然後叫用第一個呼叫 EnumFontFamiliesEx 來啟動字型列舉程式。 根據平臺軟體開發工具組 (SDK) 檔,當您將結構lfCharSet的成員設定LOGFONTDEFAULT_CHARSET 值時,EnumFontFamiliesEx會列舉所有字型系列。 字型列舉完成之後,程式代碼會呼叫 EndDoc 方法來完成列印作業管理工作。

PrinterDeviceFontFamiliesEnum 式會針對每個字型系列 EnumFontFamiliesEx 呼叫回調函式。 在該回調函式中,程式代碼一開始會檢測字型系列,只尋找參數所標示的 FontType 裝置字型。 它也會顯示任何標示為的 TrueType 字型,因為這些字型可能是可下載的字型。 對於被視為裝置字型的字型系列,會再次呼叫函式, EnumFontFamiliesEx 但會傳遞 ENUMLOGFONTEX 回調函式所收到的結構。 使用回呼參數作為第二個列舉函數調用的輸入參數,會導致第二個列舉列出該字體系列中的所有相異字型。

選取裝置字型

您可以使用印表機裝置字型的特定準則來區別這些字型與列舉的任何其他字型。 具體而言, DEVICE_FONTTYPE 請在回調函式的 DWORD 參數中 FontType 尋找 值。 除了 Adobe 字型) 之外,幾乎所有傳遞給具有此值集合之回調函式的字型,都是列印機裝置內容 (的裝置字型。

在範例程式代碼中 PrinterDeviceFontEnum ,回調函式是由字型系列中每個相異字型的第二個列舉所呼叫。 回 PrinterDeviceFontEnum 調函式會執行三項工作:

  • 再次使用裝置字型準則,以確保函式只會處理可辨識為裝置字型的字型。

  • 使用另一個字型列舉來搜尋字型,以查看裝置字型是否也用於系統的螢幕裝置內容中。

  • 將字型範例列印到要建立的列印作業,以示範如何使用字型。 此回檔函式會使用名為 的函式 IsSystemFont,這是下列範例程式代碼的一部分:

BOOL CompareLogFontEx(
  CONST ENUMLOGFONTEX * Destination,   // copy destination
  CONST ENUMLOGFONTEX * Source  // memory block
)
/*
    Returns true if the two ENUMLOGFONTEX buffers compare.
    Return false if the two buffers differ in someway as described by the 
    criteria below.
*/
{

    // Compare the string descriptions:
    if (lstrcmpi((LPCTSTR )Destination->elfFullName, (LPCTSTR )Source->elfFullName) != 0)
        return false;
    if (lstrcmpi((LPCTSTR )Destination->elfScript, (LPCTSTR )Source->elfScript) != 0)
        return false;
    if (lstrcmpi((LPCTSTR )Destination->elfStyle, (LPCTSTR )Source->elfStyle) != 0)
        return false;

    // Height and Width are not compared because they will change
    // based upon the device on which the font is enumerated.
    //  LONG lfHeight;
    //  LONG lfWidth;

    // Compare the LOGFONT properties:
    //  LONG lfEscapement;
    if (Destination->elfLogFont.lfEscapement != Source->elfLogFont.lfEscapement) return false;
    //  LONG lfOrientation;
    if (Destination->elfLogFont.lfOrientation != Source->elfLogFont.lfOrientation) return false;
    //  LONG lfWeight;
    if (Destination->elfLogFont.lfWeight != Source->elfLogFont.lfWeight) return false;
    //  BYTE lfItalic;
    if (Destination->elfLogFont.lfItalic != Source->elfLogFont.lfItalic) return false;
    //  BYTE lfUnderline;
    if (Destination->elfLogFont.lfUnderline != Source->elfLogFont.lfUnderline) return false;
    //  BYTE lfStrikeOut;
    if (Destination->elfLogFont.lfStrikeOut != Source->elfLogFont.lfStrikeOut) return false;
    //  BYTE lfCharSet;
    if (Destination->elfLogFont.lfCharSet != Source->elfLogFont.lfCharSet) return false;
    //  BYTE lfOutPrecision;
    if (Destination->elfLogFont.lfOutPrecision != Source->elfLogFont.lfOutPrecision) return false;
    //  BYTE lfClipPrecision;
    if (Destination->elfLogFont.lfClipPrecision != Source->elfLogFont.lfClipPrecision) return false;
    //  BYTE lfQuality;
    if (Destination->elfLogFont.lfQuality != Source->elfLogFont.lfQuality) return false;
    //  BYTE lfPitchAndFamily;
    if (Destination->elfLogFont.lfPitchAndFamily != Source->elfLogFont.lfPitchAndFamily) return false;
    //  TCHAR lfFaceName[LF_FACESIZE];
    if (lstrcmpi((LPCTSTR )Destination->elfLogFont.lfFaceName, (LPCTSTR )Source->elfLogFont.lfFaceName) != 0) return false;

    // Conclusion: the two LOGFONT enumeration buffers are comparable.
    return true;
}

typedef struct structEnumedFont
{
    DWORD FontType;
    ENUMLOGFONTEX * elfx;
} ENUMEDFONT;

int CALLBACK FindSystemFontEnum(
  ENUMLOGFONTEX *lpelfe,    // logical-font data
  NEWTEXTMETRICEX *lpntme,  // physical-font data
  DWORD FontType,           // type of font
  LPARAM lParam             // application-defined data
)
{
    ENUMEDFONT  *   pdf  = (ENUMEDFONT *)lParam;
    ENUMLOGFONTEX * lpelfeSrc = pdf->elfx;

    lpelfe->elfLogFont.lfHeight = lpelfeSrc->elfLogFont.lfHeight;
    lpelfe->elfLogFont.lfWidth = lpelfeSrc->elfLogFont.lfWidth;

if (CompareLogFontEx(lpelfeSrc, lpelfe) && FontType == pdf->FontType)
        return 0;       // System font found. Stop enumeration.
        return 1;
}

BOOL IsSystemFont(ENUMEDFONT *pdf)
/*
    Utility function that takes a font that is enumerated from a printer device
    that is in the pdf parameter and that looks for it on a Screen Device
    Context to conclude that the font passed in that came from the 
    printer is really supplied by the system.
 */
{
    HDC hScreenDC = GetDC(NULL);    // Get the screen device context.

    // If the enumeration stops by returning zero (0),
    // the font was found on the screen device context so it is a
    // system-supplied font.
    BOOL fFound = !EnumFontFamiliesEx(hScreenDC,
        &pdf->elfx->elfLogFont,
        (FONTENUMPROC)FindSystemFontEnum,
        (LPARAM)pdf,
        0);

    // Cleanup
    ReleaseDC(NULL, hScreenDC);
    return fFound;
}

根據本文中的定義,此函式會偵測標示為裝置字型但不是真實裝置字型的字型 () 。 當 Adobe 字型透過 Adobe Type Manager 或透過 Windows 2000 或 Windows XP 中存在的原生 Adobe 轉譯器安裝到系統時,就會發生這種情況。

發生這種情況時,字型實際上是系統提供的字型,會下載到印表機,有時會以 TrueType 字型發生。 可惜的是,沒有任何旗標可以跨 Windows 98、Windows 擴充版 (Me) 、Windows 2000 和 Windows XP 使用,指出字型是系統提供的 Adobe 字型,與 TrueType 字型不同 (,後者包含旗標) 。 結構ntmFlags的成員中有NEWTEXTMETRIC一個指示,但這只適用於 Windows 2000 和更新版本。 因此,程式代碼必須採用刪除程式。 當螢幕裝置內容和印表機裝置內容都提供裝置字型時 IsSystemFontdetermines ,字型就會移除。

為了避免重複的縮放字型範例,程式代碼也會在已使用候選字型時記下。 這個的特定實作取決於字型的列舉順序,以查看字型的循序列舉是相同字型但位於不同小數位數的時機。 若要移除只有不同小數字數的字型,程式代碼會使用函 CompareLogFontEx 式。

注意事項

程序設計 Windows 作業系統的檔不會指出只有縮放的字型實例會依序列舉。 程式代碼範例會使用這項技術,因為列舉是以這種方式運作,而列印頁面上的範例行數目減少不是示範程序代碼的重要功能。 如果您想要依賴排除相同字型的不同縮放比例,則必須保留所使用裝置字型的數據結構。 然後程式必須針對該數據結構檢查目前列舉的字型。

可調整與位圖字型

印表機上可以列舉兩種類型的裝置字型:

  • 點陣字型
  • 可調整的字型

點陣圖字型是具有固定大小字元字元定義的字型。 可調整的字型是印表機中具有數學型定義的字型,因此可以任意大小繪製。 換句話說,其大小會縮放。

位圖字型的傳統範例是每英吋 10 個字元 (cpi) 。 顧名思義,此字型是從打字機轉換為影響類型印表機的保留。 它稱為位圖字型,因為字型最常見的定義位於點矩陣印表機的 ROM 位圖影像中。

您可以在大部分 PostScript 印表機中找到可調整的印表機常駐字型範例,其中通常會有一組標準的 PostScript 字型,例如 Helvetica 和 Times。

無法調整的裝置字型具有在回調函式的 參數中 FontType 設定的位。 該位是由 SDK 中的符號 RASTER_FONTTYPE 表示。 FontType如果回調函式的參數沒有RASTER_FONTTYPEbit設定,則字型是可調整的字型。 如需如何判斷的範例,請參閱 PrinterDeviceFontEnum 範例程式代碼的回調函式。

繪製裝置字型

找到裝置字型的字型之後,範例會在完成列舉的印表機裝置內容中使用這些字型。 裝置字型的使用方式與其他字型非常類似,方法是使用 函式建立邏輯描述 CreateFontIndirect 。 這個函數呼叫會傳遞 LOGFONT 至字型列舉回檔函式的 。 HFONT建立 之後,會透過函數調用將它選取到裝置內容SelectObject,以用於印表機裝置內容中。

裝置字型的計量是透過 GetTextMetrics 函數調用取得。 最好使用 MM_TEXT 對應模式來操作印表機裝置內容,這是裝置內容的預設對應模式。 當您使用對 MM_TEXT 應模式時,您可以避免在其他對應模式的單元轉換程式期間可能發生的數學錯誤。

當您在印表機裝置內容中使用裝置字型時,您必須小心不要將字型和字串的計量傳輸到其他裝置內容。 特別是記憶體裝置內容也是如此。 根據定義,記憶體裝置內容不是列印作業,而是點陣圖形的暫存緩衝區,因此無法使用裝置字型。

當您使用印表機裝置字型時,還有另一個重要的考慮:您無法提供列印作業的 What-You-See-Is-What-You-Get 類型預覽。 很明顯地,位於印表機硬體中的字型無法繪製到螢幕上。 最接近預覽列印作業的是尋找系統提供的字型,該字型具有印表機裝置字型的一般特性,然後使用 ExtTextOut 函式在螢幕上繪製該字型的圖像,以模擬列印頁面上的字元字元位置。

使用裝置字型的問題

當您使用裝置字型時,可能會遇到下列問題:

  • 有裝置字型,但印表機驅動程式不會列舉它。

    列舉可用於印表機裝置內容的字型,有兩個原因無法找到裝置字型:

    • 印表機驅動程式已撰寫成因為某些原因而排除該裝置字型。
    • 印表機驅動程式會列舉字型,但參數中的 FontType 字型未正確標示為裝置字型。
  • 系統字型似乎列舉為裝置字型。

    將系統提供的字型下載到印表機時,就會發生此問題。

    當 TrueType 字型發生這種情況時,字型列舉回調函式會收到呼叫,TRUETYPE_FONTTYPE其中包含 參數上FontType設定的 和 DEVICE_FONTTYPE 位。 這會在範例程式代碼中處理,方法是不包含包含這些位組合的任何字型。

    這也會發生在系統中安裝並下載到印表機的 Adobe PostScript 字型。 區分這些字型與其他裝置字型的方法之一,是在系統螢幕裝置內容和印表機裝置內容中尋找這些字型。 如果可以同時在兩個裝置內容上列舉相同的字型,在印表機裝置內容上使用字型時,可能會將字型下載到印表機。

  • 我的印表機驅動程式會列舉數個可調整的裝置字型,但它們看起來相同,但大小除外。

    許多印表機驅動程式會以不同大小提供相同字型的數個不同實例,來列舉可調整的字型。 這會在範例程式代碼中處理,方法是比較這些字型的各種實例,這些字型假設可以使用 CompareLogFontEx 函式進行調整。

    注意事項

    FontType當回調函式的 參數具有 RASTER_FONTTYPEbit 集合時,多個列舉會針對每個大小提供不可調整字型之特定實例的描述。 每個回呼都會列舉該字型唯一可用的大小。

  • 某些印表機似乎沒有裝置字型。

    正確。 某些印表機,也就是筆跡 jet 類型印表機,不會提供裝置字型。 這些印表機完全是點陣化裝置,因此沒有印表機常駐字型定義。