2011-08-10 15 views
5

Enumero la lista de familias de fuentes y me vinculo al cuadro combinado, el problema es cuando hay una fuente en el sistema que está dañada. Toda la aplicación se bloqueará. De todos modos, ¿puedo unirme a las familias de las familias del sistema pero puedo omitir la fuente que muestra errores?Error SystemFontFamilies al vincular al cuadro combinado

El siguiente código funciona bien si se comenta el enlace de la familia de fuentes en la plantilla del elemento.

<ComboBox x:Name="comboFonts" 
          Grid.IsSharedSizeScope="True" 
          Grid.Row="0" Grid.Column="1" 
          ItemsSource="{Binding Source={x:Static Member=Fonts.SystemFontFamilies}}" 
          SelectedItem="{Binding FontFamily, Mode=TwoWay}" 
          HorizontalAlignment="Stretch"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto" SharedSizeGroup="FontName"></ColumnDefinition> 
         <ColumnDefinition Width="*"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 
        <TextBlock Text="{Binding Source}" HorizontalAlignment="Left"/> 
        <Label FontFamily="{Binding FallbackValue=Verdana}" HorizontalAlignment="Right">Sample</Label> 
       </Grid> 

      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

el mensaje de error que se obtiene es la siguiente

Message=Input file or data stream does not conform to the expected file format specification. 
Source=PresentationCore 
StackTrace: 
    at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr) 
    at MS.Internal.Text.TextInterface.Font.CreateFontFace() 
    at MS.Internal.Text.TextInterface.Font.AddFontFaceToCache() 
    at MS.Internal.Text.TextInterface.Font.GetFontFace() 

por favor ayuda. THanks

Respuesta

4

Tuve el mismo problema. En un editor richtextbox, llené una especie de cinta con todas las familias de fuentes disponibles y adjunto esa fuente a ese elemento específico en el cuadro combinado para que el usuario vea de inmediato cómo se ve la fuente.

Cuando había una fuente en el sistema que no puede ser procesada por WPF, la aplicación se bloqueaba.

Al observar el stacktrace en el visor de eventos, noté que WPF intenta crear una instancia de un objeto del tipo System.Windows.Media.GlyphTypeface. Descubrí que, cuando intento crear una instancia de ese objeto yo mismo en el código (a través del tipo System.Windows.Media.Typeface) y la función TryGetGlyphTypeface() devuelve falso para mi configuración de fuente específica, esa fuente no se puede usar en WPF .

El código que resolvió el problema para mí:

foreach (FontFamily aFontFamily in Fonts.SystemFontFamilies) 
    { 
     // Instantiate a TypeFace object with the font settings you want to use 
     Typeface ltypFace = new Typeface(aFontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); 
     // Try to create a GlyphTypeface object from the TypeFace object 
     GlyphTypeface lglyphTypeFace; 
     if (ltypFace.TryGetGlyphTypeface(out lglyphTypeFace)) 
     { 
      // Creation of the GlyphTypeface worked. You can use the font 
      RibbonGalleryItem lribItem = new RibbonGalleryItem(); 
      lribItem.Content = aFontFamily.Source; 
      lribItem.FontFamily = aFontFamily; 
      lribGalCatFont.Items.Add(lribItem); 
     } 
    } 

Para evitar que este código debe ejecutarse cada vez que se carga el cuadro combinado (y eso es mucho porque está en un control de usuario), hago esto una vez al inicio de la aplicación y guarde la matriz de fuentes utilizables en una variable global.

+0

Sin embargo, tenga en cuenta que _normal_ para 'TryGetGlyphTypeface()' devuelve 'null' para familias de fuentes válidas, es decir, fuentes compuestas. El hecho de que devuelva 'null', eso no significa necesariamente que el archivo de fuente esté dañado (por supuesto, si confía en el' GlyphTypeface' en sí mismo, tendrá que trabajar más para conseguirlo, descomponiendo el compuesto fuente ... pero eso no es parte del problema aquí). –

0

Vale, 5 años más tarde, aquí hay otra solución:

Declarar este código en el Window.Resource:

<CollectionViewSource x:Key="MyFonts" Source="{Binding Source={x:Static Fonts.SystemFontFamilies}, Converter={StaticResource FontToSupportedGliphConverter}}"> 
    <CollectionViewSource.SortDescriptions> 
     <componentModel:SortDescription PropertyName="Source" /> 
    </CollectionViewSource.SortDescriptions> 
</CollectionViewSource> 

<Style x:Key="FontStyle"> 
    <Setter Property="Control.FontFamily" Value="{Binding .}" /> 
    <Setter Property="Control.FontSize" Value="16" /> 
</Style> 

<DataTemplate x:Key="FontTemplate"> 
    <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ScrollViewer.IsDeferredScrollingEnabled="True"> 
     <TextBlock Style="{StaticResource FontStyle}" Text="{Binding .}" ToolTip="{Binding .}" /> 
    </VirtualizingStackPanel> 
</DataTemplate> 

Y utilizar este Converter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    var list = value as IReadOnlyCollection<FontFamily>; 

    if (list == null) 
     return DependencyProperty.UnsetValue; 

    var returnList = new List<FontFamily>(); 
    foreach (FontFamily font in list) 
    { 
     //Instantiate a TypeFace object with the font settings you want to use 
     Typeface ltypFace = new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); 

     //Try to create a GlyphTypeface object from the TypeFace object 
     GlyphTypeface lglyphTypeFace; 
     if (ltypFace.TryGetGlyphTypeface(out lglyphTypeFace)) 
     { 
      returnList.Add(font); 
     } 
    } 

    return returnList; 
} 

y aplicar los recursos a la ComboBox:

<ComboBox x:Name="FreeTextFontComboBox" Margin="10,5" 
      MinWidth="100" MaxWidth="110" IsEditable="True" 
      ItemTemplate="{DynamicResource FontTemplate}" 
      SelectedItem="{Binding Source={x:Static prop:Settings.Default}, 
      Path=FreeTextFontFamily}"> 
    <ComboBox.ItemsSource> 
     <Binding Source="{StaticResource MyFonts}" /> 
    </ComboBox.ItemsSource> 
</ComboBox> 
+0

Ver nota en la otra respuesta. Este enfoque omitirá las fuentes compuestas válidas, además de las fuentes con archivos de fuentes corruptos. –

+0

¿Y qué podemos hacer para evitar faltar algunas fuentes? Envolviendo dentro del 'try catch' con el' returnList.Add (font); 'al final? –

+0

Como escribí en mi otro comentario, cuando te encuentras con una fuente compuesta, necesitas hacer más trabajo para obtener una fuente real. Es decir. examine su 'FamilyMaps' para encontrar una' FontFamily' apropiada que admita los puntos de código Unicode que está tratando de procesar. Y sí, en cuanto a las fuentes inválidas/corruptas, el manejo de excepciones puede abordar eso.Sin embargo, en mi humilde opinión, si va a hacer eso, al menos debe informar al usuario _que_la fuente causó la excepción, para que puedan reparar su sistema. –

Cuestiones relacionadas