Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Am Server installierte Schriftarten auslesen

Geschrieben von: Christoph Wille
Kategorie: Komponenten

This printed page brought to you by AlphaSierraPapa

Im heutigen Artikel beschäftigen wir uns mit einem eher etwas "eigenartigem" Thema, nämlich dem Auslesen der am Web Server installierten Schriftarten. Dies ist nämlich ein gutes Thema um die Nützlichkeit von C++ Kenntnissen zur Komponentenerstellung zu illustrieren.

Das Aufzählen von Schriften kann unter C++ relativ einfach mit der EnumFontFamiliesEx Funktion bewerkstelligt werden. Diese Funktion benötigt zum Aufzählen eine Callback Funktion, und diese ist eben am leichtesten mit C++ zu bewerkstelligen. Diejenigen, die die Komponente nur verwenden wollen, können den nächsten Abschnitt gerne überspringen - es werden C++ und ATL Kenntnisse vorausgesetzt!

Die EnumFonts Komponente

Für die EnumFonts Komponente habe ich mich aus Gewohnheit für eine ATL Komponente entschieden, und aus Faulheit, für einige Belange in der Komponente die MFC zu verwenden. Zuallererst brauche ich ein ATL Project (EnumFonts), und die Auswahl der entsprechenden Optionen im Wizard:

Damit habe ich ein "nacktes" ATL Projekt, ohne Objekte, die von außen angreifbar wären. Um diesen Umstand zu ändern, klickt man mit der rechten Maustaste auf das Projekt, und wählt New ATL Object aus dem Kontextmenü. Es stehen einige ATL Objekte zur Auswahl, wir benügen uns mit dem Simple Object.

Die Namensgebung erfolgt ebenso simpel: InstalledFonts - und der Rest passt, wie er ist.

Im Prinzip ist unser Projekt durch die neue Klasse noch nicht um vieles funktionaler geworden - dazu müssen wir unsere Methode einfügen, die uns die Schriftliste zurückliefert:

Jetzt haben wir alle Wizards ausgereizt, jetzt heißt es selbst Hand anlegen und programmieren. Das Enumerieren von Fonts geschieht mit Hilfe der EnumFontFamiliesEx Funktion des WIN32 APIs. Wir müssen also diese in der Methode RetrieveFontList entsprechend aufrufen:

STDMETHODIMP CInstalledFonts::RetrieveFontList(BSTR *strFontList)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  // TODO: Add your implementation code here{
  HDC hDC = ::GetDC(NULL);
  LOGFONT lf;
  CString strEnumerateFont;

  // initialise the LOGFONT structure for the font enumeration
  lf.lfCharSet = ANSI_CHARSET;
  *lf.lfFaceName = 0;
  lf.lfPitchAndFamily = 0;
  
  EnumFontFamiliesEx(hDC, 
    &lf, 
    (FONTENUMPROC)EnumFontFamExProc, 
    (LPARAM)(&strEnumerateFont), 
    0);

  ::ReleaseDC(NULL,hDC);

  *strFontList = strEnumerateFont.AllocSysString();
  return S_OK;
}

Viel Lärm um nichts, könnte man sagen. Wir initialisieren alle Datenstrukturen, und dann rufen wir EnumFontFamiliesEx auf. Dabei ist der Parameter EnumFontFamExProc interessant, da dieser eine Callback Funktion ist, die wir zur Verfügung stellen müssen:

int CALLBACK EnumFontFamExProc(
                 ENUMLOGFONTEX *lpelfe,    // logical-font data
                 NEWTEXTMETRICEX *lpntme,  // physical-font data
                 DWORD FontType,           // type of font
                 LPARAM lParam             // application-defined data
)
{
  CString *pEnumerateFont = (CString*)lParam;
  *pEnumerateFont += CString("|") + ((char *)lpelfe->elfLogFont.lfFaceName);
  return 1;
}

Diese Callback Funktion wird für jede installierte Schrift aufgerufen. Und hier kommt mir meine Faulheit der Verwendung der MFC zu Gute: Als Applikations-spezifischen Parameter habe ich die String-Klasse CString übergeben, und bei jedem Aufruf hänge ich die neu gefundene Font einfach an das Ende der Fontliste an (getrennt durch "|").

Das Font-Trennzeichen "|" können wir dann in ASP verwenden, um aus dem String mit Hilfe der Split Funktion ein wunderbar zu verwendendes Array zu erstellen.

Die Komponente ist nun fertig programmiert - wir müssen sie nur noch kompilieren. Danach muß sie noch auf den Web Server kopiert und registriert werden:

regsvr32.exe EnumFonts.dll

Verwenden der Komponente

Die Anwendung der Komponente ist extrem einfach, da sie ja nur eine Methode, nämlich RetrieveFontList zur Verfügung stellt. Die kürzeste Version wäre somit:

Set xObj = Server.CreateObject("EnumFonts.InstalledFonts")
strFonts = xObj.RetrieveFontList() 
Response.Write strFonts

Damit wollen wir uns aber nicht zufrieden geben - es muß schon mehr hermachen. Der folgende Screenshot zeigt das Ergebnis, das ich erreichen möchte:

Beschäftigen wir uns zuallererst mit dem Befüllen der Combobox:

Am Server installierte Schriften: 
<select name="InstalledFonts" onChange="changeFont();">
<%
Dim xObj, strFonts, i, arrFonts
If "" = Application("InstalledFonts") Then
    Set xObj = Server.CreateObject("EnumFonts.InstalledFonts")
    strFonts = xObj.RetrieveFontList()  ' diese Liste ist nicht sortiert!
    Set xObj = Nothing
    Application("InstalledFonts") = strFonts
Else
    strFonts = Application("InstalledFonts")
End If

arrFonts = Split(strFonts, "|")
For i = 0 To UBound(arrFonts)
    Response.Write "<OPTION>" & arrFonts(i) & "</OPTION>" & vbCrLf
Next
%>
</select>

Ich habe mir eine kleine Optimierung nicht verkneifen können - wozu soll die Fontliste mit jedem Seitenaufruf neu generiert werden? Eine Kopie innerhalb der ganzen Application reicht völlig aus, da sich die Fontliste am Server wohl doch nicht so schnell ändern wird...

Jetzt fehlt nur noch der JavaScript-Teil, den ich zum visuellen Aufpeppen mit hineingenommen habe:

<script language="JavaScript">
// <!--
function changeFont()
{
  var nSelectedIndex, strFontName;
  nSelectedIndex = document.all.InstalledFonts.selectedIndex;
  strFontName = document.all.InstalledFonts.options[nSelectedIndex].text;
  document.all.myTestElement.style.fontFamily = strFontName;
}
// -->
</script>

...

<div id="myTestElement">
Willkommen in der wunderbaren Welt der Schriften. Dieser Beispielabsatz
dient zum Herumspielen mit der Combobox - allerdings nur dann sinnvoll,
wenn der Server gleichzeitig der Client ist &lt;g /&gt;...
</div>

Schlußbemerkung

Damit hätten wir eine Komponente, mit der man am Server installierte Schriften einfach Auflisten kann. Wichtig ist, daß die Liste der Schriften nicht sortiert ist - aber das Sortieren von Arrays kann man in anderen Artikeln auf AspHeute nachlesen!

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010126.zip

Verwandte Artikel

Sortieren von Arrays in VBScript
http:/www.aspheute.com/artikel/20000906.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.