Создание частной коллекции шрифтов
Класс PrivateFontCollection наследуется от абстрактного базового класса FontCollection . Объект PrivateFontCollection можно использовать для поддержки набора шрифтов специально для вашего приложения.
Частная коллекция шрифтов может включать в себя как установленные системные шрифты, так и шрифты, которые не были установлены на компьютере. Чтобы добавить файл шрифта в частную коллекцию шрифтов, вызовите метод PrivateFontCollection::AddFontFile объекта PrivateFontCollection .
Примечание
При использовании API GDI+ никогда не следует разрешать приложению скачивать произвольные шрифты из ненадежных источников. Операционной системе требуются повышенные привилегии, чтобы гарантировать, что все установленные шрифты являются доверенными.
Метод FontCollection::GetFamilies объекта PrivateFontCollection возвращает массив объектов FontFamily . Перед вызовом FontCollection::GetFamilies необходимо выделить буфер, достаточно большой для хранения этого массива. Чтобы определить размер требуемого буфера, вызовите метод FontCollection::GetFamilyCount и умножьте возвращаемое значение на sizeof(FontFamily).
Количество семейств шрифтов в частной коллекции шрифтов не обязательно должно совпадать с количеством файлов шрифтов, добавленных в коллекцию. Например, предположим, что в коллекцию были добавлены файлы ArialBd.tff, Times.tff и TimesBd.tff. В коллекции будет три файла, но только два семейства, так как Times.tff и TimesBd.tff принадлежат одному семейству.
В следующем примере к объекту PrivateFontCollection добавляются следующие три файла шрифтов:
- C:\WINNT\Fonts\Arial.tff (Arial, regular)
- C:\WINNT\Fonts\CourBI.tff (Courier New, курсив полужирным шрифтом)
- C:\WINNT\Fonts\TimesBd.tff (Times New Roman, полужирный)
Код вызывает метод FontCollection::GetFamilyCount объекта PrivateFontCollection для определения количества семейств в частной коллекции, а затем вызывает FontCollection::GetFamilies для получения массива объектов FontFamily .
Для каждого объекта FontFamily в коллекции код вызывает метод FontFamily::IsStyleAvailable , чтобы определить, доступны ли различные стили (обычный, полужирный, курсив, курсив, подчеркивание и зачеркивка). Аргументы, передаваемые методу FontFamily::IsStyleAvailable , являются членами перечисления FontStyle , которое объявляется в Gdiplusenums.h.
Если доступно определенное сочетание семейства и стиля, объект Font создается с использованием этого семейства и стиля. Первым аргументом, переданным конструктору Font , является имя семейства шрифтов (а не объект FontFamily , как в случае с другими вариантами конструктора шрифта ), а последним аргументом является адрес объекта PrivateFontCollection . После создания объекта Font его адрес передается методу DrawString класса Graphics , чтобы отобразить имя семейства вместе с именем стиля.
#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+ может имитировать полужирный курсив из полужирного и курсивного стилей. Выходные данные программы показывают, что полужирный курсив доступен для семейства Times, несмотря на то, что TimesBd.tff (Times New Roman, полужирный) является единственным файлом Times в коллекции.
В этой таблице указаны несистемные шрифты, поддерживаемые GDI+.
Формат | GDI | GDI+ в Windows 7 | GDI+ в Windows 8 | DirectWrite |
---|---|---|---|---|
. FON | да | нет | нет | нет |
. FNT | да | нет | нет | нет |
. TTF | да | да | да | да |
. OTF с TrueType | да | да | да | да |
. OTF с Adobe CFF | да | нет | да | да |
Adobe Type 1 | да | нет | нет | нет |