用Windows API加载一个ttf字体

使用CreateFont可以指定字体名称和一堆其他属性。 但是,如果我有一个font.ttf文件,我想这个特定的字体由Windows加载? 我如何指定要使用的特定文件?

我很确定你不能。 所有对字体的请求都通过字体映射器,它会挑选最接近符合您所提供的规范的字体文件。 虽然我不确定它是否在现实中,但至少在理论上可以使用(例如)来自两个完全独立的字体文件的数据来创建一个逻辑字体。

无可否认,这是相当间接的,但是在Windows 7+上运行时,您可以使用DWDI与DWrite进行互操作。

 #include <Windows.h> #include <WindowsX.h> #include <DWrite.h> ... // Make the font file visible to GDI. AddFontResourceEx(fontFileName, FR_PRIVATE, 0); if (SUCCEEDED(GetLogFontFromFileName(fontFileName, &logFont))) { logFont.lfHeight = -long(desiredPpem); HFONT hf = CreateFontIndirect(&logFont); HFONT oldFont = SelectFont(hdc, hf); ... // Do stuff... ... SelectFont(hdc, oldFont); } RemoveFontResource(fontFileName); .... HRESULT GetLogFontFromFileName(_In_z_ wchar const* fontFileName, _Out_ LOGFONT* logFont) { // DWrite objects ComPtr<IDWriteFactory> dwriteFactory; ComPtr<IDWriteFontFace> fontFace; ComPtr<IDWriteFontFile> fontFile; ComPtr<IDWriteGdiInterop> gdiInterop; // Set up our DWrite factory and interop interface. IFR(DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&dwriteFactory) ); IFR(g_dwriteFactory->GetGdiInterop(&gdiInterop)); // Open the file and determine the font type. IFR(g_dwriteFactory->CreateFontFileReference(fontFileName, nullptr, &fontFile)); BOOL isSupportedFontType = false; DWRITE_FONT_FILE_TYPE fontFileType; DWRITE_FONT_FACE_TYPE fontFaceType; UINT32 numberOfFaces = 0; IFR(fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces)); if (!isSupportedFontType) return DWRITE_E_FILEFORMAT; // Set up a font face from the array of font files (just one) ComPtr<IDWriteFontFile> fontFileArray[] = {fontFile}; IFR(g_dwriteFactory->CreateFontFace( fontFaceType, ARRAYSIZE(fontFileArray), // file count &fontFileArray[0], // or GetAddressOf if WRL ComPtr 0, // faceIndex DWRITE_FONT_SIMULATIONS_NONE, &fontFace ); // Get the necessary logical font information. IFR(gdiInterop->ConvertFontFaceToLOGFONT(fontFace, OUT logFont)); return S_OK; } 

在那里IFR只是一个失败的宏返回一个FAILED HRESULT,并且ComPtr是一个辅助智能指针类(用你自己的,或ATL CComPtr,WinRT ComPtr,VS2013 _com_ptr_t …替代)。

一种可能性是EnumFonts() ,保存结果。 然后再添加你的私人字体与AddFontResourceEx()EnumFonts() ,不同的是你添加。 请注意,TTF和位图字体枚举不同,但对于此测试,这应该不重要。

如果您使用的是位图字体,则可以轻松解析(.FNT和.FON)。 您可能需要构建TTF(或者借用其他评论者建议的FreeType)解析器,将“名称”表从TTF文件中提取出来。

对于您正在控制或提供给您的应用程序的字体而言,这似乎有很多工作要做。

我们使用AddFontResourceEx()来添加一个私人字体,但是由于我们控制了我们添加的字体,我们只是将传递给CreateFontIndirect()的字体名进行硬编码以匹配。

如果您不关心安装字体,您可以使用AddFontResource来完成,那么您可以通过查看HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts中的映射来获取物理.TTF和它的逻辑/系列名称之间的关系。

我在评论中提到了PrivateFontCollection ,因为我以为你想暂时这样做; 您可以使用PrivateFontCollection::AddFontFile将TTF加载到PFC中,从集合&考试GetFamilyName取回新的FontFamily对象。 (我已经做了类似于.NET的.net实现,但不是原始的API)