5

何年にもわたって Windows API を使用してきた経験の中で、Windows の現在のプログラミング インターフェイスでは実行できないことを実行する必要があるという状況に直面したのは、これが初めてです。

私の調査によると、フォント「Arial Black」はファイルarialblk.ttfを使用し、フォント「Arial Black Italic」のファイルも、フォント「Arial Black Bold」のファイルも、少なくとも Windows 7 を搭載した私のコンピューターにはありません。

プログラムの下に挿入して、フォント「Arial Black」を単独で使用し、次に斜体と太字を使用して数行のテキストを表示しました。驚いたことに、斜体のテキストは正常にレンダリングされ、太字のテキストは単なる「Arial Black」のようにレンダリングされました。その後、MS 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;
} 

これは、上で参照したスクリーン ショットです。

ここに画像の説明を入力

4

2 に答える 2

4

論理フォントから物理フォントへの 1 対 1 のマッピングがないという理由だけで、この関数は存在しません。イタリック体専用のアウトラインのセットがないことを発見することで、すでに部分的にそれを発見しました。Windowsは、アウトラインに変換を適用して不足しているスタイルを合成します。その同じ合成は太字スタイルで特別なことを何もしませんでした.フォントはすでに太字です.

フォントにアウトラインがないグリフを使用するテキストを表示すると、さらに複雑になります。漢字みたい。その後、Windowsは、要求されたグリフを持つ別のフォントに完全に置き換えます。明らかに、それはあなたが望む種類の機能を実装することを不可能にします。

このプロセスをより適切に制御したい場合は、Uniscribe API を検討してください。

于 2012-06-18T19:08:29.953 に答える