2012-06-18 8 views
5

Esta es la primera vez, en años de experiencia usando la API de Windows, que enfrento una situación en la que necesito hacer algo, que no puedo, con la interfaz de programación actual de Windows.¿Por qué MS no tiene en su win32api una función que devuelve el nombre del archivo de fuente, dado el identificador de fuente?

Según mi investigación, el tipo de letra "Arial Negro" utiliza el archivo arialblk.ttf y no hay archivo para el tipo de letra "Arial Negro cursiva", ni por el tipo de letra "Arial Negro Bold", al menos en mi ordenador con a Windows 7.

Inserté debajo de un programa para mostrar unas líneas de texto usando la fuente "Arial Black", por sí mismo, y luego con cursiva y negrita. Para mi sorpresa, el texto en cursiva se hizo con normalidad y el texto en negrita se representó como si fuera solo "Arial Black". Entonces me di cuenta de que pasa lo mismo con MS Word. También inserté una captura de pantalla de un documento de Word, superpuesto por el resultado del código a continuación. Que esta pasando aqui ? ¿Tengo que adivinar qué archivo de fuente se usa en cada caso? Aparentemente, la API de Windows no me da la posibilidad de una respuesta. ¿Por qué el misterio?

#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; 
} 

Esta es la captura de pantalla que me he referido anteriormente:

enter image description here

+2

¿Hay alguna razón por la que necesita saber el nombre del archivo de fuente, cuando sabe qué tipo de letra desea? – crashmstr

+0

No me gustaría entrar en este detalle. Pero Windows tiene que hacer eso. Por ejemplo, cuando un programa llama a GetFontData(), donde el primer argumento de la función es un controlador de DC, Windows debe determinar el nombre del archivo de fuente, según la fuente seleccionada en el DC. ¿Por qué tal función no existe en la API de Windows? – WaldB

+0

Es posible que el renderizador de fuentes simplemente esté sesgando y engrosando la fuente, en lugar de usar una definición TTF. Soy especialmente sospechoso de la versión en cursiva, pero no soy un tipo de letra, así que no puedo decirlo con certeza. –

Respuesta

3

No todas las fuentes han diseñado versiones cursiva o negrita. Arial Black es uno de esos.

No creo que la mayoría de las aplicaciones necesitarían poder determinar qué archivo de fuente real se está utilizando. De ahí la falta de una API directa.

Dicho esto, hay algunas muestras antiguas que dicen hacer esto. No he probado ninguno de los métodos.

Get the font filename (like tahoma.ttf) con un ejemplo de C# de 2006.
Finding a Font file from a Font name en CodeProject de 2001

+0

Supongamos que un programa llama a GetFontData() dos veces para obtener una copia de los archivos de fuente que contienen las fuentes "Arial Black" y "Arial Black Italic" en la memoria. ¡Sin saber que los archivos son los mismos, el programa debería mantener dos copias del mismo archivo en la memoria! – WaldB

+0

En el enlace de CodeProject dado anteriormente, encontrará esta frase "Desafortunadamente, esto no se puede considerar un método 100% efectivo para encontrar el nombre de un archivo de fuente" – WaldB

+0

Sí, lo leí. El código C# podría ser más viable. Al no trabajar con fuentes en este nivel, no sé cuántos datos devuelve 'GetFontData'. – crashmstr

4

La función no existe simplemente porque no hay correlación de uno a uno a partir de fuentes lógicas a fuentes físicas. Ya lo descubrió parcialmente al descubrir que no tiene un conjunto dedicado de contornos para cursiva. Windows sintetiza estilos faltantes al aplicar una transformación en el contorno. Esa misma síntesis no hizo nada especial con el estilo audaz, la fuente ya está en negrita.

Se vuelve mucho más enrevesado cuando se muestra texto que usa glifos para los cuales la fuente no tiene un contorno. Al igual que los caracteres chinos. Entonces Windows completamente sustituye otra fuente que tiene el glifo solicitado. Claramente eso hace que la implementación del tipo de función que desea sea imposible.

Considere la API de Uniscribe si desea un mejor control sobre este proceso.

+0

>> La función no existe simplemente porque no hay un mapeo uno a uno desde las fuentes lógicas a las fuentes físicas << Pero hay un mapeo tal como uno a uno, por lo que esta función es viable y útil, ya que Expliqué con mi ejemplo anterior, donde tendría que guardar dos copias del mismo archivo de fuente en la memoria, sin saber que representan el mismo archivo. – WaldB

+0

>> Considere la API de Uniscribe si desea un mejor control sobre este proceso << Supongamos que quiero procesar los archivos de fuente yo mismo, sin utilizar las bibliotecas de Uniscribe. ¿Cómo me aseguro de que no tendré copias duplicadas en memoria de esos archivos? – WaldB

+0

¿Por qué supone que hay duplicación? Sin duda no hay. No se puede averiguar de todos modos, es bastante irrelevante. –

Cuestiones relacionadas