建立私人字型集合
PrivateFontCollection類別繼承自FontCollection抽象基類。 您可以使用 PrivateFontCollection 物件來維護一組專為您的應用程式使用的字型。
私人字型集合可以包含已安裝的系統字型,以及電腦上尚未安裝的字型。 若要將字型檔案新增至私人字型集合,請呼叫PrivateFontCollection::PrivateFontFile 物件的 AddFontFile方法。
注意
當您使用 GDI+ API 時,絕對不能允許應用程式從不受信任的來源下載任意字型。 作業系統需要提高的許可權,以確保所有已安裝的字型都受到信任。
PrivateFontCollection物件的FontCollection::GetFamilies方法會傳回FontFamily物件的陣列。 呼叫 FontCollection::GetFamilies之前,您必須配置足以保存該陣列的緩衝區。 若要判斷必要緩衝區的大小,請呼叫 FontCollection::GetFamilyCount 方法,並將傳回值乘以 sizeof (FontFamily) 。
私人字型集合中的字型系列數目不一定與已新增至集合的字型檔案數目相同。 例如,假設您將 ArialBd.tff、Times.tff 和 TimesBd.tff 檔案新增至集合。 集合中只有三個檔案,但只有兩個系列,因為 Times.tff 和 TimesBd.tff 屬於同一個系列。
下列範例會將下列三個字型檔案新增至 PrivateFontCollection 物件:
- C:\WINNT\Fonts\Arial.tff (Arial,一般)
- C:\WINNT\Fonts\CourBI.tff (Courier New,粗體斜體)
- C:\WINNT\Fonts\TimesBd.tff (Times New Roman, bold)
程式碼會呼叫PrivateFontCollection物件的FontCollection::GetFamilyCount方法,以判斷私人集合中的系列數目,然後呼叫FontCollection::GetFamilies來擷取FontFamily物件的陣列。
針對集合中的每個 FontFamily 物件,程式碼會呼叫 FontFamily::IsStyleAvailable 方法,以判斷是否有各種樣式 (一般、粗體、斜體、粗體斜體、底線和刪除線) 。 傳遞至 FontFamily::IsStyleAvailable 方法的引數是 FontStyle 列舉的成員,其宣告于 Gdiplusenums.h 中。
如果有特定的系列/樣式組合可用,則會使用該系列和樣式來建構 Font 物件。 傳遞至 Font 建構函式的第一個引數是字型系列名稱, (不是 FontFamily 物件,如同 Font 建構函式的其他變化) ,最後一個引數是 PrivateFontCollection 物件的位址。 建構Font物件之後,其位址會傳遞至Graphics類別的DrawString方法,以顯示系列名稱以及樣式的名稱。
#define MAX_STYLE_SIZE 20
#define MAX_FACEANDSTYLE_SIZE (LF_FACESIZE + MAX_STYLE_SIZE + 2)
PointF pointF(10.0f, 0.0f);
SolidBrush solidBrush(Color(255, 0, 0, 0));
INT count = 0;
INT found = 0;
WCHAR familyName[LF_FACESIZE];
WCHAR familyNameAndStyle[MAX_FACEANDSTYLE_SIZE];
FontFamily* pFontFamily;
PrivateFontCollection privateFontCollection;
// Add three font files to the private collection.
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\Arial.ttf");
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\CourBI.ttf");
privateFontCollection.AddFontFile(L"c:\\Winnt\\Fonts\\TimesBd.ttf");
// How many font families are in the private collection?
count = privateFontCollection.GetFamilyCount();
// Allocate a buffer to hold the array of FontFamily
// objects returned by GetFamilies.
pFontFamily = new FontFamily[count];
// Get the array of FontFamily objects.
privateFontCollection.GetFamilies(count, pFontFamily, &found);
// Display the name of each font family in the private collection
// along with the available styles for that font family.
for(INT j = 0; j < count; ++j)
{
// Get the font family name.
pFontFamily[j].GetFamilyName(familyName);
// Is the regular style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleRegular))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Regular");
Font* pFont = new Font(
familyName, 16, FontStyleRegular, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the bold style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleBold))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Bold");
Font* pFont = new Font(
familyName, 16, FontStyleBold, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the italic style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleItalic))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Italic");
Font* pFont = new Font(
familyName, 16, FontStyleItalic, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the bold italic style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleBoldItalic))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" BoldItalic");
Font* pFont = new Font(familyName, 16,
FontStyleBoldItalic, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Is the underline style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleUnderline))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Underline");
Font* pFont = new Font(familyName, 16,
FontStyleUnderline, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0);
delete(pFont);
}
// Is the strikeout style available?
if(pFontFamily[j].IsStyleAvailable(FontStyleStrikeout))
{
StringCchCopyW(familyNameAndStyle, LF_FACESIZE, familyName);
StringCchCatW(familyNameAndStyle, MAX_FACEANDSTYLE_SIZE, L" Strikeout");
Font* pFont = new Font(familyName, 16,
FontStyleStrikeout, UnitPixel, &privateFontCollection);
graphics.DrawString(familyNameAndStyle, -1, pFont, pointF, &solidBrush);
pointF.Y += pFont->GetHeight(0.0f);
delete(pFont);
}
// Separate the families with white space.
pointF.Y += 10.0f;
} // for
delete pFontFamily;
下圖顯示上述程式碼的輸出。
Arial.tff (在上述程式碼範例中新增至私人字型集合) 是 Arial 一般樣式的字型檔案。 不過,請注意,程式輸出會顯示 Arial 字型系列以外的數種可用樣式。 這是因為 Windows GDI+ 可以從一般樣式模擬粗體、斜體和粗體斜體樣式。 GDI+ 也可以從一般樣式產生底線和刪除線。
同樣地,GDI+ 可以從粗體樣式或斜體樣式模擬粗體斜體樣式。 程式輸出顯示即使 TimesBd.tff (Times New Roman,粗體) 也是集合中唯一的 Times 檔案,粗體斜體樣式仍可供 Times 系列使用。
下表指定 GDI+ 支援的非系統字型。
格式 | GDI | Windows 7 上的 GDI+ | Windows 8上的 GDI+ | DirectWrite |
---|---|---|---|---|
.FON | 是 | 否 | 否 | 否 |
.FNT | 是 | 否 | 否 | 否 |
.TTF | 是 | 是 | 是 | 是 |
.具有 TrueType 的 OTF | 是 | 是 | 是 | 是 |
.OTF 與 Adobe CFF | 是 | 否 | 是 | 是 |
Adobe Type 1 | 是 | 否 | 否 | 否 |