DLLCall in/aus undokumentierter DLL

  • Hallo Leute,
    ich möchte gerne die (undokumentierte) Funktion "InstallFontFile" aus der "%windir%\system32\fontext.dll" bzw. "%windir%\SysWOW64\fontext.dll" benutzen um einen
    Font (ttf, otf, pfm) "elegant" in Win7x32x64 zu installieren. Dazu gibt es einen Artikel unter: http://stackoverflow.com/questions/7563…0-setup-project
    In diesem ist auch ein Stück C# Code welcher das anscheinend ermöglicht. Im folgenden der relevante Auszug daraus:

    Code
    [DllImport("fontext.dll", CharSet = CharSet.Auto)]private static extern void InstallFontFile(IntPtr hwnd, string filePath, int flags);string path = @"c:\Windows\Fonts\MyFont.pfm";InstallFontFile(IntPtr.Zero, path, 0);

    Ich habe nun versucht das Ganze mal nach AutoIt zu konvertieren, bis dato aber ohne Erfolg:

    [autoit]

    #RequireAdmin
    InstallFontFile("c:\windows\fonts\synthetique_tt.ttf")
    Func InstallFontFile($ff)
    local $fedll = DllOpen("fontext.dll")
    DllCall($fedll,"none","InstallFontFile","hwnd",0,"str",$ff,"int",0) ; @error gibt 0 zurück!!!!
    DllClose($fedll)
    EndFunc

    [/autoit]


    PS: Im obigen Beispiel ist der Font vorher bereits in Fonts-Verzeichnis kopiert worden. "InstallFontFile" sollte eigentlich nur dem System dauerhaft den Font bekannt machen (Registry bzw. Sendmessage).
    Meine Annahme ist nun, dass ich eventuell ein Problem mit den DLLCall-Parametern habe(obwohl @error == 0), hat jemand eine Idee?


    Vielen DANK!

  • Es gibt bereits eine Funktion dafür im englischen Forum:

    [autoit]

    #Include <WinAPIEx.au3>

    [/autoit][autoit][/autoit][autoit]

    ConsoleWrite(_FontInstall('MyFont.ttf') & @CR)

    [/autoit][autoit][/autoit][autoit]

    Func _FontInstall($sFile)

    [/autoit][autoit][/autoit][autoit]

    Local $Font, $Name, $Path

    [/autoit][autoit][/autoit][autoit]

    $Name = _WinAPI_GetFontResourceInfo($sFile, 1)
    If @error Then
    Return SetError(1, 0, 0)
    EndIf
    $Name &= ' (TrueType)'
    $Font = StringRegExpReplace($sFile, '^.*\\', '')
    If Not RegWrite('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts', $Name, 'REG_SZ', $Font) Then
    Return SetError(2, 0, 0)
    EndIf
    $Path = _WinAPI_ShellGetSpecialFolderPath($CSIDL_FONTS)
    If Not FileCopy($sFile, $Path) Then
    RegDelete('HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts', $Name)
    Return SetError(3, 0, 0)
    EndIf
    If Not _WinAPI_AddFontResourceEx($Path & '\' & $Font, 0, 1) Then
    Return SetError(4, 0, 0)
    EndIf
    Return 1
    EndFunc ;==>_FontInstall

    [/autoit]

    Die lässt sich einfach benutzen ;)

  • Vielen Dank für eine Hilfe alleine es gibt da ein paar Dinge die leider alles andere als optimal sind.
    Die _WinAPI_GetFontResourceInfo() ist mir bekannt, sie hat allerdings einen ganz großen Nachteil...
    sie liefert den Schriftgrad des Fonts in Anhängigkeit der Regionaleinstellung zurück, genau so wie er der Schriftartenvorschau angezeigt wird.
    In der Registry steht aber leider immer (fast) genau der Name, der auch im File steht. (die Erläuterung von (fast) würde hier zu weit gehen)
    Beispiel:
    %windir%\Fonts\arialbi.ttf --> heißt in der Registry "Arial Bold Italic (TrueType)"
    wenn ich die Datei mit _WinAPI_GetFontResourceInfo() ermittle --> "Arial Fett Kursiv (TrueType)"

    Momentan installiere ich Fonts mit der Shell.Application.CopyHere Funktion.
    Nachteile: dauert ewig, Statusfenster beim kopieren/installieren, geniales Verhalten bei Fontdateinamen mit Underscore(s) am Ende.
    Deswegen wollte ich das mit der InstallFontFile mal testen, ich werd mir mal die Express Edition von C# installieren und schauen ob der Code überhaut geht.
    So wie es aussieht gibt es als einzige effektive Installations-Methode wirklich nur einen Registry/File Snapshot.


    Danke trotzdem nochmal!

    • Offizieller Beitrag

    Die _WinAPI_GetFontResourceInfo() ist mir bekannt, sie hat allerdings einen ganz großen Nachteil...
    sie liefert den Schriftgrad des Fonts in Anhängigkeit der Regionaleinstellung zurück


    Versuch doch folgende Lösung: Switche die Regionaleinstellung für die Dauer der Abfrage auf US / EN. Dann sollte das identsich sein. Die Regionaleinstellungen findest du im Schlüssel "HKCU\Control Panel\International". Einfach mal per Hand wechseln und die Änderungen in den Werten dann als Parameter für das automatische Switchen verwenden.