プリンター デバイス フォントを使用する

プリンターにあるフォントは、アプリケーション プログラム コードで使用するのが便利で困難な場合があります。 この記事では、Win32 プリンター デバイス コンテキストで使用できるプリンター常駐デバイス フォントを決定する方法について説明します。 また、この記事では、アプリケーション コードでこれらのプリンター フォントを使用しようとしたときに発生する可能性があるいくつかの問題についても説明します。

元の製品バージョン: Win32 プリンター デバイス
元の KB 番号: 201978

概要

ほとんどの場合、ソフトウェア開発者はオペレーティング システムに依存して、描画に使用されるフォントを提供します。 これを行うには、アプリケーション プログラミング インターフェイス (API) または一般的な [フォントの選択] ダイアログ ボックスを使用して、オペレーティング システムが提供する フォントを選択 できます。 ただし、アプリケーションは通常、使用される特定のフォントに関係なく、特定の要件を満たし、ユーザーがフォントを好むだけです。 重要な要件は次のとおりです:

  • フォントは特定のサイズにする必要があります。
  • フォントには文字 (グリフと呼ばれる) が含まれている必要があります。
  • フォントには特定のスタイルが必要です。

通常、アプリケーションがドキュメントを印刷するときに、アプリケーションから特定の操作を行わずに、プリンターでフォント (またはそれに似たフォント) が使用されます。 これは通常、アプリケーションにとって正しい結果であり、適切な速度で良好な印刷結果が生成されます。

ただし、アプリケーション開発者がターゲット プリンターから特定のフォントのみを選択しなければならない場合があります。 従来、これは、特定の書式設定を取得したり、印刷を高速化したりするために、影響型プリンター (ドット マトリックス プリンターなど) で必要でした。

現在、ほとんどのプリンターは基本的にラスター デバイスとして設計されており、すべての文字グリフと同じくらい効率的に紙の任意の部分にドット (ピクセル) を描画できます。 ほとんどのアプリケーションでは、文字グリフをプリンター常駐定義からフォーム全体として描画するか、オペレーティング システムが提供するピクセルのコレクションとして描画しても問題ありません。 ただし、プリンターのみが提供するフォントを引き続き使用できます。 たとえば、これは、フォントが一意であり、オペレーティング システムで同様の代替品がないため、またはプリンターにフォント定義をダウンロードするオーバーヘッドを回避したい場合に発生する可能性があります。

デバイス フォント

この記事の目的上、デバイス フォントは、プリンターのメモリ内に永続的または一時的に定義が存在するフォントです。 これらのデバイス フォントは、プリンターのページ ラスタライザー ハードウェアによって文字ごとにアドレス指定できる文字グリフ定義を提供し、図形を用紙にインクします。

デバイス フォントは、次の 3 つの基本的な種類に分類できます。

  • True デバイス フォント。 この記事の目的上、これらはプリンター ハードウェアのみが提供するフォントであり、プリンターでのみ使用できます。

  • デバイスのフォント置換。 オペレーティング システムに存在し、プリンター ハードウェアにも用意されているフォント。 この場合、プリンター ハードウェアはオペレーティング システムのフォントに置き換えることができます。

  • ダウンロード可能なフォント。 オペレーティング システムが提供するが、その定義をプリンターにダウンロードし、プリンター ハードウェアが直接フォントを提供したかのようにプリンターで使用できるフォント。

ダウンロード可能なフォント

オペレーティング システムは、ダウンロード可能なフォントを提供します。これはソフト フォントとも呼ばれます。 文書を印刷すると、フォントの定義が印刷ジョブの一部として提供されます。 プリンターが印刷ジョブを処理すると、フォント定義がプリンター メモリにインストールされ、文書の印刷ページにフォント定義をインクできます。

プリンターがフォントの文字グリフを描画しているため、これらのフォントはデバイス フォントであると主張する人もいます。 ただし、フォント定義がダウンロードされたとき、またはビットマップを介してグリフがプリンターに描画されると、一部のオーバーヘッドまたは印刷ジョブのスプール・サイズのみが保存されます。 このプロセスは、オペレーティング システム内のフォントを画面とプリンターで使用できるように、アプリケーションに対して透過的に実行されます。 この記事では、プリンターのみが提供するデバイス フォントの使用方法に焦点を当てているため、この記事ではダウンロード可能なフォントの使用方法について説明しません。

デバイスフォントの置換

デバイスのフォント置換は、オペレーティング システムで使用されるフォント定義とプリンターで使用される 2 つの異なるフォント定義がある場合に発生します。 つまり、アプリケーションは、画面上のドキュメントのオペレーティング システムでフォントを選択して使用します。 文書を印刷すると、プリンターが提供する同様に定義されたフォントを使用して、印刷された出力が描画されます。 そのため、オペレーティング システムのフォントはプリンターでプリンター定義フォントに置き換えられます。

これは通常、一般的な Windows TrueType フォントが使用されている場合、PostScript プリンターで発生します。 この例としては、通常、ほとんどの PostScript デバイスで Helvetica フォントの PostScript フォント定義を使用して印刷される TrueType Arial フォントがあります。 これは、フォント名が異なる同様のフォントを使用した置換の例です。 この場合、同様のフォント定義も真のデバイス フォントとして公開されているため、通常、この類似のフォント定義を直接見つけて使用できます。 これについては、この記事の後半で説明します。

デバイスのフォント置換は、プリンターのフォントがオペレーティング システムが提供するフォントと同じ名前を持つ場合にも発生します。 これは通常、Hewlett-Packard LaserJet プリンターなどのプリンターで発生します。 通常、これらのプリンターには、Arial や Times New Roman などの Windows コア フォントの独自のバージョンがあります。 これらのフォントは、通常、実際のデバイス フォントを探すことによっても見つかりますが、プリンター ドライバーが頻繁に単独で選択するか、オペレーティング システムが提供するフォントを使用するかどうかをユーザー設定で選択するため、その使用を保証できない場合があります。

True デバイス フォント

True デバイス フォントは、プリンター上の定義のみを持つフォントです。 アプリケーションでこれらのフォントを使用できる唯一の方法は、アプリケーションがフォントを具体的に識別し、プリンター デバイス コンテキストで使用するために作成することです。

デバイスに関する十分な情報がわかっている場合は、デバイス フォントを実現する構造で LOGFONT 論理フォントの説明を作成できます。 特に、メンバー、メンバー、およびフォントの lfFacename 文字セットに対して lfHeight 正しい情報を提供することが重要です。 また、メンバーには lfOutPrecision 、フォント マッピング プロセスに影響を与えるフラグを含め OUT_DEVICE_PRECIS 、同様の名前のシステム フォントではなくデバイス フォントを選択する必要があります。

フォントの説明が不明な場合は、フォントを列挙してデバイス フォントを検出できます。 プリンターでサポートされているデバイス フォントの一覧を取得するには、 などの EnumFontFamiliesExフォント列挙関数のいずれかを使用します。 コールバック関数に配置されたアプリケーション コードは、コールバック関数に渡されるデータを調べて、デバイス フォントを記述するフォント インスタンスを決定できます。

真のデバイス フォントを使用する

プリンター デバイス コンテキストでデバイス フォントを使用するプロセスは、次の一般的な手順に従います。

  1. プリンター デバイス コンテキストのフォントの列挙によって、実際のデバイス フォントを識別します。
  2. フラグと削除プロセスによって示されるデバイス専用の FontType フォントを選択します。
  3. マッピング モードでプリンター固有のメトリックを MM_TEXT 使用して、デバイス フォントを使用して描画されるテキストを正確に配置します。

プリンター デバイス コンテキストのフォントを列挙する

デバイス コンテキストで使用可能なすべてのフォントを列挙するには、コールバック関数と EnumFontFamiliesEx Win32 アプリケーション プログラミング インターフェイス (API) の関数を使用できます。 デバイス コンテキストのすべてのフォントを列挙するには、2 回を呼び出す EnumFontFamiliesEx 必要があります。最初にフォント ファミリの一覧を取得し、2 回目は各フォント ファミリにあるすべての個別のフォントを取得します。

プリンター デバイス コンテキスト上のすべてのデバイス フォントを検索するには、プリンター デバイス コンテキストのすべてのフォントを列挙する必要があります。 各フォントがコールバック関数に渡されると、フォントが検査され、デバイス フォントであるかどうかを判断します。 次の PrinterDeviceFontEnum サンプル コードの および PrinterDeviceFontFamiliesEnum コールバック関数は、この操作を実行します。

// 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 2 回呼び出されるサンプル コードで確認できます。 最初の呼び出しは 関数で PrintDeviceFontList 行われます。 2 番目の呼び出しはコールバック関数にあります PrinterDeviceFontFamiliesEnum

PrintDeviceFontList は最上位の関数です。 PrintDeviceFontList は、プリンター デバイス コンテキストで印刷ジョブを開始してから、最初の呼び出しを呼び EnumFontFamiliesEx 出してフォント列挙プロセスを開始することで、2 つのタスクを実行します。 プラットフォーム ソフトウェア開発キット (SDK) のドキュメントに従って、構造体のメンバーをLOGFONT値にDEFAULT_CHARSET設定すると、EnumFontFamiliesExすべてのフォント ファミリが列挙lfCharSetされます。 フォント列挙が完了すると、コードは メソッドを呼び出して印刷ジョブ管理タスクを EndDoc 完了します。

PrinterDeviceFontFamiliesEnumコールバック関数は、 関数によってEnumFontFamiliesExフォント ファミリごとに呼び出されます。 そのコールバック関数では、コードは最初にフォント ファミリをスクリーンして、 パラメーターによって FontType マークされたデバイス フォントのみを検索します。 また、これらのフォントはダウンロード可能なフォントである可能性が高いため、として TrueType マークされているフォントも画面に表示されます。 デバイス フォントと見なされるフォント ファミリの場合、 EnumFontFamiliesEx 関数は再び呼び出されますが、コールバック関数が受け取った構造体が渡されます ENUMLOGFONTEX 。 コールバック パラメーターを 2 番目の列挙関数呼び出しの入力パラメーターとして使用すると、2 番目の列挙体はそのフォント ファミリ内のすべての個別のフォントを一覧表示します。

デバイス フォントを選択する

プリンター デバイス フォントの特定の条件を使用して、これらのフォントを列挙されている他のフォントと区別できます。 具体的には、コールバック関数の DEVICE_FONTTYPE DWORD パラメーターの FontType 値を探します。 この値が設定されたコールバック関数に渡されるほとんどのフォントは、プリンター デバイス コンテキストのデバイス フォントです (Adobe フォントを除く)。

サンプル コードでは、コールバック関数は、 PrinterDeviceFontEnum フォント ファミリ内の個別のフォントごとに 2 番目の列挙によって呼び出されます。 コールバック関数は PrinterDeviceFontEnum 、次の 3 つのタスクを実行します。

  • デバイス フォントの条件をもう一度使用して、関数がデバイス フォントとして認識されるフォントのみを処理することを確認します。

  • 別のフォント列挙を使用してフォントを検索し、デバイス フォントがシステムの画面デバイス コンテキストでも使用されているかどうかを確認します。

  • フォントの使用を示すために作成されている印刷ジョブにフォントのサンプルを印刷します。 このコールバック関数は、 という名前 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 Type Manager または Windows 2000 または Windows XP に存在するネイティブ Adobe ラスタライザーを使用して、Adobe フォントがシステムにインストールされている場合に発生します。

これが発生した場合、フォントは実際にはシステム提供のフォントであり、プリンターにダウンロードされます。これは TrueType フォントで発生することがあります。 残念ながら、Windows 98、Windows ミレニアム エディション (Me)、Windows 2000、および Windows XP で使用できるフラグはありません。これは、フォントが (フラグを含む TrueType フォントとは異なり) システムが提供する Adobe フォントであることを示します。 構造体ntmFlagsのメンバーにはNEWTEXTMETRIC表示がありますが、これは Windows 2000 以降でのみ使用できます。 したがって、コードは削除のプロセスに頼る必要があります。 デバイス フォントが画面デバイス コンテキストとプリンター デバイス コンテキストの両方によって提供されると IsSystemFontdetermines 、フォントは削除されます。

スケーリングするフォントの繰り返しのサンプルを回避するために、候補のフォントが既に使用されている場合もコードによってメモされます。 この特定の実装は、フォントの列挙順序に依存して、フォントの連続した列挙体が同じフォントで、スケールが異なるかどうかを確認します。 スケールが異なるフォントを削除するために、コードでは 関数を使用します CompareLogFontEx

注:

Windows オペレーティング システムのプログラミングに関するドキュメントでは、スケールによってのみ異なるフォント インスタンスが順番に列挙されるとは記載されていません。 この方法で動作する列挙型が見られたため、コード サンプルではこの手法が使用されます。また、印刷されたページ上のサンプル 行の数を減らすことは、デモ コードの重要な機能ではありません。 同じフォントの異なるスケールを排除することに依存する場合は、使用されるデバイス フォントのデータ構造を保持する必要があります。 その後、プログラムは、そのデータ構造に対して現在列挙されているフォントをチェックする必要があります。

スケーラブルなフォントとビットマップ フォント

プリンターで列挙できるデバイス フォントには、次の 2 種類があります。

  • ビットマップフォントまたはラスター フォント
  • スケーラブルなフォント

ビットマップ フォントは、固定サイズの文字グリフ定義を持つフォントです。 スケーラブルなフォントは、任意のサイズで描画できるように、プリンターで数学ベースの定義を持つフォントです。 つまり、サイズスケールです。

ビットマップ フォントの従来の例は、Courier 10 文字/インチ (cpi) です。 名前が示すように、このフォントはタイプライターからインパクトタイププリンターへの切り替えからのホールドオーバーです。 フォントの最も一般的な定義は、ドット マトリックス プリンターの ROM ビットマップ イメージにあったため、ビットマップ フォントと呼ばれます。

スケーラブルなプリンター常駐フォントの例は、通常、Helvetica や Times などの標準の PostScript フォントセットがあるほとんどの PostScript プリンターで見つけることができます。

スケーラブルではないデバイス フォントには、コールバック関数のパラメーターに FontType 設定されているビットがあります。 そのビットは、SDK のシンボル RASTER_FONTTYPE によって表されます。 コールバック関数の FontType パラメーターに 設定されていない RASTER_FONTTYPEbit 場合、フォントはスケーラブルなフォントです。 これを確認する方法の例については、サンプル コードの PrinterDeviceFontEnum コールバック関数を参照してください。

デバイス フォントを描画する

デバイス フォントであるフォントが見つかった後、サンプルでは、列挙が行われたプリンター デバイス コンテキストでそれらを使用します。 デバイス フォントは、関数を使用して論理説明を作成することで、他のフォントと同様に CreateFontIndirect 使用されます。 この関数呼び出しは、フォント列挙コールバック関数に渡された を渡 LOGFONT されます。 HFONTが作成された後、関数呼び出しでデバイス コンテキストに選択することで、プリンター デバイス コンテキストで使用されますSelectObject

デバイス フォントのメトリックは、関数呼び出しによって GetTextMetrics 取得されます。 デバイス コンテキストの既定のマッピング モードであるマッピング モードを MM_TEXT 使用して、プリンター デバイス コンテキストを操作することをお勧めします。 マッピング モードを使用すると、他の MM_TEXT マッピング モードの単位変換プロセス中に発生する可能性がある数学的エラーを回避できます。

プリンター デバイス コンテキストでデバイス フォントを使用する場合は、フォントと文字列のメトリックを他のデバイス コンテキストに転送しないように注意する必要があります。 これは、特にメモリ デバイス コンテキストに当てはまります。 定義上、メモリ デバイス コンテキストは印刷ジョブではありませんが、ラスター グラフィックスの一時的なメモリ バッファーであるため、デバイス フォントを使用できません。

プリンター デバイス フォントを使用する場合には、もう 1 つの重要な考慮事項があります。印刷ジョブの What-You-See-Is-What-You-Get 型プレビューを提供することはできません。 明らかに、プリンター ハードウェアに存在するフォントを画面に描画することはできません。 印刷ジョブのプレビューに最も近いのは、プリンター デバイス フォントの一般的な特性を持つシステム提供のフォントを見つけ、そのフォントのグリフを画面に描画する関数を使用して ExtTextOut 、印刷ページ上の文字グリフの配置をシミュレートすることです。

デバイス フォントの使用に関する問題

デバイス フォントを使用すると、次の問題が発生する可能性があります。

  • デバイス フォントはありますが、プリンター ドライバーでは列挙されません。

    プリンター デバイス コンテキストで使用できるフォントを列挙すると、デバイス フォントが見つからない理由は 2 つあります。

    • プリンター ドライバーは、何らかの理由でそのデバイス フォントを除外するように記述されました。
    • プリンター ドライバーはフォントを列挙しますが、フォントがデバイス フォントとしてパラメーターで FontType 正しくマークされていません。
  • デバイス フォントとして列挙するように見えるシステム フォントがあります。

    この問題は、システム指定のフォントがプリンターにダウンロードされるときに発生します。

    TrueType フォントでこれが発生すると、フォント列挙コールバック関数は、 パラメーターに TRUETYPE_FONTTYPE ビットが設定された と の DEVICE_FONTTYPE 呼び出しを FontType 受け取ります。 これは、これらのビットの組み合わせを含むフォントを含めないようにして、サンプル コードで処理されます。

    これは、プリンターにダウンロードされるシステムにインストールされている Adobe PostScript フォントでも発生します。 これらのフォントを他のデバイス フォントと区別する 1 つの方法は、システム画面デバイス コンテキストとプリンター デバイス コンテキストの両方でそれらを検索することです。 両方のデバイス コンテキストで同じフォントを列挙できる場合、フォントはプリンター デバイス コンテキストで使用されるときにプリンターにダウンロードされる可能性があります。

  • プリンター ドライバーは、いくつかのスケーラブルなデバイス フォントを列挙しますが、サイズ以外は同じのように見えます。

    多くのプリンター ドライバーは、サイズが異なる同じフォントの複数の異なるインスタンスを提供することで、スケーラブルなフォントを列挙します。 これは、関数を使用 CompareLogFontEx してスケーラブルであると推定されるフォントのさまざまなインスタンスを比較することで、サンプル コードで処理されます。

    注:

    コールバック関数の FontType パラメーターに が設定されている場合、複数の列挙型は RASTER_FONTTYPEbit 、サイズごとにスケーラブルではないフォントの特定のインスタンスの説明を提供します。 各コールバックは、そのフォントが使用可能な唯一のサイズを列挙します。

  • 一部のプリンターには、デバイス フォントがないようです。

    これは正しいです。 一部のプリンター (つまり、インク ジェットタイプのプリンター) には、デバイス フォントが用意されていません。 これらのプリンターは厳密にはラスター デバイスであるため、プリンター常駐フォント定義はありません。