|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 19.04.2006, 20:17 Titel: [Win API] Standard-Dateidialoge |
|
|
Wenn man einen Leveleditor oder ähnliches mit der Win-API programmieren möchte, ist es sehr praktisch wenn man den Windowsstandard Dateidialog benutzen kann. Der Aufwand ist realtiv gering, aber das Ergebnis wirkt professionell.
Hier mal ein Beispiel um Dateien zu laden:
CPP: | char Dir[128], Name[128];
ZeroMemory(Name, sizeof(Name));
GetModuleFileName(NULL, Dir, 128);
OPENFILENAME Filename;
ZeroMemory(&Filename, sizeof(OPENFILENAME));
Filename.lStructSize=sizeof(OPENFILENAME);
Filename.lpstrInitialDir=Dir;
Filename.lpstrFile=Name;
Filename.nMaxFile=128;
if(GetSaveFileName(&Filename))
SaveFile(Filename.lpstrFile);
|
Man ruft also einfach die Funktion GetSaveFileName auf und übergibt als Parameter einen Zeiger auf eine OPENFILENAME-Struktur. Diese hat ziemlich viele Elemente, weswegen hier mehr oder weniger eine Minimallösung vorgestellt wird.
Wichtig ist hier der Name-String, der hinterher den Dateinamen enthält. Man muss in der Openfilename Struktur vorher den Speicherort und die Größe des Buffers angeben, damit das ganze funktioniert.
Der Dir-String dient hier lediglich dazu, das der Dateidialog dort startet, wo sich die exe-Datei befindet. Man kann auch jedes andere Verzeichnis angeben das einem passt.
Der Rückgabewert gibt an ob auch eine Datei ausgewählt wurde. Man kann ja schließlich auch auf "Abbrechen" klicken, und dann darf natürlich nichts gespeichert oder geladen werden.
Für das Laden von Dateine benutzt man exakt die selbe Struktur, nur heißt die Funktion jetzt GetOpenFileName. Die unterschiede sind minimal, beide geben schließlich einen Dateinamen zurück, nur will man beim öffnen von Dateien vieleicht nicht auf einen "Speichern"-Button klicken.
Detailiertere Beschreibungen findet man in der MSDN, einfach "OPENFILENAME", "GetOpenFileName" oder "GetSaveFileName" eingeben. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
Dragon Super JLI'ler
Alter: 38 Anmeldedatum: 24.05.2004 Beiträge: 340 Wohnort: Sachsen Medaillen: Keine
|
Verfasst am: 19.04.2006, 20:28 Titel: |
|
|
etwas kurz für ein Tutorial, vieleicht könntest du es noch etwas mehr ausbauen _________________ Nur wenn man ein Ziel sieht, kann man es auch treffen.
___________
Mein Leben, Freunde und die Spieleentwicklung |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 19.04.2006, 20:44 Titel: |
|
|
Jo, das ist so ein wenig zwischen FAQ/Tutorial. Ich werd bei Gelegenheit mal ein paar mehr Sachen erläutern, zum Beispiel Standarddateiendung, und Filter zur Dateiauswahl, was beides relativ nützlich ist. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
FH Super JLI'ler
Alter: 36 Anmeldedatum: 16.10.2004 Beiträge: 438
Medaillen: Keine
|
Verfasst am: 26.04.2006, 18:52 Titel: |
|
|
/me erweiteret das jetzt mal ein bisschen:
Die Struktur OPENFILENAME kann aber noch mehr:
Zum Beispiel kann man einen Filter definieren, dass z.B. nur Dateien mit der Endung .txt angezeigt werden. Man kann auch mehrere solcher Filter definieren. Der User kann dann zwischen der verschiedenen Filtern wählen.
Den Filter gibt man folgendermaßen an:
CPP: | Filename.lpstrFilter="Text-Dateien\0*.txt\0Alle Dateien\0*.*\0"; |
Es ist eigentlich ganz simpel: Man hängt die verschiedenen Filter einfach hintereinander, und trennt sie durch Null-Zeichen. Zuerst kommt eine Beschreibung des Filters (die kriegt der User angezeigt), dann folgt ein Nullzeichen, und nun kommt der String, nach dem gesucht wird. Ein "*" steht dabei allgemein für eine beliebige Zeichenkombination. Zum Abschluss kommt wieder ein Nullzeichen.
Wir haben hier im Beispiel also zwei Filter: Erstmal einen Filter, der alle Text-Dateien anzeigt, und dann einen Filter, der alle Dateien anzeigt. Ihr könnt auch gerne noch mehr Filter deklarieren, und diese einfügen.
Gruß
FH _________________ goto work, send your kids to school
follow fashion, act normal
walk on the pavement, watch T.V.
save for your old age, obey the law
Repeat after me: I am free |
|
Nach oben |
|
|
FH Super JLI'ler
Alter: 36 Anmeldedatum: 16.10.2004 Beiträge: 438
Medaillen: Keine
|
Verfasst am: 26.04.2006, 19:15 Titel: |
|
|
Wenn wir schon beim Thema Standard-Datei-Dialoge sind:
Man kann auch nur nach Ordner suchen lassen.
Ihr müsst dazu die Datei "shlobj.h" includen.
Nun zum eigentlichen Code für das Suchen nach Ordnern:
CPP: | BROWSEINFO bi;
LPITEMIDLIST pItemIDList;
char Path[MAX_PATH+1];
ZeroMemory(&bi,sizeof(BROWSEINFO));
bi.lpszTitle="Bitte wählen sie einen Ordner aus.";
pItemIDList=SHBrowseForFolder(&bi);
SHGetPathFromIDList(pItemIDList,Path); |
Man macht also folgendes: Man nutzt die Struktur BROWSEINFO. Deren Member lpszTitle übergibt man einen Text, der über dem eigentlich Feld zur Suche nach den Ordnern angezeigt wird.
Dann ruft ihr SHBrowseForFolder auf. Dies gibt einen Zeiger auf ein ITEMIDLIST-Objekt zurück, oder 0 falls der User abbrechen gedrückt hat. Mit diesem Zeiger auf ein ITEMIDLIST-Objekt können wir vorerst mal überhaupt nix anfangen. Deshalb werfen wir es erstmal der Funktion SHGetPathFromIDList vor. Diese Funktion übernimmt noch einen Zeiger auf ein char-Array. Dieses Array enthält danach die Pfadangabe zum vom User ausgewählten Ordner. Das char-Array muss mindestens MAX_PATH lang sein (das ist eine in den untiefen der Windows-include-Dateien definierte Konstante).
Der Dialog sieht dann im Endeffekt so aus:
So, dass wars erstmal.
Wer jetzt noch etwas daran zu meckern hat, dass ich Ordner statt Verzeichniss schreibe: Verzeichniss is so lang, und ich bin schlichtweg tippfaul.
Gruß
FH _________________ goto work, send your kids to school
follow fashion, act normal
walk on the pavement, watch T.V.
save for your old age, obey the law
Repeat after me: I am free
Zuletzt bearbeitet von FH am 23.07.2011, 23:01, insgesamt 3-mal bearbeitet |
|
Nach oben |
|
|
fast hawk Senior JLI'ler
Anmeldedatum: 15.07.2005 Beiträge: 237 Wohnort: Freiburg Medaillen: Keine
|
Verfasst am: 27.04.2006, 17:53 Titel: |
|
|
\me gibt auch noch seinen senf dazu:
Wenn man bei GetSaveFileName Filter benutzt wird in Filename.nFilterIndex der Filter gespeichert.
d.h.:
wenn der Filter so aus sieht:
CPP: | Filename.lpstrFilter="Text-Dateien\0*.txt\0Alle Dateien\0*.*\0"; |
und nacher Filename.nFilterIndex == 2 ist, hat derjenige "Alle Dateien" ausgwählt,
wenn Filename.nFilterIndex == 1 ist "Text-Dateien".
Für wenn es verwireen sollte es beginnt hier wirklich mit 1 nicht wie sonst oft mit 0. Ebenso wird der Dateityp nicht automatisch hinten angehenkt das muss händisch gemacht werden.
siehe auch: http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/aboutcommondialogboxes/openandsaveasdialogboxes.asp?frame=true _________________ Jetziges Projekt: The Ring War
Status: 40%
-----------------------------------
Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.
--
Lucius Annaeus Seneca (4)
röm. Philosoph, Dramatiker und Staatsmann |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
|
Nach oben |
|
|
fast hawk Senior JLI'ler
Anmeldedatum: 15.07.2005 Beiträge: 237 Wohnort: Freiburg Medaillen: Keine
|
Verfasst am: 30.04.2006, 18:52 Titel: |
|
|
Nein macht es nicht es setzt nur den aktullen pfad auf deinen Auswahl Pfad so wie er bei jedem Start deines Programmes auf deinen Programmpfad gesetzt wird. Den kannst du auch über die Eingabeaufforderung umsetzen(D:,C:,I:,E;(darf leider keinen Doppelpunkt machen weil es sonst ein Smile wird ). Wurd aber in dem anderen thread ja auch schon gesagt!! _________________ Jetziges Projekt: The Ring War
Status: 40%
-----------------------------------
Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.
--
Lucius Annaeus Seneca (4)
röm. Philosoph, Dramatiker und Staatsmann |
|
Nach oben |
|
|
FH Super JLI'ler
Alter: 36 Anmeldedatum: 16.10.2004 Beiträge: 438
Medaillen: Keine
|
Verfasst am: 01.05.2006, 09:38 Titel: |
|
|
Allerdings hat die Struktur OPENFILENAME einen Member namens Flags. Wenn man ihn auf OFN_NOCHANGEDIR setzt, wird der Pfad nicht verändert.
Es gibt da übrigens ebenfalls noch ein paar sehr schöne andere Flags!
Gruß
FH _________________ goto work, send your kids to school
follow fashion, act normal
walk on the pavement, watch T.V.
save for your old age, obey the law
Repeat after me: I am free |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 09.08.2006, 12:45 Titel: |
|
|
Laut MSDN muss bei Filtern der letze Filter mit zwei NULL zeichen abgeschlossen werden. Ist ja auch logsich, woher sollte Windows sonst wissen, wo der String aufhört, wenn es nach einem NULL-Zeichen noch weiter geht?
MSDN hat Folgendes geschrieben: |
lpstrFilter
Pointer to a buffer containing pairs of null-terminated filter strings. The last string in the buffer must be terminated by two NULL characters.
|
_________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
User_User JLI'ler
Anmeldedatum: 05.08.2004 Beiträge: 137
Medaillen: Keine
|
Verfasst am: 25.02.2007, 20:24 Titel: |
|
|
Wenn ich den Dateidialog in einem Programm verwende, welches 3D-Grafik verwendet (z.B. Kapitel 27 Triangle3D, muss ich das Programm im Ordner Debug direkt mittels Doppelklick starten.
Beweg ich das Fenster des Dateidialogs, dann werden freigewordene Flächen des darunterliegenden Fensters mit einer einheitlichen Hintergrundfarbe dargestellt.
Wir erreiche ich es, dass die ursprüngliche 3D-Hintergrundgrafik wiederhergestellt wird? |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
|
Nach oben |
|
|
Otscho Super JLI'ler
Alter: 36 Anmeldedatum: 31.08.2006 Beiträge: 338 Wohnort: Gummibären-Gasse Medaillen: Keine
|
Verfasst am: 28.01.2009, 18:25 Titel: |
|
|
Ich hab mal nach Petzold folgende OPENFILENAME implementierung ausprobiert:
Das erstellen einer Struktur:
CPP: | static OPENFILENAME ofn;
static TCHAR szFilter[] = __TEXT("MelioRay Xml Dateien (*.mrx)\0*.MRX\0") \
__TEXT("Alle Dateien (*.*)\0*.*\0\0");
static TCHAR Dir[128], Name[128];
GetModuleFileName(NULL, Dir, 128);
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = globalInstance;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = NULL;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrInitialDir = Dir;
ofn.lpstrTitle = NULL;
ofn.Flags = 0;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = TEXT("mrx");
ofn.lCustData = 0L;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL; |
Und dann der Aufruf des Dialogfensters zum öffnen einer Datei:
CPP: | ofn.hwndOwner = hwnd;
ofn.lpstrFile = Name;
ofn.lpstrFileTitle = TEXT("mrx");
ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT;
GetOpenFileName(&ofn); |
Leider kommt es bei mir hier immer zu einem Programmabsturz, wegen eines ungültigen Speicherzugriffs.
Weiß jemand, was ich falsch gemacht habe ?
Ich verwende Windows Vista und bin mir nicht sicher, welche Dinge der Struktur ich hier mit einer "NULL" abfertigen darf.
Das Debuggen hat mir leider auch Nichts gebracht. |
|
Nach oben |
|
|
FH Super JLI'ler
Alter: 36 Anmeldedatum: 16.10.2004 Beiträge: 438
Medaillen: Keine
|
Verfasst am: 28.01.2009, 19:36 Titel: |
|
|
Otscho hat Folgendes geschrieben: | CPP: | ofn.lpstrFile = NULL;
ofn.nMaxFile = MAX_PATH;
|
|
lpstrFile darf nicht NULL sein, denn in den Buffer, den du da angibst, wird Pfad der Datei reingeschrieben. Sozusagen die Rückgabe.
Und nMaxFile sollte die Länge des Buffers in lpstrFile enthalten.
Nebenbei sollte der Buffer für lpstrFile mit einem \0 beginnen.
Ansonsten würde ich dir noch empfehlen, OFN_NOCHANGEDIR in den Flags zu setzen, denn sonst verändert GetOpenFileName den aktuellen Pfad zu dem Pfad, der geöffnet wurde, was später (z.B. beim nachladen von DLLs) gerne zu sehr merkwürdigem Verhalten führt.
Überhaupt würde ich dir wegen den Flags noch zu einem Blick in die Doku raten, je nachdem, ob man ein File zum lesen oder zum schreiben öffnen will, gibt es da noch einige nette Flags.
Gruß
FH _________________ goto work, send your kids to school
follow fashion, act normal
walk on the pavement, watch T.V.
save for your old age, obey the law
Repeat after me: I am free |
|
Nach oben |
|
|
Otscho Super JLI'ler
Alter: 36 Anmeldedatum: 31.08.2006 Beiträge: 338 Wohnort: Gummibären-Gasse Medaillen: Keine
|
Verfasst am: 29.01.2009, 17:37 Titel: |
|
|
Ich hab mal deinen Ratschlag befolgt FH. und für nMaxFile = 128 eingesetzt. lpstrFile hab ich ja vor dem Öffnen auf den Buffer "Name" gesetzt. Wobei ich das erste Zeichen auf \0 gestzt habe, hat das nichts bewirkt als dass ein komisches Zeichen am als vorwahl datei angezeigt wurde.
Leider hat das alles nichts gebracht.
Kann es was ausmachen, dass ich den "Datentyp" TCHAR verwende ? |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|