Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi GetOpenFileNamePreview - unerwartetes Verhalten (https://www.delphipraxis.net/1591-getopenfilenamepreview-unerwartetes-verhalten.html)

Christian Seehase 11. Dez 2002 15:29


GetOpenFileNamePreview - unerwartetes Verhalten
 
Moin Zusammen,

da ich in D5 nicht die "schicken, neuen" Open- und Savedialoge habe, wie sie in D6 schon implementiert sind, wollte ich mir dafür mal Komponenten erstellen.
Da sich die API Aufrufe für die xxxPreview Versionen von denen ohne Preview nicht sonderlich unterscheiden sollen die der Vollständigkeit halber auch mit aufgenommen werden.

Soweit ist das auch alles kein Problem und funktioniert auch.

Beim Aufruf der Preview Versionen ergibt sich nur ein kleines Problem:
Es gibt keinen Preview, ausser es wird der Dialog im Old-Style aufgerufen, dann klappts.
Sobald als Flag OFN_EXPLORER verwendet wird entfällt das Preview Control.

Ich habe auch schon überprüft, dass die richtige Funktion aus der richtigen DLL aufgerufen wird.

Auch wenn ich für den Aufruf der Funktion nur lStructSize, lpstrFilter (=PChar('AVI'#00'*.avi'#00#00)), lpstrFile (=StrAlloc(MAX_PATH)), nMaxFile (=MAX_PATH) und Flags (=OFN_EXPLORER, bzw. OFN_EXPLORER or OFN_ENABLESIZING) setze, und den Rest vorher mit FillChar auf 0 gesetzt habe passiert das gleiche. An der Kompo scheints also nicht zu liegen.
(bei Flags = 0 wird auch hier der Old-Style Dialog korrekt aufgerufen).

Hat jemand eine Idee?

Luckie 11. Dez 2002 15:39

Die Openfilename-Striuktur hat unter WinNT eine andere Größe, siehe PSDK. Eventuell liegt es daran.

Christian Seehase 11. Dez 2002 15:58

Moin Luckie,

danke für den Tip, das hatte ich allerdings schon eingearbeitet bzw. berücksichtigt.
Ich hab's aber eben noch mal ausgetestet.
Wird die Grösse falsch angegeben (unter W2K) lässt er, naheliegender Weise, die PlacesBar weg. FlagsEx liegt ja im erweiterten Bereich.

Luckie 11. Dez 2002 16:03

Hm, hätte mir eigentlich klar sein sollen, dass du daran schon gedacht hast. :?

Mit ist nur nichts besseres eingefallen. :|

Christian Seehase 11. Dez 2002 17:11

Moin Luckie,

ich hätt's ja auch einfach übersehen haben können.
Was mich nur so überrascht:
Mit dem Old-Style Dialog klappts (aber wer will den schon :mrgreen:), nur mit dem heute üblichen nicht.
Auch googeln hat nichts gebracht, und MSDN auch nicht.
Es werden immer nur Beispiele gegeben, wie die Funktion eingebunden und aufgerufen wird, soweit war ich aber schon :?
Nirgends ein Hinweis auf eine Besonderheit für den "neuen Stil". :(

MathiasSimmack 11. Dez 2002 17:45

Ähem ... wo gibt´s diese Komponente, und wann ... Will mal neugierig schnüffeln und auch "neue" Dialoge verwenden. :wink: Die API-Deklaration würde mir auch schon reichen ... :)

Christian Seehase 11. Dez 2002 17:56

Moin Mathias,

nur um's noch mal deutlich zu machen:
Es geht um die Standard Open/Save Dialoge, die man ab D6 in der Komponentenpalette hat.
Die mit der PlacesBar links (Eigene Dateien...)

Das sind die APIs GetOpenFileName und GetSaveFileName.

Als Kompo wird's demnächst zum Test bereitstehen (wenn ich endlich weiss, was es mit diesem #&@%$@!! Preview Control auf sich hat)

MathiasSimmack 11. Dez 2002 18:25

Zitat:

Zitat von Christian Seehase
nur um's noch mal deutlich zu machen:
Es geht um die Standard Open/Save Dialoge, die man ab D6 in der Komponentenpalette hat.
Die mit der PlacesBar links (Eigene Dateien...)

Deutlich genug, Christian. Aber ich hab´s auch schon beim ersten Mal kapiert. Ich schwöre ... :)

Zitat:

Das sind die APIs GetOpenFileName und GetSaveFileName.
Heißt das, ich müsste im PSDK nach ein paar neuen Stilen gucken, und könnte das bereits benutzen?

Christian Seehase 11. Dez 2002 18:34

Moin Mathias,

das sind nur die zwei (vier) Funktionsdeklarationen (mit je einem Parameter), eine Struktur und einige Konstanten.
Vielleicht auch schon vollständig in D5 (Unit Commdlg) deklariert.
(bis auf die Preview Funktionen)
Ich importiere mir die halt lieber selber ;-)

MathiasSimmack 11. Dez 2002 18:40

Falls du die Ergänzung in "OPENFILENAME" meinst:
Code:
#if (_WIN32_WINNT >= 0x0500)
  void *        pvReserved;
  DWORD        dwReserved;
  DWORD        FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
Nein, die sind in Delphi 5 noch nicht vorhanden. Spontan würde ich sagen:
Code:
pvReserved: POINTER;
dwReserved: dword;
FlagsEx: dword;
Richtig? :?

Die "GetOpenFileNamePreview" habe ich zuerst in der COMDLG32.DLL gesucht, bin dann aber in der MSVFW32.DLL fündig geworden? Oder habe ich mich da vertan?

Ansonsten gucke ich mal, welche Konstanten neu sind, dann probiere ich mal, ob ich die Places-Bar zum Leuchten bringen kann.

Oder, falls du´s schneller da hast bzw. in meiner Spontanidee was korrigieren müsstest, wäre ich für einen Fix immer sehr dankbar. :)

Christian Seehase 11. Dez 2002 22:30

Moin Mathias,

bei mir sieht die OPENFILENAME Struktur so aus

Delphi-Quellcode:
type
  PcsOPENFILENAME = ^TcsOPENFILENAME;
  TcsOPENFILENAME =
    packed record
      lStructSize      : DWORD;
      hwndOwner        : HWND;
      hInstance        : DWORD;
      lpstrFilter      : PChar;
      lpstrCustomFilter : PChar;
      nMaxCustFilter   : DWORD;
      nFilterIndex     : DWORD;
      lpstrFile        : PChar;
      nMaxFile         : DWORD;
      lpstrFileTitle   : PChar;
      nMaxFileTitle    : DWORD;
      lpstrInitialDir  : PChar;
      lpstrTitle       : PChar;
      Flags            : DWORD;
      nFileOffset      : WORD;
      nFileExtension   : WORD;
      lpstrDefExt      : PChar;
      lCustData        : lParam;
      lpfnHook         : PcsOFNHookProc;
      lpTemplateName   : PChar;
      pvReserved       : Pointer;
      dwReserved       : DWORD;
      FlagsEx          : DWORD;
    end;
die erforderlichen Konstanten so

Delphi-Quellcode:
const // aus COMMDLG.H
  OFN_READONLY            = $00000001;
  OFN_OVERWRITEPROMPT     = $00000002;
  OFN_HIDEREADONLY        = $00000004;
  OFN_NOCHANGEDIR         = $00000008;
  OFN_SHOWHELP            = $00000010;
  OFN_ENABLEHOOK          = $00000020;
  OFN_ENABLETEMPLATE      = $00000040;
  OFN_ENABLETEMPLATEHANDLE = $00000080;
  OFN_NOVALIDATE          = $00000100;
  OFN_ALLOWMULTISELECT    = $00000200;
  OFN_EXTENSIONDIFFERENT  = $00000400;
  OFN_PATHMUSTEXIST       = $00000800;
  OFN_FILEMUSTEXIST       = $00001000;
  OFN_CREATEPROMPT        = $00002000;
  OFN_SHAREAWARE          = $00004000;
  OFN_NOREADONLYRETURN    = $00008000;
  OFN_NOTESTFILECREATE    = $00010000;
  OFN_NONETWORKBUTTON     = $00020000;
  OFN_NOLONGNAMES         = $00040000;
  OFN_EXPLORER            = $00080000;
  OFN_NODEREFERENCELINKS  = $00100000;
  OFN_LONGNAMES           = $00200000;
  OFN_ENABLEINCLUDENOTIFY = $00400000;
  OFN_ENABLESIZING        = $00800000;
  OFN_DONTADDTORECENT     = $02000000;
  OFN_FORCESHOWHIDDEN     = $10000000;
  OFN_EX_NOPLACESBAR      = $00000001;
und die Funktionsdeklarationen so

Delphi-Quellcode:
function GetOpenFileNameA(const lpofn : PcsOPENFILENAME) : Boolean; stdcall; external 'comdlg32.dll';
function GetSaveFileNameA(const lpofn : PcsOPENFILENAME) : Boolean; stdcall; external 'comdlg32.dll';
function GetOpenFileNamePreviewA(const lpofn : PcsOPENFILENAME) : Boolean; stdcall; external 'msvfw32.dll';
function GetSaveFileNamePreviewA(const lpofn : PcsOPENFILENAME) : Boolean; stdcall; external 'msvfw32.dll';
Das alles auch mal, falls jemand darin noch einen Fehler entdecken kann, denn ausserhalb der Kompo, nur unter Verwendung dieser Deklarationen funktioniert's ja auch nicht :?

MathiasSimmack 12. Dez 2002 08:50

Also, ich bin auch irgendwie nicht auf den rechten Weg gekommen. Ich habe das Gefühl, diese Preview-Dialogbox liegt nur in dem "alten" Stil vor. Sobald man ein (in dem Fall) unpassendes Flag benutzt, wird wohl automatisch zum bekannten Öffnen/Speichern-Dialog umgeschaltet.
Und das PSDK schweigt sich über das Design wohl auch aus; zumindest habe ich bisher noch nichts gefunden, was diese Frage klären würde.


Und noch mal kurz zur Aussage, dass "TOpenFileName" unter NT eine andere Größe hat. Unter allen älteren Versionen ist das so. Wie ist das bei ME; gibt´s da die Placesbar auch schon eingebaut im System? Zumindest bei Win98 ist es nötig, die alte Größe zu initialisieren, sonst wird der Dialog gar nicht erst aufgerufen:
Code:
if(Win2k) then ofn.lStructSize := SizeOf(TOpenFileName)
  else ofn.lStructSize := OPENFILENAME_SIZE_VERSION_400;
Ich wollte nur darauf hinweisen, auch wenn ich davon ausgehe, dass du es sowieso berücksichtigt hättest, Christian. In dem Zusammenhang fiel mir nämlich das TNA-Icon ein. Da war´s egal, und man konnte die erweiterte Struktur von Win 2000 und XP auch unter 98 initialisieren. Natürlich wurde nur benutzt, was vom OS bereitgestellt wurde, aber zumindest erschien das Icon.

Hier -bei den Dialogen!- passiert nichts, wenn du eine falsche Größe angibst, mit der das OS nichts anfangen kann. Will sagen: der Dialog erscheint gar nicht erst. (Win98 getestet!)

Christian Seehase 12. Dez 2002 11:40

Moin Mathias,

lass Dir doch mal bei nicht Erscheinen (if not Get...) den CommDlgExtendedError mal anzeigen.
Ich bin nämlich gestern noch unter W2K darüber gestolpert, dass mir ein simples Beispiel immer den Fehler 3002 (ungültiger Dateiname) brachte statt den Dialog aufzurufen. Da der übergebene Dateiname einfach ein leerer Buffer war, konnte das nur nicht so ganz angehen.
Als ich dann mal im Single Step da durchgegangen bin, um mir die Werte der Struktur anzusehen, wurde der Dialog aufgerufen :shock:
Als nächstes habe ich dann einfach mal versucht die Funktion dynamisch zu importieren und nicht statisch: Gleicher Fehler.
Als ich dann statt der ANSI Version die UNICODE Version benutzt habe gings (dann müssen natürlich auch die PChar in der Struktur angepasst werden).
Das einzige was an Test noch aussteht:
Bei der ANSI Version hatte ich den Filenamebuffer auf MAX_PATH initialisiert. Ich werd's nochmal mit MAX_PATH+1 versuchen.

Fazit:
Ich werde wohl die Funktionen dynamisch importieren müssen, und dann, abhängig vom OS die ANSI (9x/ME) oder die UNICODE (NTff) Variante verwenden müssen. :?
Ob der Fehler auch bei den "normalen" Dateidialogen auftritt weiss ich noch nicht, aber um die Kompo nicht unnötig aufwändig zu machen (bislang eine Basiskompo für alle vier Dialoge) werde ich die Änderung beim Aufruf auch bei diesen machen.

BTW:
Ich hatte über das CPU Fenster schon mal nachgeschaut, von wo der Dialog gestartet wird: Es war die msvfw32.dll.
Aber ich werd's nochmal genauer verfolgen.
Ausserdem habe ich auch schon Screenshots eines New Style Preview Dialoges im Internet gefunden. Wenn die nicht gefakt waren, müsste es wohl doch irgendwie gehen.

Luckie 12. Dez 2002 11:54

Zeig doch mal ein paar Screenshots. Ich will endlich mal sehen, wo von ihr redet. :?

OregonGhost 12. Dez 2002 16:09

Zitat:

Zitat von Christian Seehase
Ich bin nämlich gestern noch unter W2K darüber gestolpert, dass mir ein simples Beispiel immer den Fehler 3002 (ungültiger Dateiname) brachte statt den Dialog aufzurufen. Da der übergebene Dateiname einfach ein leerer Buffer war, konnte das nur nicht so ganz angehen.
Als ich dann mal im Single Step da durchgegangen bin, um mir die Werte der Struktur anzusehen, wurde der Dialog aufgerufen

Falls ich das richtig verstanden habe:

Das Problem hatte ich auch schon mal und es lag daran, dass der leere Puffer als erstes Zeichen ein Nullbyte haben muss. Vielleicht hast du das vergessen? ;c) Dazu würde passen, dass im Debugmodus die Variable korrekt initialisiert wird (wenn das in Delphi so ist (c; ).

Christian Seehase 12. Dez 2002 17:30

Moin Oregon Ghost,

ich bin ja wohl so .... :oops: :oops:

Das der Speicher mit einem Nullbyte anfangen muss war mir zwar schon klar, aber....
aus irgendeinem Grunde hatte es sich bei mir festgesetzt, das StrAlloc den Speicher auf null initialisiert, was ja gar nicht der Fall ist :oops: :oops:

Bei der Wide Version hab' ich ihn dann mit AllocMem reserviert...
das initialisiert auf 0.... :?

DANKE!!!

BTW:
Womit sich das eigentliche Problem allerdings leider immer noch nicht gelöst hat ;-)

Christian Seehase 12. Dez 2002 17:57

Moin Luckie,

wenn Du's mal sehen möchtest, kannst Du das hier mal laufen lassen (die Deklarationen stehen ja weiter oben, uses Commdlg nicht vergessen):

Delphi-Quellcode:
procedure TfrmMAIN.Button1Click(Sender: TObject);

var
  ofnStruct : TcsOPENFILENAME;
  sError   : string;

begin
  FillChar(ofnStruct,SizeOf(TcsOPENFILENAME),0);
  ofnStruct.lStructSize := SizeOf(TcsOPENFILENAME);
  ofnStruct.lpstrFilter := PChar('AVI'#00'*.avi'#00#00);
  ofnStruct.lpstrFile        := AllocMem(MAX_PATH+1);
  ofnStruct.nMaxFile         := MAX_PATH;
  ofnStruct.Flags            := OFN_EXPLORER;
  ofnStruct.FlagsEx          := OFN_EX_NOPLACESBAR;
  try
    if not GetOpenFileNamePreviewA(@ofnStruct) then
    begin
      sError := IntToHex(CommDlgExtendedError,8);
      if sError <> '00000000' then
      begin
        ShowMessage(sError);
      end;
    end;
  finally
    FreeMem(ofnStruct.lpstrFile,MAX_PATH+1);
  end;
end;
Wenn Du jetzt OFN_EXPLORER mal durch 0 ersetzt und dann, sobald der Dialog da ist, auf eine AVI Datei klickst, siehst Du im Old Style Dialog das, was im anderen auch da sein müsste.

MathiasSimmack 12. Dez 2002 20:09

Mal so rum gefragt, Christian:

Ist dir unter Win 2k oder XP schon eine Anwendung begegnet, die den neuen Dialogstil + Vorschau benutzt? Ich hätte z.B. auf den MediaPlayer getippt, bin aber eines besseren belehrt worden.

Aber die Screenshots, die du angesprochen hast, würde ich gern mal sehen. Weißt du die Seite noch, auf der sie waren?

Christian Seehase 12. Dez 2002 20:51

Moin Mathias,

nein, mir ist, wissentlich, noch keine Anwendung untergekommen, bei der ich das gesehen hätte, die Idee diesen Dialog mit zu Benutzen kam mir aber auch erst als ich sie im PSDK sah.

Ich hab' jetzt nochmal bei Hotbot gesucht (da hatte ich den Screenshot her)

http://cad.ntu-kpi.kiev.ua/~netlib/b...le/vcu37fi.htm

Ziemlich in der Mitte ist dann ein Link zum Screenshot:

http://cad.ntu-kpi.kiev.ua/~netlib/b...le/37vcu04.gif

Das ist kein Old-Style Dialog :?

Ich hab' mir jetzt auch mal alle Dialogresourcen aus der comdlg32.dll und ocx, shell32.dll, msvfw32.dll, mmsys.cpl angesehen. Nirgendes auch nur einer der beiden Dialoge mit Preview zu sehen.

Die Comdlg32.dll enthält die hingegen alle Dialogresourcen ohne :shock:

Ich kann also, zumindest so ohne weiteres, nichts finden, wo auch nur der Old-Style Dialog mit Preview herkommt.

MathiasSimmack 13. Dez 2002 19:24

Hi Christian.

Frag nicht warum, aber wenn ich das Beispiel von der URL nachvollziehe, die du angegeben hast, dann funktioniert es. Das Original fix in Delphi nachgebaut (mal ohne dynamischen Schnickschnack, usw.):
Delphi-Quellcode:
uses
  CommDlg;

function GetOpenFileNamePreview(var OpenFile: TOpenFileNameA): Bool; stdcall;
  external 'msvfw32.dll' name 'GetOpenFileNamePreviewA';

procedure TForm1.Button1Click(Sender: TObject);
var
  ofn : TOpenFileName;
begin
  ZeroMemory(@ofn,sizeof(TOpenFileName));
  ofn.lStructSize := sizeof(ofn);
  ofn.lpstrFilter := 'AVIs'#0'*.avi'#0#0;

  GetOpenFileNamePreview(ofn);
end;
Ergebnis: der Dialog hat den neuen Stil, und zeigt bei der Auswahl einer AVI rechts die Preview an. Getestet habe ich´s mit D5-Pro unter Win98.

Gruß,
Mathias.


PS: Unter WinXP wird bei obigem Code nur der alte Stil angezeigt. Wie das unter Win 2000 ist, weiß ich nicht. Aber wäre es nicht möglich, dass Microsoft diesen Dialog dort nur im alten Stil untergebracht hat?

Christian Seehase 14. Dez 2002 02:45

Moin Mathias,

was passiert denn, wenn Du nicht die OPENFILENAME Struktur verwendest, die in der Commdlg Unit von D5 deklariert ist?
Die ist nämlich 12 Byte kürzer und gestatt nicht die wirklich neuen Dialoge (mit Placesbar).
Ausserdem wäre es vielleicht noch interessant, welche msvfw32.dll Version Du auf dem 98 Rechner hast.

Unter W2K SP2 erhalte ich mit Deinem Beispiel nur einen üblichen OpenDialog, als hätte ich ihn aus der Komponentenpalette ausgewählt, also ohne Placesbar. (Logisch, es wird ja auch die "alte" Struktrulänge übergeben)

MathiasSimmack 14. Dez 2002 07:57

So ganz kann ich dir nicht folgen, Christian. Wenn ich mir Luckies "Öffnen/Speichern"-API-Demo nehme und unter WinXP teste, sehe ich die Placesbar. Sie ist IMO im System eingebaut und damit fester Bestandteil des Dialogs.

Die erweiterte Struktur hat meiner Meinung nach auch nicht wirklich was damit zu tun. Der Pointer (pvReserved) muss bisher nil sein, die Größe (dwReserved) muss Null sein, und das zusätzliche Flag kann nur "OFN_EX_NOPLACESBAR" sein.
Deswegen bin ich auch durcheinander gekommen. Ich dachte, es gäbe auch schon unter Win9x eine Möglichkeit, die Dialoge vom Office zu verwenden. Die sind ja unabhängig vom OS und bieten eine eigene Placesbar.

Außerdem sagte ich ja schon, was unter Win98 z.B. passiert. Benutzt du die erweiterte Struktur und übergibst auch die neue Länge, dann wird der Dialog gar nicht erst angezeigt.

Ich werde es bei Gelegenheit aber noch mal unter XP mit der erweiterten Struktur probieren.

Christian Seehase 14. Dez 2002 12:53

Moin Mathias,

stimmt, hast Du wohl wahr :oops:

Das bezog sich auf den "normalen" Dateidialog. Wenn dort zusätzlich zur kleineren Strukturgrösse noch OFN_ENABLEHOOK angebeben wird, wird die Placesbar unterdrückt (gemäss PSDK aus Kompatibilitätsgründen).

Ich werd' nochmal ausprobieren, was passiert, wenn man bei der Preview Funktion noch eine Hook Funktion mit übergibt.

Bei den Office Dialogen sehe ich zwei Möglichkeiten:
Entweder sie werden vollständig von Office implementiert, oder aber, was ich mir eher vorstellen kann, es handelt sich um die üblichen Dialoge, die aber um neue Templates erweitert wurden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz