Yazıcı cihazı yazı tiplerini kullanma

Yazıcılardaki yazı tipleri bazen kullanışlı olabilir ve uygulama programı kodunda kullanılması zor olabilir. Bu makalede, Win32 yazıcı cihazı bağlamında hangi yazıcıda yerleşik cihaz yazı tiplerinin kullanılabilmesinin nasıl sağlandığı açıklanır. Makalede, bu yazıcı yazı tiplerini uygulama kodunda kullanmaya çalıştığınızda karşılaşabileceğiniz çeşitli sorunlar da açıklanmaktadır.

Orijinal ürün sürümü: Win32 yazıcı cihazı
Özgün KB numarası: 201978

Özet

Çoğu durumda, yazılım geliştiricisi çizimi için kullanılacak yazı tiplerini sağlamak için işletim sistemine dayanır. Bunu yapmak için, uygulama programlama arabirimi (API) veya ortak Yazı Tipi Seç iletişim kutusu aracılığıyla işletim sistemi tarafından sağlanan yazı tipini seçebilirsiniz. Ancak, uygulama genellikle kullanılan belirli yazı tipiyle ilgilenmez, yalnızca belirli gereksinimleri karşılar ve kullanıcı yazı tipini tercih eder. Bu gereksinimler şunlardır:

  • Yazı tipi belirli bir boyutta olmalıdır.
  • Yazı tipi karakter içermelidir (aksi takdirde glif olarak bilinir).
  • Yazı tipinin belirli bir stili olmalıdır.

Genellikle, uygulama belgeyi yazdırdığında, yazı tipi (veya buna benzeyen bir yazı tipi) uygulamadan herhangi bir eylem olmadan yazıcıda kullanılır. Bu genellikle uygulama için doğru sonuç olur ve makul hızlarda iyi yazdırılmış sonuçlar üretir.

Ancak bazen bir uygulama geliştiricinin hedef yazıcıdan yalnızca belirli bir yazı tipini seçmesi gerekebilir. Geçmişte, bu belirli biçimlendirmeyi elde etmek veya yazdırmayı hızlandırmak için etki türündeki yazıcılarda (örneğin noktalı matrisli yazıcılar) gerekliydi.

Günümüzde çoğu yazıcı temel olarak raster cihazlar olarak tasarlanmıştır ve kağıdın herhangi bir bölümüne bir karakter karakteri kadar verimli bir şekilde nokta (piksel) çizebilir. Çoğu uygulama için, karakter karakterinin yazıcıda yerleşik bir tanımdan bir bütün olarak çizilip çizildiği veya işletim sisteminin sağladığı piksel koleksiyonu olarak çizilip çizildiği bir sorun değildir. Ancak, yine de yalnızca yazıcının sağladığı bir yazı tipi kullanmak isteyebilirsiniz. Örneğin, bu durum yazı tipinin benzersiz olması ve işletim sisteminde benzer bir ikame olmaması veya yazıcıya yazı tipi tanımı indirme yükünden kaçınmak istemeniz olabilir.

Cihaz yazı tipleri

Bu makalenin amaçları doğrultusunda cihaz yazı tipleri, tanımı kalıcı veya geçici olarak yazıcının belleğinde bulunan tüm yazı tipleridir. Bu cihaz yazı tipleri, şekli kağıda mürekkeple eklemek için yazıcının sayfa tarama donanımı tarafından karakter başına adreslenebilen bir karakter karakteri tanımı sağlar.

Cihaz yazı tipleri üç temel türe ayrılır:

  • Gerçek cihaz yazı tipleri. Bu makalenin amaçları doğrultusunda, bunlar yalnızca yazıcı donanımının sağladığı ve yalnızca yazıcıda kullanabileceğiniz yazı tipleridir.

  • Cihaz yazı tipi değiştirme. İşletim sisteminde bulunan ve yazıcı donanımının da sağladığı yazı tipleri. Bu durumda, yazıcı donanımı işletim sisteminin yazı tiplerinin yerini alabilir.

  • İndirilebilir yazı tipleri. İşletim sisteminin sağladığı ancak tanımı yazıcıya indirilebilen ve yazıcı donanımı yazı tiplerini doğrudan sağlamış gibi yazıcıda kullanılabilen yazı tipleri.

İndirilebilir yazı tipleri

İşletim sistemi, yumuşak yazı tipleri olarak da bilinen indirilebilir yazı tipleri sağlar. Bir belgeyi yazdırdığınızda, yazı tipinin tanımı yazdırma işinin bir parçası olarak sağlanır. Yazıcı yazdırma işini işlediğinde, yazı tipi tanımının belgenin yazdırılan sayfasına mürekkeple yazılabilmesi için yazı tipi tanımı yazıcı belleğine yüklenir.

Bazıları, yazıcı yazı tipinin karakter karakter karakterlerini çizdiğinden, bu yazı tiplerinin cihaz yazı tipleri olduğunu iddia eder. Ancak, bir yazı tipi tanımı indirildiğinde veya bir bit eşlem aracılığıyla yazıcıya bir karakter çizildiğinde, yalnızca bazı ek yük veya yazdırma işi biriktirici boyutu kaydedilir. Bu işlem, işletim sistemindeki yazı tipinin ekranda ve yazıcıda kullanılabilmesi için uygulamada saydam bir şekilde gerçekleşir. Bu makale yalnızca yazıcının sağladığı cihaz yazı tiplerinin nasıl kullanılacağına odaklandığından, bu makalede indirilebilir yazı tiplerinin nasıl kullanılacağı açıklanmaktadır.

Cihaz yazı tipi değiştirme

Cihaz yazı tipi değişimi, iki ayrı yazı tipi tanımı olduğunda gerçekleşir: biri işletim sisteminin kullandığı, diğeri de yazıcının kullandığı. Başka bir ifadeyle, uygulama ekrandaki bir belgedeki işletim sistemindeki bir yazı tipini seçer ve kullanır. Belgeyi yazdırdığınızda, yazdırılan çıktı yazıcının sağladığı benzer şekilde tanımlanmış yazı tipi kullanılarak çizilir. Bu nedenle, işletim sistemindeki yazı tipi yazıcıda yazıcı tanımlı yazı tipiyle değiştirilmiştir.

Bu durum genellikle yaygın bir Windows TrueType yazı tipi kullanıldığında PostScript yazıcılarında oluşur. Buna örnek olarak, çoğu PostScript cihazında Helvetica yazı tipi için PostScript yazı tipi tanımı kullanılarak yazdırılan TrueType Arial yazı tipi verilebilir. Bu, yazı tipi adı farklı olan benzer bir yazı tipi kullanılarak değiştirme örneğidir. Bu durumda, benzer yazı tipi tanımı da gerçek bir cihaz yazı tipi olarak kullanıma sunulduğundan, bu benzer yazı tipi tanımını doğrudan bulup kullanabilirsiniz. Bu makalenin devamında ele alınmalıdır.

Cihaz yazı tipi değişimi, yazıcıdaki yazı tipinin adı işletim sisteminin sağladığı yazı tipiyle aynı olduğunda da gerçekleşir. Bu durum genellikle Hewlett-Packard LaserJet yazıcılar gibi yazıcılarda oluşur. Bu yazıcılar genellikle Arial ve Times New Roman gibi Windows çekirdek yazı tiplerinin kendi sürümlerine sahiptir. Bu yazı tipleri genellikle gerçek cihaz yazı tipleri aranarak da bulunabilse de, bazen yazıcı sürücüleri sık sık kendi başlarına seçim yaptıkları veya işletim sisteminin sağladığı yazı tipinin kullanılıp kullanılmayacağını kullanıcı ayarları üzerinden seçtiğinden kullanımları garanti edilemez.

Gerçek cihaz yazı tipleri

Gerçek cihaz yazı tipleri, yazıcıda yalnızca tanımı olan yazı tipleridir. Bir uygulamanın bu yazı tiplerini kullanabilmesinin tek yolu, uygulamanın yazı tipini özel olarak tanımlaması ve yazıcı cihazı bağlamında kullanmak üzere oluşturmasıdır.

Bir cihaz hakkında yeterli bilgi biliyorsanız, bir yapıda LOGFONT cihaz yazı tipinin gerçekleştirilmesiyle sonuçlanacak bir mantıksal yazı tipi açıklaması oluşturabilirsiniz. Özellikle üye, üye ve yazı tipinin lfFacenamelfHeight karakter kümesi için doğru bilgileri sağlamak önemlidir. Ayrıca üye, lfOutPrecision benzer adlandırılmış sistem yazı tipleri yerine cihaz yazı tiplerini seçmek için yazı tipi eşleme işlemini etkileyen bir OUT_DEVICE_PRECIS bayrak içermelidir.

Yazı tipinin açıklaması bilinmiyorsa, cihaz yazı tiplerini bulmak için yazı tiplerini numaralandırabilirsiniz. Yazıcının desteklediği cihaz yazı tiplerinin listesini almak için gibi EnumFontFamiliesExyazı tipi numaralandırma işlevlerinden birini kullanın. Geri çağırma işlevine konulan uygulama kodu, hangi yazı tipi örneklerinin bir cihaz yazı tipini tanımladığını belirlemek için geri çağırma işlevine verilen verileri inceleyebilir.

Gerçek cihaz yazı tiplerini kullanma

Yazıcı cihaz bağlamında cihaz yazı tipini kullanma işlemi şu genel adımları izler:

  1. Yazıcı cihaz bağlamındaki yazı tiplerinin sabit listesiyle gerçek cihaz yazı tiplerini tanımlayın.
  2. Bayraklarla ve eleme işlemiyle FontType gösterildiği gibi yalnızca cihaz olan yazı tiplerini seçin.
  3. Cihaz yazı tipi kullanılarak çizilen metni doğru bir şekilde yerleştirmek için eşleme modunda yazıcıya özgü ölçümleri MM_TEXT kullanın.

Yazıcı cihazı bağlamının yazı tiplerini listeleme

Bir cihaz bağlamında kullanılabilen tüm yazı tiplerini listelemek için win32 uygulama programlama arabiriminden (API) geri çağırma işlevlerini ve EnumFontFamiliesEx işlevini kullanabilirsiniz. Bir cihaz bağlamının tüm yazı tiplerini listelemek için iki kez aramanız EnumFontFamiliesEx gerekir: önce yazı tipi ailelerinin listesini almak için, ikinci kez de her yazı tipi ailesindeki tüm ayrı yazı tiplerini almak için.

Yazıcı cihazı bağlamında tüm cihaz yazı tiplerini bulmak için, yazıcı cihazı bağlamının tüm yazı tiplerini listelemeniz gerekir. Her yazı tipi geri çağırma işlevlerine geçirildiğinde, bir cihaz yazı tipi olup olmadığını belirlemek için yazı tipi incelenmiştir. PrinterDeviceFontEnum Aşağıdaki örnek koddaki ve PrinterDeviceFontFamiliesEnum geri çağırma işlevleri bu işlemi gerçekleştirir.

// 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;
}

İşlevin iki kez çağrıldığı örnek kodda EnumFontFamiliesEx görebilirsiniz. İşlevde PrintDeviceFontList ilk çağrı yapılır. İkinci çağrı geri çağırma işlevindedir PrinterDeviceFontFamiliesEnum .

PrintDeviceFontList en üst düzey işlevdir. PrintDeviceFontList yazıcı cihazı bağlamında bir yazdırma işi başlatıp yazı tipi numaralandırma işlemini başlatmak için ilk çağrıyı EnumFontFamiliesEx çağırarak iki görev gerçekleştirir. Platform Yazılım Geliştirme Seti (SDK) belgelerine göre, yapının lfCharSet üyesini LOGFONTDEFAULT_CHARSET değerine ayarladığınızda tüm EnumFontFamiliesEx yazı tipi ailelerini numaralandırır. Yazı tipi numaralandırması tamamlandıktan sonra kod, yöntemini çağırarak EndDoc yazdırma işi yönetim görevini tamamlar.

Geri PrinterDeviceFontFamiliesEnum çağırma işlevi, işlevi tarafından her yazı tipi ailesi için çağrılır EnumFontFamiliesEx . Bu geri çağırma işlevinde kod başlangıçta yazı tipi ailelerini görüntüleyerek yalnızca parametresi tarafından FontType işaretlenmiş cihaz yazı tiplerini bulur. Ayrıca, bu yazı tiplerinin indirilebilir yazı tipleri olma olasılığı yüksek olduğundan olarak TrueType işaretlenmiş tüm yazı tiplerini de gösterir. Cihaz yazı tipleri olarak kabul edilen bu yazı tipi EnumFontFamiliesEx aileleri için işlev yeniden çağrılır ancak geri çağırma işlevinin ENUMLOGFONTEX aldığı yapıya geçirilir. geri çağırma parametresinin ikinci sabit listesi işlev çağrısına giriş parametresi olarak kullanılması, ikinci numaralandırmanın bu yazı tipi ailesindeki tüm ayrı yazı tiplerini listelemesine neden olur.

Cihaz yazı tiplerini seçme

Bu yazı tiplerini numaralandırılmış diğer yazı tiplerinden ayırmak için yazıcı cihazı yazı tiplerinin belirli ölçütlerini kullanabilirsiniz. Özellikle, geri çağırma işlevinin DEVICE_FONTTYPEFontType DWORD parametresindeki değeri arayın. Bu değer kümesiyle geri çağırma işlevine sunulan yazı tiplerinin neredeyse tümü yazıcı cihaz bağlamı için cihaz yazı tipleridir (Adobe yazı tipleri hariç).

Örnek kodda geri çağırma işlevi, PrinterDeviceFontEnum yazı tipi ailesindeki her ayrı yazı tipi için ikinci numaralandırma tarafından çağrılır. PrinterDeviceFontEnum Geri çağırma işlevi üç görev gerçekleştirir:

  • İşlevin yalnızca cihaz yazı tipi olarak tanınan yazı tiplerini işlediğinden emin olmak için cihaz yazı tipi ölçütlerini yeniden kullanır.

  • Cihaz yazı tipinin sistemin ekran cihazı bağlamında da kullanılıp kullanılmadığı görmek için başka bir yazı tipi numaralandırması kullanarak yazı tipini arar.

  • Yazı tipinin kullanımını göstermek için oluşturulan yazdırma işine yazı tipinin bir örneğini yazdırır. Bu geri çağırma işlevi, aşağıdaki örnek kodun parçası olan adlı IsSystemFontbir işlev kullanır:

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;
}

Bu işlev, cihaz yazı tipi olarak işaretlenmiş ancak gerçek bir cihaz yazı tipi olmayan bir yazı tipinin ne zaman algılandığını algılar (bu makaledeki tanıma göre). Adobe yazı tipleri, Adobe Type Manager aracılığıyla veya Windows 2000 veya Windows XP'de bulunan yerel Adobe rasterizer aracılığıyla sisteme yüklendiğinde bu durum oluşur.

Bu durumda, yazı tipi gerçekten yazıcıya indirilen sistem tarafından sağlanan bir yazı tipidir ve bazen TrueType yazı tipleri ile gerçekleşir. Ne yazık ki, Windows 98, Windows Millennium Edition (Me), Windows 2000 ve Windows XP'de yazı tipinin sistemin sağladığı bir Adobe yazı tipi olduğunu belirten bir bayrak yoktur (bayrak içeren TrueType yazı tiplerinin aksine). Yapının ntmFlags üyesinde NEWTEXTMETRIC bir gösterge vardır, ancak bu yalnızca Windows 2000 ve sonraki sürümlerde kullanılabilir. Bu nedenle, kodun bir eleme işlemine başvurması gerekir. Cihaz yazı tipi hem ekran cihazı bağlamı hem de yazıcı cihazı bağlamı tarafından sağlandığında IsSystemFontdetermines yazı tipi kaldırılır.

Ölçeklendirilen bir yazı tipinin tekrarlı örneklerini önlemek için kod, aday yazı tipi kullanıldığında da not alır. Bunun belirli bir uygulaması, bir yazı tipinin sıralı numaralandırmalarının aynı yazı tipi ancak farklı bir ölçekte ne zaman olduğunu görmek için yazı tiplerinin numaralandırma sırasına bağlıdır. Kod, yalnızca farklı bir ölçek olan yazı tiplerini kaldırmak için işlevini kullanır CompareLogFontEx .

Not

Windows işletim sistemlerini programlama belgeleri, yalnızca ölçeğe göre farklılık gösteren yazı tipi örneklerinin sıralı olarak numaralandırılacağını belirtmez. Numaralandırmanın bu şekilde çalıştığı görüldüğü ve yazdırılan sayfadaki örnek satır sayısının azalması tanıtım kodunun kritik bir özelliği olmadığından kod örneği bu tekniği kullanır. Aynı yazı tipinin farklı ölçeklerini ortadan kaldırmak istiyorsanız, kullanılan cihaz yazı tiplerinin veri yapısını korumanız gerekir. Daha sonra program, o anda numaralandırılmış yazı tipini bu veri yapısına göre denetlemelidir.

Ölçeklenebilir ve Bit Eşlem yazı tipleri karşılaştırması

Yazıcılarda numaralandırılabilir iki tür cihaz yazı tipi vardır:

  • Bit eşlem veya raster yazı tipleri
  • Ölçeklenebilir yazı tipleri

Bit eşlem yazı tipleri, sabit boyutlu karakter karakteri tanımına sahip yazı tipleridir. Ölçeklenebilir yazı tipleri, her boyutta çizilebilmeleri için yazıcıda matematik tabanlı bir tanımı olan yazı tipleridir. Başka bir deyişle boyutları ölçeklendirilir.

Bit eşlem yazı tipinin klasik örneği Courier 10 karakter/inçtir (cpi). Adından da anlaşılacağı gibi, bu yazı tipi daktilolardan etki türündeki yazıcılara geçişten bir tutunmadır. Yazı tipinin en yaygın tanımı nokta matrisli bir yazıcının ROM bit eşlem görüntüsünde bulunduğundan bit eşlem yazı tipi olarak adlandırılır.

Genellikle Helvetica ve Times gibi standart bir PostScript yazı tipi kümesinin bulunduğu çoğu PostScript yazıcısında ölçeklenebilir, yazıcıda yerleşik yazı tipi örnekleri bulunabilir.

Ölçeklenebilir olmayan cihaz yazı tiplerinin geri çağırma işlevinin parametresinde FontType ayarlanmış bir biti vardır. Bu bit, SDK'daki simgeyle RASTER_FONTTYPE temsil edilir. Geri çağırma işlevinin FontType parametresinin RASTER_FONTTYPEbit kümesi yoksa, yazı tipi ölçeklenebilir bir yazı tipidir. Bunun nasıl belirleneceğini gösteren bir örnek için örnek kodun PrinterDeviceFontEnum geri çağırma işlevine bakın.

Cihaz yazı tiplerini çizme

Cihaz yazı tipleri olan yazı tipleri bulunduktan sonra, örnek bunları numaralandırmanın yapıldığı yazıcı cihazı bağlamında kullanır. Cihaz yazı tipleri, işleviyle CreateFontIndirect mantıksal bir açıklama oluşturarak diğer yazı tiplerinde olduğu gibi kullanılır. Bu işlev çağrısı, LOGFONT yazı tipi numaralandırma geri çağırma işlevine geçirilen öğesini geçirilir. HFONT oluşturulduktan sonra, işlev çağrısıyla SelectObject cihaz bağlamında seçilerek yazıcı cihazı bağlamında kullanılır.

Cihaz yazı tipi ölçümleri, işlev çağrısı aracılığıyla GetTextMetrics elde edilir. Bir cihaz bağlamı için varsayılan eşleme modu olan eşleme modunu kullanarak MM_TEXT yazıcı cihazı bağlamlarında çalışmak en iyisidir. Eşleme modunu kullandığınızda MM_TEXT , diğer eşleme modlarının birim dönüştürme işlemi sırasında oluşabilecek matematiksel hatalardan kaçınabilirsiniz.

Yazıcı cihaz bağlamında bir cihaz yazı tipi kullandığınızda, yazı tipi ölçümlerini ve dizeleri diğer cihaz bağlamlarına taşımamaya dikkat etmeniz gerekir. Bu, özellikle bellek cihazı bağlamları için geçerlidir. Tanım gereği, bellek cihazı bağlamı yazdırma işi değildir, ancak raster grafiklerin geçici bir bellek arabelleğidir ve bu nedenle cihaz yazı tipini kullanamaz.

Yazıcı cihazı yazı tiplerini kullanırken dikkat edilmesi gereken başka bir nokta daha vardır: Yazdırma işinin What-You-See-Is-What-You-Get tür önizlemesini sağlayamazsınız. Açıkçası, yazıcı donanımında bulunan yazı tipleri ekrana çizilemez. Yazdırma işini önizlemeye en yakın olan, yazıcı cihazı yazı tipinin genel özelliklerine sahip sistem tarafından sağlanan bir yazı tipini bulmak ve ardından yazdırılan sayfada karakter karakterlerinin yerleşimini simüle etmek için işlevini kullanarak ExtTextOut bu yazı tipinin karakter karakterlerini ekranda çizmektir.

Cihaz yazı tiplerini kullanma sorunları

Cihaz yazı tiplerini kullanırken aşağıdaki sorunlarla karşılaşabilirsiniz:

  • Bir cihaz yazı tipi var, ancak yazıcı sürücüsü numaralandırmıyor.

    Yazıcı cihazı bağlamında kullanılabilecek yazı tiplerini numaralandırarak cihaz yazı tipini bulamamanıza neden olan iki neden vardır:

    • Yazıcı sürücüsü, bir nedenden dolayı bu cihaz yazı tipini dışlamak için yazılmıştır.
    • Yazıcı sürücüsü yazı tipini numaralandırır, ancak yazı tipi parametrede FontType cihaz yazı tipi olarak düzgün işaretlenmez.
  • Cihaz yazı tipleri olarak numaralandırılıyor gibi görünen sistem yazı tipleri vardır.

    Bu sorun, sistem tarafından sağlanan bir yazı tipi yazıcıya indirildiğinde oluşur.

    TrueType yazı tiplerinde bu durum oluştuğunda, yazı tipi numaralandırma geri çağırma işlevi parametresinde FontType ve bitleri ayarlanmış olarak TRUETYPE_FONTTYPEDEVICE_FONTTYPE bir çağrı alır. Bu, bu bit birleşimlerini içeren yazı tipleri dahil edilmeyerek örnek kodda işlenir.

    Bu durum, yazıcıya indirilen sistemde yüklü olan Adobe PostScript yazı tiplerinde de oluşur. Bu yazı tiplerini diğer cihaz yazı tiplerinden ayırt etmenin bir yolu, bunları hem sistem ekranı cihaz bağlamında hem de yazıcı cihazı bağlamında aramaktır. Aynı yazı tipi her iki cihaz bağlamında da numaralandırılabiliyorsa, yazıcı cihaz bağlamında kullanıldığında yazı tipi büyük olasılıkla yazıcıya indirilir.

  • Yazıcı sürücüm birkaç ölçeklenebilir cihaz yazı tipini numaralandırır, ancak boyutları dışında aynı görünüyorlar.

    Birçok yazıcı sürücüsü, aynı yazı tipinin farklı boyutlarda birkaç farklı örneğini sağlayarak ölçeklenebilir bir yazı tipini numaralandırır. Bu örnek kodda, işlevi kullanılarak CompareLogFontEx ölçeklenebilir olduğu varsayılan yazı tiplerinin çeşitli örnekleri karşılaştırılarak işlenir.

    Not

    Geri çağırma işlevinin FontType parametresi kümesine RASTER_FONTTYPEbit sahip olduğunda, birden çok numaralandırma her boyut için ölçeklenebilir olmayan yazı tiplerinin belirli örneklerinin açıklamalarını sağlar. Her geri arama, söz konusu yazı tipinin kullanılabildiği tek boyutları numaralandırır.

  • Bazı yazıcılarda cihaz yazı tipleri yok gibi görünüyor.

    Bu doğru. Mürekkep jeti türündeki yazıcılar gibi bazı yazıcılarda cihaz yazı tipleri sağlanmaz. Bu yazıcılar kesinlikle daha raster cihazlardır ve bu nedenle yazıcıda yerleşik yazı tipi tanımları yoktur.