Archiv verlassen und diese Seite im Standarddesign anzeigen : [RMXP / RGSS]: Datei kopieren...?
Hallo Leute,
ich verwende in meinem Projekt eine eigene Schriftart (ttf), die nicht im Standard-Windows-Schriftsatz enthalten ist. Das ist an sich kein Problem, die Font ist Freeware und ich kann sie beim Spiel-Download dazugeben. Allerdings wäre es nett, wenn man die .ttf-Datei aus dem Spielverzeichnis per Skript einfach in den Schriften-Ordner von Windows kopieren könnte. Leider habe ich in der Hilfe vom RPG-Maker in der File-Klasse nur Methoden zum ÖFFNEN von Files gefunden, nicht zum verschieben oder kopieren. Es gibt die Standard-Bibliothek "ftools" für Ruby, aber die ist leider nicht im Lieferumfang des RMXP enthalten ^_^'
Gibt es Vorschläge wie man soetwas machen kann oder soll ich beim Download einfach dazuschreiben dass man sich doch bitte die Font kopieren soll?
Gruß,
Alan
MagicMagor
11.01.2011, 14:10
Die einfachste Möglichkeit eine Datei zu kopieren wäre es einfach sie zu öffnen und die Bytes in die neue Datei schreiben.
Könnte (in Pseudo-code) etwa so aussehen:
quelle = open(quelldatei, 'r')
target = open(zieldatei, 'w')
repeat
byte = quelle.read()
if byte==EOF
break
else
target.write(byte)
end
end
Alternativ gibt es vermutlich eine "Datei kopieren"-Funktion in der Windows-API und auf diese kannst du im XP zugreifen (dazu gibt es die Win32API-Klasse in Ruby).
Da es allerdings um eine Schriftart gehst, wirst du mMn um die Windows-API nicht herumkommen, da ein Kopieren der Datei in den Fonts-Ordner alleine nicht ausreicht um die Schriftart im XP nutzbar zu machen. Ich weiß das irgendwann mal hier jemand genau dieses Problem hatte und ich habe damals eine API-Funktion ausgegraben, die die Font bei Windows registriert. Die Kombination, "Datei kopieren" und dann "Schriftart registrieren" war genug um die Schriftart nutzbar zu machen.
Leider finde ich den Thread nicht mehr aber ich hab mal in der WinAPI-Referenz rumgestöbert:
CopyFile (http://msdn.microsoft.com/en-us/library/aa363851%28v=VS.85%29.aspx)
AddFontResource (http://msdn.microsoft.com/en-us/library/dd183326%28v=VS.85%29.aspx)
Wie du die Win32API-Klasse nutzt um diese Funktionen aufzurufen, erfährst du in der Ruby-Dokumentation (Nicht die in der Hilfe-Datei des Makers, such eine vollständige im Netz)
Edit:
Tatsächlich würde ich ausprobieren ob das AddFontResource am Anfang ausreicht, dann muss der Spieler nicht seinen Fonts-Ordner mit Dateien zukleistern, von denen er später nicht mehr weiß wo sie herkommen.
Natürlich gebietet der gute Ton es dann auch, das du beim Beenden des Spiels die Font-Resource wieder entfernst. Klick dich in der API-Referenz mal rum, es sollte auch sowas wie "RemoveFontResource" geben.
Hi,
danke für's Rauskramen - ich hatte bisher noch nie mit der Win32API-Anbindung unter Ruby zu tun, aber da ich auch ein wenig C beherrsche sollte es hoffentlich klar gehen (falls nicht werde ich mich vertrauensvoll an euch Leute hier wenden ^_^).
Wegen dem "Font-Registrierung beim Beenden des Programms löschen"... nun: wenn der Spieler das Programm beendet, wie es gehört - okay. Das lässt sich sicher mit einem entsprechenden API-Befehl regeln. Aber wenn er einfach ALT+F4 drückt oder das RGSS-Player-Fenster manuell schließt, dann hat man da über Ruby meines Wissens nach keine Chance, das irgendwie abzufangen und die Font per Interrupt Handler o.Ä. wieder zu löschen. Außerdem besteht ja ENTFERNT die Möglichkeit dass der User diese Font tatsächlich auch selbst benutzt und sie bereits vor dem Spielen meines Projektes installiert hatte - in so einem Fall möchte ich sie ihm nicht unter der Nase weglöschen... (besides: das ist Zukunftsmusik ;) Im Moment muss ich sie einfach nur mal registriert bekommen!)
Anyway - ich freue mich immer wieder darüber welch kompetente und schnelle Hilfe man hier bekommt, vielen Dank dafür ;)
Gruß,
Alan
Das vorzeitige Beenden des Programms über den Exitbutton wirft die Exception SystemExit, lässt sich also auch abfangen. Es gibt aber afair auch WinAPI-Funktionen, mit denen man Fonts temporär registrieren kann (die sind dann beim nächsten Systemstart wieder weg). Allerdings hatte ich mal versucht Fonts automatisch registrieren zu lassen und hatte das nicht hinbekommen. Man musste immer das Spiel einmal neustarten, ehe die Änderung wirksam war. Ich weiß allerdings nicht mehr woran das lag (ist schon länger her). Eventuell hab ich mich auch einfach nur zu blöd angestellt.
Hi Leute,
ich hab mich ein wenig umgeschaut - ich denke ich bekomme langsam eine ungefähre Vorstellung davon, wie der Win32API-Kernel unter Ruby zu verwenden ist. Auch hab ich beim Durchforsten des Kernels diese Funktion hier gefunden, die wie geschaffen für unsere Zwecke aussieht:
http://msdn.microsoft.com/en-us/library/dd183327(v=vs.85).aspx
Das klingt doch ziemlich gut was meint ihr? Wenn man für den "fl"-Parameter FR_PRIVATE angibt, so wird die Font sogar aus der Registry genommen sobald der aufrufende Prozess terminiert, egal wie. Zusätzlich spielt es so keine Rolle mehr, ob die Font vorher schon am System war oder nicht (Private Registrierung überdeckt öffentliche). Nur hab' ich noch ein kleines theoretisches Problem mit dem Win32API-Kernel in Ruby. Da werden die Argumenttypen ja am Anfang als String-Array angegeben, wobei "L" für Zahlen steht, "P" für Pointer, "V" für void etc. - aber was bitte ist das Kürzel für DWORD? Ist ein DWORD ein String? (sry für die Noob-Frage, mit C++ hatte ich bislang noch nichts zu tun)
Auch wenn ich es jetzt noch nicht getestet habe, ich glaube wir sind schon recht nahe an der Lösung dran ;)
Gruß,
Alan
Hi Leute,
ich hab es mal geschafft, den Call erfolgreich abzusetzen. Hier das entsprechende Code-Fragment:
@kernel = Win32API.new('Gdi32', 'AddFontResourceEx', ['p', 'l', 'p'], 'i')
result = @kernel.call('Sansation_Regular.ttf', 16, 0)
p result
Ich weiß dass der Call erfolgreich war, weil das "p result" genau "1" ausgibt - in der Dokumentation der Kernel-Funktion steht, dass sie die Anzahl der erfolgreich geddeten Fonts zurückgibt, das stimmt also genau.
Das Problem, das ich jetzt noch habe ist schlicht und ergreifend, dass die Font im RPG-Maker nicht erkannt wird, wenn ich nach obigem Code schreibe:
p Font.exist?("Sansation")
p Font.exist?("sansation")
p Font.exist?("Sansation_Regular")
... alle drei calls printen "false" auf den Bildschirm. Habt ihr eine Idee woran es liegen könnte? Ich teste hier inzwischen weiter...
Gruß,
Alan
EDIT: Es ist egal, ob ich die Font per "AddFontResource" oder "AddFontResourceEx" hinzufüge - der Call ist erfolgreich (liefert 1 zurück), die Font ist laut RPG-Maker aber tortzdem nicht vorhanden.
EDIT2: Ok, das ist das VERRÜCKTESTE was ich in Zusammenhang mit Fonts jemals gesehen hab. Da mein Hinzufügen der Font ja 1 zurückgeliefert hat, der RPG-Maker aber keinen Zugriff auf die Font hatte, dachte ich so bei mir: "Ok, dann versuch' mal sie zu löschen, schauen ob das geht." Ich also folgenden Code geschrieben:
@kernelAdd = Win32API.new('Gdi32', 'AddFontResource', ['p'], 'i')
result = @kernelAdd.call('Sansation_Regular.ttf')
p result
@kernelRem = Win32API.new('Gdi32', 'RemoveFontResource', ['p'], 'i')
result = @kernelRem.call('Sansation_Regular.ttf')
p result
p Font.exist?("Sansation")
Die Resultate der Prints:
1
1
true
Wenn ich die Font nur adde, ist sie laut Font.exist? NICHT da. Wenn ich sie lösche (und das löschen erfolgreich ist, da 1 zurückgeliefert wird) und DANACH versuche, auf die Font zuzugreifen, ist sie DA. Ich meine - ich bin froh dass es überhaupt geht, aber DAS nenne ich seltsam. So richtig. Hat jemand eine Erklärung dafür?
MagicMagor
12.01.2011, 11:38
Man musste immer das Spiel einmal neustarten, ehe die Änderung wirksam war. Ich weiß allerdings nicht mehr woran das lag (ist schon länger her). Eventuell hab ich mich auch einfach nur zu blöd angestellt.
Naja, AddFontResource fügt die Font der System Font-Table hinzu, aber es ist möglich, dass Ruby diese nur zu Beginn abfragt und sich eine eigene interne Table daraus konstruiert. Somit wäre die Font erst nutzbar wenn Ruby die System Table erneut liest.
Vielleicht kann mit dieser Info aus der API-Referenz etwas anfangen:
Any application that adds or removes fonts from the system font table should notify other windows of the change by sending a WM_FONTCHANGE message to all top-level windows in the operating system. The application should send this message by calling the SendMessage function and setting the hwnd parameter to HWND_BROADCAST.
Das könnte die unter Ruby liegende Game.exe dazu veranlassen die System Table erneut zu lesen und vielleicht ist die Font dann auch direkt in Ruby nutzbar. Einen Versuch wäre es wert.
StarWolf
12.01.2011, 14:24
Soweit ich weiss, werden neue Schriften nicht gelesen, solange der Game Thread noch läuft.
SM = Win32API.new('user32', 'SendMessage', ['L'] * 4, 'L')
WM_FONTCHANGE = 0x001D
HWND_BROADCAST = 0xffff
SM.call(HWND_BROADCAST,WM_FONTCHANGE,0,0)
a = Thread.new
{
system('Game')
}
exit
Hi Leute,
ich habe folgendes festgestellt:
Wenn man eine Font per AddFontResource hinzufügt, so bekommt man die Bestätigung, dass es funktioniert hat, man kann sie aber noch nicht direkt anwenden. Öffnet man dann z.B. Microsoft Word, so ist die Font dort vorhanden. Startet man das RPG-Maker-Game dann neu, so ist die Font auch dort vorhanden (hätte man Word nicht zwischenzeitlich gestartet, wäre die Font auch im neu gestarteten RM-Projekt nicht da). Man kann eine Font so oft löschen wie man sie zuvor erzeugt hat.
Scheinbar handelt es sich wirklich um ein Update-Problem.
@StarWolf: Ich verstehe deinen Code, nur: wohin sollte man ihn einfügen? Gleich als allererstes in das oberste File des RMXP-Skript-Editors? Auf jeden Fall aber erst, NACHDEM man die Font erzeugt hat oder?
@All: Was mich wundert: bei AddFontResource steht dabei, dass man eben selbigen Broadcast wie er von StarWolf vorgezeigt wurde, machen soll - bei AddFontResourceEx hingegen nicht. Hinzu kommt, dass ich bei diesem Befehl für alle anderen Fenster ja nichts ändert, folglich kein Update nötig ist. Und muss ich wirklich mein EIGENES Fenster darüber informieren dass es jetzt eine zusätzliche Font gibt?
Gruß,
Alan
Powered by vBulletin® Version 4.2.3 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.