C++ 为什么微软没有';在win32api中是否有一个函数,在给定字体句柄的情况下返回字体文件名?

C++ 为什么微软没有';在win32api中是否有一个函数,在给定字体句柄的情况下返回字体文件名?,c++,winapi,windows-7,fonts,C++,Winapi,Windows 7,Fonts,这是在多年使用Windows API的经验中,我第一次遇到这样的情况:我需要用Windows当前的编程界面做一些事情,但我做不到 根据我的研究,字体“Arial Black”使用的是文件arialblk.ttf,没有用于字体“Arial Black Italic”的文件,也没有用于字体“Arial Black Bold”,至少在我的Windows 7电脑中是这样 我在下面插入了一个程序,用“Arial Black”字体单独显示几行文本,然后用斜体和粗体显示。令我惊讶的是,斜体文本被正常渲染,而粗

这是在多年使用Windows API的经验中,我第一次遇到这样的情况:我需要用Windows当前的编程界面做一些事情,但我做不到

根据我的研究,字体“Arial Black”使用的是文件
arialblk.ttf
没有用于字体“Arial Black Italic”的文件,也没有用于字体“Arial Black Bold”,至少在我的Windows 7电脑中是这样

我在下面插入了一个程序,用“Arial Black”字体单独显示几行文本,然后用斜体和粗体显示。令我惊讶的是,斜体文本被正常渲染,而粗体文本被渲染为“Arial Black”。然后我意识到Word女士也会发生同样的事情。我还插入了Word文档的屏幕截图,上面叠加了下面代码的输出。这里发生了什么事?我是否必须猜测,每种情况下使用的是哪种字体文件?显然,Windows API没有给我答案的可能性。为什么是迷雾

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, UINT, LONG);


int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
{
    WNDCLASSEX  wndclassx;

    wndclassx.cbSize        = sizeof(WNDCLASSEX);
    wndclassx.style         = CS_HREDRAW | CS_VREDRAW;
    wndclassx.lpfnWndProc   = WndProc;
    wndclassx.cbClsExtra    = 0;
    wndclassx.cbWndExtra    = 0;
    wndclassx.hInstance     = hInstance;
    wndclassx.hIcon         = nullptr;
    wndclassx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wndclassx.lpszMenuName  = nullptr;
    wndclassx.lpszClassName = L"WndProc";
    wndclassx.hIconSm       = nullptr;

    if( !RegisterClassEx(&wndclassx) ) return 0;

    HWND hWnd = CreateWindow(L"WndProc", nullptr, WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, CW_USEDEFAULT,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);

    ShowWindow(hWnd, SW_MAXIMIZE);
    UpdateWindow(hWnd);

    MSG msg;
    while( GetMessage(&msg, nullptr, 0, 0) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
    static HFONT s_hArialBlack, s_hArialBlackItalic, s_hArialBlackBold;

    switch ( message )
    {
        case WM_CREATE:
        {
            LOGFONT lf;
            memset(&lf, 0, sizeof(LOGFONT));
            lf.lfHeight = -MulDiv(20, 96, 72);
            wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Arial Black");


            if( !(s_hArialBlack = CreateFontIndirect(&lf)) ) return -1;

            lf.lfItalic = true;

            if( !(s_hArialBlackItalic = CreateFontIndirect(&lf)) )
            {
                DeleteObject(s_hArialBlack);
                return -1;
            }

            lf.lfWeight = FW_BOLD;
            lf.lfItalic = false;

            if( !(s_hArialBlackBold = CreateFontIndirect(&lf)) )
            {
                DeleteObject(s_hArialBlackItalic);
                DeleteObject(s_hArialBlack);
                return -1;
            }
        }
        break;

        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            BeginPaint(hwnd, &ps);
            HFONT hFont = (HFONT)SelectObject(ps.hdc, s_hArialBlack);
            TextOut(ps.hdc, 20, 10, L"Font Arial Black", 16);
            SelectObject(ps.hdc, s_hArialBlackItalic);
            TextOut(ps.hdc, 20, 50, L"Font Arial Black Italic", 23);
            SelectObject(ps.hdc, s_hArialBlackBold);
            TextOut(ps.hdc, 20, 90, L"Font Arial Black Bold", 21);
            SelectObject(ps.hdc, hFont);
            EndPaint(hwnd, &ps);
        }
        break;

        case WM_DESTROY:
        DeleteObject(s_hArialBlackBold);
        DeleteObject(s_hArialBlackItalic);
        DeleteObject(s_hArialBlack);
        PostQuitMessage(0);
        break;

        default:

        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
} 
#包括
LRESULT回调WndProc(HWND、UINT、UINT、LONG);
int APICENTRY WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR pszCmdLine、int nCmdShow)
{
wndclassx wndclassx;
wndclassx.cbSize=sizeof(wndclassx);
wndclassx.style=CS_HREDRAW | CS_VREDRAW;
wndclassx.lpfnWndProc=WndProc;
wndclassx.cbClsExtra=0;
wndclassx.cbWndExtra=0;
wndclassx.hInstance=hInstance;
wndclassx.hIcon=nullptr;
wndclassx.hCursor=LoadCursor(空,IDC_箭头);
wndclassx.hbrBackground=(HBRUSH)(彩色窗口+1);
wndclassx.lpszMenuName=nullptr;
wndclassx.lpszClassName=L“WndProc”;
wndclassx.hIconSm=nullptr;
如果(!RegisterClassEx(&wndclassx))返回0;
HWND HWND=CreateWindow(L“WndProc”,nullptr,WS_重叠窗口| WS_VSCROLL | WS_HSCROLL,CW_USEDEFAULT,
CW_usefault、CW_usefault、CW_usefault、nullptr、nullptr、hInstance、nullptr);
显示窗口(hWnd、SW_);
更新窗口(hWnd);
味精;
while(GetMessage(&msg,nullptr,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回(int)msg.wParam;
}
LRESULT回调WndProc(HWND HWND,UINT消息,UINT wParam,长LPRAM)
{
静态HFONT s_hArialBlack、s_hArialBlack Italic、s_hArialBlackBold;
开关(信息)
{
案例WM_创建:
{
LOGFONT-lf;
memset(&lf,0,sizeof(LOGFONT));
lf.lfHeight=-MulDiv(20,96,72);
wcscpy_s(左前面板名称,左前面板大小,L“Arial黑色”);
if(!(s_hArialBlack=createfontdirective(&lf))返回-1;
lf.lfItalic=true;
如果(!(s_hArialBlackItalic=CreateFontIndirect(&lf)))
{
删除对象(s_hArialBlack);
返回-1;
}
lf.lfWeight=FW_粗体;
lf.lfItalic=false;
如果(!(s_hArialBlackBold=CreateFontIndirect(&lf)))
{
删除对象(s_hArialBlackItalic);
删除对象(s_hArialBlack);
返回-1;
}
}
打破
案例WM_油漆:
{
PAINTSTRUCT-ps;
开始油漆(hwnd和ps);
HFONT HFONT=(HFONT)选择对象(ps.hdc,s_hArialBlack);
文本输出(ps.hdc,20,10,L“字体Arial黑色”,16);
选择对象(ps.hdc,s_hArialBlackItalic);
文本输出(ps.hdc,20,50,L“字体Arial黑色斜体”,23);
选择对象(ps.hdc,s_hArialBlackBold);
文本输出(ps.hdc,20,90,L“字体Arial黑色粗体”,21);
选择对象(ps.hdc、hFont);
端漆(hwnd和ps);
}
打破
案例WM_销毁:
删除对象(s_hArialBlackBold);
删除对象(s_hArialBlackItalic);
删除对象(s_hArialBlack);
PostQuitMessage(0);
打破
违约:
返回DefWindowProc(hwnd、message、wParam、lParam);
}
返回0;
} 
这是我上面提到的屏幕截图:


并非所有字体都设计了斜体或粗体版本。Arial Black就是其中之一

我不认为大多数应用程序需要能够确定实际使用的字体文件。因此缺乏直接API

也就是说,有一些旧的样品声称这样做。这两种方法我都没有测试过

以2006年的c#为例。

在2001年的CodeProject上,函数不存在,因为没有从逻辑字体到物理字体的一对一映射。你已经发现了一部分,通过发现你没有一套专门的斜体轮廓。Windows通过对轮廓应用变换来合成缺少的样式。同样的合成对粗体风格没有任何特殊作用,字体已经粗体了

当您显示使用字形但字体没有轮廓的文本时,它会变得更加复杂。我喜欢汉字。然后Windows会完全替换另一种具有所需字形的字体。显然,这使得实现您想要的功能变得不可能


如果您希望更好地控制此过程,请考虑Uniscribe api。

当您知道所需字体时,是否有需要知道字体文件名的原因?我不想详细说明。但Windows必须做到这一点。例如,当程序调用GetFontData()时,函数的第一个参数是DC句柄,Windows必须根据在DC中选择的字体确定字体文件名。为什么Windows API中不存在这样的函数?字体渲染器可能只是倾斜和加厚字体,而不是使用TTF定义。我特别怀疑他