2009-04-07 16 views
15

¿Cuál es la mejor manera de incrustar una fuente truetype dentro de la aplicación que estoy desarrollando? Básicamente quiero asegurarme de que una fuente en particular esté disponible para mi aplicación cuando esté instalada en otra máquina. Tengo el archivo de fuente * .ttf y solo necesito una manera de incrustarlo o instalarlo automáticamente cuando se ejecuta la aplicación.¿Cómo incrusto una fuente con mi aplicación C#? (usando Visual Studio 2005)

¿Debo configurar el programa de instalación para instalar la fuente durante la instalación o puedo cargar dinámicamente la fuente durante el tiempo de ejecución de la aplicación? De hecho, ambos sería bueno saberlo.

La aplicación se está desarrollando en C# utilizando .NET 2.0.

Respuesta

15

Este blog post debería ayudarlo.

Básicamente se agrega la fuente como un recurso incrustado y luego se carga en un objeto PrivateFontCollection.

+0

A veces recibí excepciones cuando intenté dibujar texto usando una fuente que creé usando esta técnica, a menos que mantuviera una referencia a la colección PrivateFontCollection. Pensé que tenía mi fuente, ¿por qué todavía necesitaba la colección? Supongo que la fuente utiliza información de ella y se recolectó basura o algo así. –

11

Es más fácil que esto parece; puede incrustar la fuente como un recurso en su aplicación y acceder a ella como una propiedad fuertemente tipada dentro del espacio de nombres de Propiedades de su aplicación. Pero el enlace dado debería ser un buen punto de partida.


Para la VB-discapacitados:

Add the font as a resource in your application. Llame al MyFontLol recursos. Puede acceder a este recurso (como una matriz de bytes) desde Properties.Resources.MyFontLol.

No he probado los siguientes, pero parece ser viable:

public void LoadMyFontLolKThx() 
{ 
    // get our font and wrap it in a memory stream 
    byte[] myFont = Properties.Resources.MyFontLol; 
    using (var ms = new MemoryStream(myFont)) 
    { 
     // used to store our font and make it available in our app 
     PrivateFontCollection pfc = new PrivateFontCollection(); 
     // The next call requires a pointer to our memory font 
     // I'm doing it this way; not sure what best practice is 
     GCHandle handle = GCHandle.Alloc(ms, GCHandleType.Pinned); 
     // If Length > int.MaxValue this will throw 
     checked 
     { 
      pfc.AddMemoryFont(
       handle.AddrOfPinnedObject(), (int)ms.Length); 
     } 
     var font = new Font(pfc.Families[0],12); 

     // use your font here 
    } 
} 

Una última nota. El PFC almacena la fuente como una fuente GDI +. Estos no son compatibles con algunos controles de formularios. De los documentos:

Para utilizar la fuente de memoria, el texto en un control debe representarse con GDI +. utiliza el método SetCompatibleTextRenderingDefault , pasando verdadera, para establecer GDI + representación de la aplicación, o en controles individuales mediante el establecimiento de UseCompatibleTextRendering de propiedades del control a verdadero. Algunos controles no pueden renderizarse con GDI +.

+0

Mi. Fuente. Lol. ¿Es ese el mejor nombre que podrías pensar? –

+0

Puedo excavar el nombre del método LolKThx –

+0

Cuando intento esto, definitivamente hay un problema al pasar un MemoryStream a GCHandle.Alloc - no era un objeto de tipo primitivo la esencia de la excepción. * shrug * –

12

Aquí es la respuesta de Will, traducido a C# (no probado): Método

PrivateFontCollection pfc = new PrivateFontCollection(); 

using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("Alphd___.ttf")) 
{ 
    if (null == fontStream) 
    { 
     return; 
    } 

    int fontStreamLength = (int) fontStream.Length; 

    IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength); 

    byte[] fontData = new byte[fontStreamLength]; 
    fontStream.Read(fontData, 0, fontStreamLength); 

    Marshal.Copy(fontData, 0, data, fontStreamLength); 

    pfc.AddMemoryFont(data, fontStreamLength); 

    Marshal.FreeCoTaskMem(data); 
} 

junto con su pintura():

protected void Form1_Paint(object sender, PaintEventArgs e) 
{ 
    bool bold = false; 
    bool italic = false; 

    e.Graphics.PageUnit = GraphicsUnit.Point; 

    using (SolidBrush b = new SolidBrush(Color.Black)) 
    { 
     int y = 5; 

     foreach (FontFamily fontFamily in pfc.Families) 
     { 
      if (fontFamily.IsStyleAvailable(FontStyle.Regular)) 
      { 
       using (Font font = new Font(fontFamily, 32, FontStyle.Regular)) 
       { 
        e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
       } 
       y += 40; 
      } 
      if (fontFamily.IsStyleAvailable(FontStyle.Bold)) 
      { 
       bold = true; 
       using (Font font = new Font(fontFamily, 32, FontStyle.Bold)) 
       { 
        e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
       } 
       y += 40; 
      } 
      if (fontFamily.IsStyleAvailable(FontStyle.Italic)) 
      { 
       italic = true; 
       using (Font font = new Font(fontFamily, 32, FontStyle.Italic)) 
       { 
        e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
       } 
       y += 40; 
      } 

      if(bold && italic) 
      { 
       using(Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic)) 
       { 
        e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
       } 
       y += 40; 
      } 

      using (Font font = new Font(fontFamily, 32, FontStyle.Underline)) 
      { 
       e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
       y += 40; 
      } 

      using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout)) 
      { 
       e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic); 
      } 
     } 
    } 
} 
+0

Creo que "b.Dispose();" no es correcto. –

+0

Es cierto, @coffee_machine. Estoy seguro de que está cubierto por el hecho de que b se declara en un bloque de uso y puede eliminarse. –

+1

En realidad, usted está desechando dentro del bucle for. Esto solo funcionará para la primera iteración. –

-2

tal vez no sea la mejor manera, pero no pudiste incluya la fuente con sus recursos y luego cópiela a la carpeta de la fuente en el directorio de Windows?

Cuestiones relacionadas