Ein Viewer für Schriftartfamilien

1. Aufgabe

Erstellen Sie eine WPF-Anwendung mit einem Fenster, das alle auf Ihrem Rechner installierten Schriftartfamilien anzeigt. Der Clou in der Darstellung ist, dass der Name jeder Schriftartfamilie in der korrespondierenden Schriftart dargestellt wird. Die Oberfläche der Anwendung sollte in etwa wie in Abbildung 1 gezeigt aussehen

Ein Viewer für Schriftartfamilien.

Abbildung 1. Ein Viewer für Schriftartfamilien.

2. Lösung

Eine recht einfache Lösung der Aufgabe besteht darin, ein UniformGrid-Steuerelement zu verwenden und dieses pro Zelle und Schriftart mit einem TextBlock-Steuerelement zu füllen. Dabei spielt es keine Rolle, dass nach dem unmittelbaren Start der Anwendung die Anzahl der installierten Schriftarten noch nicht bekannt ist. Die Zeilen und Spalten des UniformGrid-Steuerelements lassen sich zu einem späteren Zeitpunkt auch abändern (Listing 1):

01: <Window
02:     x:Class="WpfInstalledFontsDemoEx.MainWindow"
03:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
04:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
05:     Title="Installed Fonts Viewer" Height="900" Width="700">
06:     <UniformGrid Name="FontFamiliesGrid" Rows="0" Columns="0">
07:     </UniformGrid>
08: </Window>

Beispiel 1. UniformGrid-Steuerelement: XAML.


Das Abfüllen des UniformGrid-Steuerelements erfolgt in der Code-Behind-Datei, und hier wiederum mit zwei Methoden GetInstalledFonts und FillGrid. Die erste der beiden Methoden (GetInstalledFonts) bedient sich der Klasseneigenschaft SystemFontFamilies (aus der Klasse Font), um Zugang zu einem Enumerationsobjekt (ICollection<FontFamily>) zu erhalten. Da die Namen der Schriftartfamilien durch die Enumeration leider in nicht-alphabetischer Form aufgezählt werden, legen wir die Referenzen aller FontFamily-Objekte in einem Array vom Typ FontFamily[] ab, um dieses mit der Array.Sort zu sortieren. Das Resultat eines GetInstalledFonts-Aufrufs (Zeilen 29 bis 41 von Listing 2) ist somit ein sortiertes FontFamily[]-Array mit allen verfügbaren Schriftartfamilien.

Mit der zweiten Methode FillGrid (Zeilen 43 bis 64) befüllen wir das UniformGrid-Steuerelement. Wenn wir von fünf fest vorgegebenen Spalten in der Gitterrasterung ausgehen, können wir an Hand der Länge des FontFamily[]-Arrays berechnen, wie viele Zeilen wir im Gitter benötigen. Anschließend traversieren wir das Array Element für Element und legen pro Schriftart ein geeignetes TextBlock-Objekt an. Nicht zu vergessen ist dabei, dass wir nach dem Erzeugen und Initialisieren des TextBlock-Objekts seine Referenz dem Children-Containerobjekt hinzufügen müssen:

01: namespace WpfInstalledFontsDemoEx
02: {
03:     class FontsSortByNameHelper : IComparer<FontFamily>
04:     {
05:         public int Compare(FontFamily f1, FontFamily f2)
06:         {
07:             return (f1.Source.CompareTo(f2.Source));
08:         }
09:     }
10: 
11:     public partial class MainWindow : Window
12:     {
13:         private FontFamily[] fontFamiliesArray;
14: 
15:         public MainWindow()
16:         {
17:             this.InitializeComponent();
18:             this.Loaded += new RoutedEventHandler (this.MainWindow_Loaded);
19:         }
20: 
21:         // event handler
22:         private void MainWindow_Loaded(Object sender, RoutedEventArgs e)
23:         {
24:             this.GetInstalledFonts();
25:             this.FillGrid();
26:         }
27: 
28:         // private helper methods
29:         private void GetInstalledFonts()
30:         {
31:             ICollection<FontFamily> fontFamilies = Fonts.SystemFontFamilies;
32: 
33:             // copy enumeration of references into an array of references
34:             int numFonts = fontFamilies.Count;
35:             this.fontFamiliesArray = new FontFamily[numFonts];
36:             fontFamilies.CopyTo(this.fontFamiliesArray, 0);
37: 
38:             // sort font family names alphabetically
39:             FontsSortByNameHelper fontsComparer = new FontsSortByNameHelper();
40:             Array.Sort(this.fontFamiliesArray, fontsComparer);
41:         }
42: 
43:         private void FillGrid()
44:         {
45:             int cols = 5;
46:             int rows = this.fontFamiliesArray.Length / 5 + 1;
47: 
48:             this.FontFamiliesGrid.Rows = rows;
49:             this.FontFamiliesGrid.Columns = cols;
50: 
51:             for (int i = 0; i < this.fontFamiliesArray.Length; i++)
52:             {
53:                 FontFamily f = this.fontFamiliesArray[i];
54: 
55:                 TextBlock block = new TextBlock();
56:                 block.Background = new SolidColorBrush(Colors.LightGray);
57:                 block.Margin = new Thickness(1);
58:                 block.Text = f.Source;
59:                 block.FontFamily = f;
60:                 block.FontSize = 16;
61: 
62:                 this.FontFamiliesGrid.Children.Add(block);
63:             }
64:         }
65:     }
66: }

Beispiel 2. UniformGrid-Steuerelement: Code-Behind.