Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Fehler mit ShellExecute (https://www.delphipraxis.net/216742-fehler-mit-shellexecute.html)

Delbor 21. Feb 2025 13:14

Fehler mit ShellExecute
 
In meinem AlexOpenfileFrame suche und klicke ich eine bestimmte Datei, in diesem Fall eine PDF, und gelange
dann über einen Event hierher, um hier in einem Tabsheet eine Form zu erzeugen:

Delphi-Quellcode:
procedure TOfficerAlexMain.DoTextSelectionEvent(Sender: TObject; const ATextSelection: String);
  var LFilename: String;
begin
  FTextSelection := ATextSelection;
  if ExtractFileExt(ATextSelection) = AnsiLowerCase('.pdf') then
  begin
    LFilename := ATextSelection;
    AlexExternAppForm := TAlexExternAppForm.Create(Self);
    AlexExternAppForm.FFilename := LFilename;
    AlexExternAppForm.Parent := OfficerAlexMain.tbsAppParent;
    AlexExternAppForm.ExecuteShell;
  end;
end;
In AlexExternAppForm wird nach dem Create der folgende Code ausgeführt:


Delphi-Quellcode:
procedure TAlexExternAppForm.ExecuteShell();
begin
  if ShellExecute(AlexExternAppForm.Handle,
     'open',
     PChar(FFilename),
     nil, nil, SW_NORMAL) <= 32 then
    ShowMessage('Es ist ein Fehler aufgetreten');
end;
FFileName enthält hier den Pfad der Datei, die ich in meinem AlexOpenfileFrame angeklickt habe.
Das Resultat ist allerdings nicht beabsichtigt:

Auf dem vorgesehenen Tabsheet wird die gewünschte Form erstellt, der Name steht in der Symbolleiste, aber die Form ist leer.
Die gewünschte PDF wird in der Standard-App dargestellt, allerdings ohne sich in der vorgesehenen Form zu befinden.
(noch nicht getestet: Völlig frei auch von der Mainform.

Was mache ich falsch?

Gruss
Delbor

Delphi.Narium 21. Feb 2025 13:48

AW: Fehler mit ShellExecute
 
Dashier verstehe ich nicht:
Delphi-Quellcode:
if ExtractFileExt(ATextSelection) = AnsiLowerCase('.pdf') then
.pdf ist doch schon in Kleinbuchstaben, warum wird es in Kleinbuchstaben umgewandelt? Wenn in ATextSelection die Dateiendung .PDF ist, hat das genau keine Wirkung.
Müsste es nicht eher
Delphi-Quellcode:
if AnsiLowerCase(ExtractFileExt(ATextSelection)) = '.pdf' then
heißen?

Oder eventuell
Delphi-Quellcode:
if AnsiSameText(ExtractFileExt(ATextSelection),'.pdf') then
?

Open heißt: Starte die Datei im damit verknüpften Programm. Und genau das geschieht. ShellExecute weiß nichts davon, dass Du einen Frame hast, in dem die Anzeige erfolgen soll.

Wenn Du SumatraPDF zur Anzeige der PDF-Dateien nutzen könntest / möchtest ... wäre dashier eventuell eine Option:

Delphi-Quellcode:
ShellExecute(0, 'open', 'SumatraPDF.exe', PChar(Format('-plugin %d "%s"',[FrameHandle,PDFFilePath])), nil, SW_SHOW);

shebang 21. Feb 2025 13:56

AW: Fehler mit ShellExecute
 
Zitat:

Zitat von Delbor (Beitrag 1546432)
Was mache ich falsch?

Der erste Parameter von ShellExecute gibt nicht die Zielanwendung an, sondern im Gegenteil den Absender des ShellExecute-Befehls.

jaenicke 21. Feb 2025 14:03

AW: Fehler mit ShellExecute
 
Wenn du eine PDF-Datei in deiner Anwendung anzeigen möchtest, musst du eine entsprechende Komponente verwenden.

Das kann auch eine Browserkomponente sein, was zwar am billigsten, aber nicht unbedingt am schönsten ist.

Frickler 21. Feb 2025 17:10

AW: Fehler mit ShellExecute
 
Geht auch mit dem oben erwähnten SumatraPDF, das in die Anwendung eingebettet werden kann, wie in diesem Beitrag: https://www.delphipraxis.net/1498907-post5.html beschrieben.

tomkupitz 21. Feb 2025 17:29

AW: Fehler mit ShellExecute
 
Eine PDF in deiner Anwendung anzeigen geht so:

Code:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.ShlObj, System.Win.ComObj, Winapi.ActiveX, Winapi.PropSys, System.Win.Registry;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private

  public

  end;

  TDefaultPreview=class
  private
    FFileStream: TFileStream;
    FPreviewHandler: IPreviewHandler;
  public
    constructor Create;
    destructor Destroy; override;

    function LoadPreview(ParentControl: TWinControl; FileName: string): Boolean;
    procedure PaintPreview(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetPreviewHandlerCLSID(const AFileName: string): string;
var
  LRegistry: TRegistry;
  LKey: String;
begin
  LRegistry:=TRegistry.Create();
  Result:=EmptyStr;
  try
    LRegistry.RootKey:=HKEY_CLASSES_ROOT;
    LKey:=ExtractFileExt(AFileName) + '\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}';
    if LRegistry.OpenKeyReadOnly(LKey) then begin
      Result:=LRegistry.ReadString('');
      LRegistry.CloseKey;
    end else begin
      LKey:='SystemFileAssociations\' + ExtractFileExt(AFileName) + '\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}';
      if LRegistry.OpenKeyReadOnly(LKey) then begin
        Result:=LRegistry.ReadString('');
        LRegistry.CloseKey;
      end else begin
        LRegistry.RootKey:=HKEY_LOCAL_MACHINE;
        LKey:='\Software\Classes\' + ExtractFileExt(AFileName) + '\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}';
        if LRegistry.OpenKeyReadOnly(LKey) then begin
          Result:=LRegistry.ReadString('');
          LRegistry.CloseKey;
        end else begin
          LKey:='\Software\Classes\SystemFileAssociations\' + ExtractFileExt(AFileName) +
            '\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}';
          if LRegistry.OpenKeyReadOnly(LKey) then begin
            Result:=LRegistry.ReadString('');
            LRegistry.CloseKey;
          end;
        end;
      end;
    end;
  finally
    LRegistry.Free;
  end;
end;

//

constructor TDefaultPreview.Create;
begin
  inherited Create;

  FFileStream:=nil;
  FPreviewHandler:=nil;
end;

destructor TDefaultPreview.Destroy;
begin
  if Assigned(FPreviewHandler) then
  begin
    FPreviewHandler.Unload;
    FPreviewHandler:=nil;
  end;

  inherited Destroy;
end;

//

function TDefaultPreview.LoadPreview(ParentControl: TWinControl; FileName: string): Boolean;
const
  GUID_ISHELLITEM='{43826d1e-e718-42ee-bc55-a1e261c37bfe}';

var
  re: TRect;

  GUID: TGUID;
  GUIDStr: string;

 InitializeWithFile: IInitializeWithFile;
 InitializeWithStream: IInitializeWithStream;
 InitializeWithItem: IInitializeWithItem;
 PreviewHandlerVisuals: IPreviewHandlerVisuals;

  Stream: IStream;

  ShellItem: IShellItem;

  res: HRESULT;

begin
  result:=False;

  //

  if Assigned(FPreviewHandler) then
  begin
    FPreviewHandler.Unload;
    FPreviewHandler:=nil;
  end;

  //

  CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE);

  //

  GUIDStr:=GetPreviewHandlerCLSID(FileName);

  if GUIDStr='' then
    Exit;

  GUID:=StringToGUID(GUIDStr);

  CoCreateInstance(GUID, nil, CLSCTX_LOCAL_SERVER, IPreviewHandler, FPreviewHandler);

  if FPreviewHandler=nil then
  begin
    CoUninitialize;
    Exit;
  end;

  result:=True;

  if FPreviewHandler.QueryInterface(IInitializeWithStream, InitializeWithStream)=S_OK then
  begin
    FFileStream:=TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
    Stream:=TStreamAdapter.Create(FFileStream, soOwned) as IStream;

    res:=InitializeWithStream.Initialize(Stream, STGM_READ or STGM_FAILIFTHERE or STGM_DIRECT);

    if (Succeeded(res)) then
    begin
      re:=Form1.ClientRect;

      FPreviewHandler.SetWindow(Form1.Handle, re);

      FPreviewHandler.SetRect(re);
      FPreviewHandler.DoPreview;
      FPreviewHandler.SetFocus;

      CoUninitialize;
      Exit;
    end;
  end;

  if Assigned(FPreviewHandler) then
  begin
    FPreviewHandler.Unload;
    FPreviewHandler:=nil;
  end;

  CoUninitialize;
end;

//

procedure TDefaultPreview.PaintPreview(Sender: TObject);
var re: TRect;

begin
  if Assigned(FPreviewHandler) then
  begin
    re:=Form1.ClientRect;

    FPreviewHandler.SetRect(re);
    FPreviewHandler.DoPreview;
    FPreviewHandler.SetFocus;
  end;
end;

//

var
  dp: TDefaultPreview;

procedure TForm1.FormCreate(Sender: TObject);
begin
  dp:=TDefaultPreview.Create;
  dp.LoadPreview(Self, 'demo.pdf');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  dp.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  dp.PaintPreview(Sender);
end;

end.

dummzeuch 21. Feb 2025 17:30

AW: Fehler mit ShellExecute
 
Zitat:

Zitat von Frickler (Beitrag 1546437)
Geht auch mit dem oben erwähnten SumatraPDF, das in die Anwendung eingebettet werden kann, wie in diesem Beitrag: https://www.delphipraxis.net/1498907-post5.html beschrieben.

Unglücklicherweise:

"Plugin mode is no longer supported."

https://github.com/sumatrapdfreader/...df/issues/1980

Delphi.Narium 21. Feb 2025 17:58

AW: Fehler mit ShellExecute
 
Ältere Versionen sind hier zu finden: https://www.sumatrapdfreader.org/download-prev

Eventuell reicht da ja auch eine nicht ganz aktuelle Version zur Anzeige aus, bei mir funktioniert (unter Windows 11) die Version 3.1.2 problemlos.

Delbor 22. Feb 2025 08:06

AW: Fehler mit ShellExecute
 
Hi zusammen

Zitat:

Zitat von shebang (Beitrag 1546435)
Zitat:

Zitat von Delbor (Beitrag 1546432)
Was mache ich falsch?

Der erste Parameter von ShellExecute gibt nicht die Zielanwendung an, sondern im Gegenteil den Absender des ShellExecute-Befehls.

Der erste Parameter von ShellExecute ist die Form TAlexExternAppForm, die auf einem Tabsheet angezeigt und wieder zerstört wird/werden soll. Somit ist TAlexExternAppForm einerseits der Absender und andrerseits das Ziel, in dem die Datei dargestellt werden soll.

Delphi-Quellcode:
procedure TAlexExternAppForm.ExecuteShell();
begin
  if ShellExecute(AlexExternAppForm.Handle,
     'open',
     PChar(FFilename),
     nil, nil, SW_NORMAL) <= 32 then
    ShowMessage('Es ist ein Fehler aufgetreten');
end;
PS: Heisst dies nun, dass ShellExecute von da aufgerufen werden muss, wo ich aktuell die AlexExternAppForm erzeuge?

Gruss
Delbor

Delbor 22. Feb 2025 09:42

AW: Fehler mit ShellExecute
 
Hi Delphi-Natrium

[QUOTE=Delphi.Narium;1546433]Dashier verstehe ich nicht:
Delphi-Quellcode:
if ExtractFileExt(ATextSelection) = AnsiLowerCase('.pdf') then
.pdf ist doch schon in Kleinbuchstaben, warum wird es in Kleinbuchstaben umgewandelt? Wenn in ATextSelection die Dateiendung .PDF ist, hat das genau keine Wirkung.
Müsste es nicht eher
Delphi-Quellcode:
if AnsiLowerCase(ExtractFileExt(ATextSelection)) = '.pdf' then
heißen?


Ja klar doch! Vielen Dank für deinen Hinweis!


Gruss
Delbor


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:58 Uhr.
Seite 1 von 2  1 2      

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