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/)
-   -   Datei mit meinem Programm öffnen (https://www.delphipraxis.net/24577-datei-mit-meinem-programm-oeffnen.html)

Alex_ITA01 23. Jun 2004 08:22


Datei mit meinem Programm öffnen
 
Hallo,
ich weiß diese Frage gab es schon aber ich habe noch eine etwas speziellere Frage.
Ich kann EINE Datei im Windows öffnen mit meinem Programm
Source:
FORMSHOW
Delphi-Quellcode:
  if (paramcount > 0) and FileExists(paramstr(1)) then
  begin
    FileList.Add(paramstr(1));
  end;
Nur wollte ich jetzt gerne mehrere Dateien gleichzeitig öffnen mit meinem Programm.Also mehrere markieren und sagen öffnen mit...
Ich habe schon versucht eine for schleife drum herum zu bauen die bis anzahl paramcount zählt aber das geht auch nicht.
Kann mir bitte jemand helfen?

Danke
Alex

MrKnogge 23. Jun 2004 08:29

Re: Datei mit meinem Programm öffnen
 
Zitat:

Zitat von Alex_ITA01
Ich habe schon versucht eine for schleife drum herum zu bauen die bis anzahl paramcount zählt aber das geht auch nicht.

Du musst auch bis Paramcount-1 zählen.

Delphi-Quellcode:
for i := 0 to paramcount-1 do
  if FileExists(paramstr(i)) then FileList.Add(paramstr(i));
PS: Ich würde das in's Form.Create Ereigniss schreiben.

MathiasSimmack 23. Jun 2004 09:01

Re: Datei mit meinem Programm öffnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
In dem Fall irrst du, MrKnogge. "paramstr(0)" ist die Anwendung selbst (sprich: Pfad und Name der Exe), ab "paramstr(1)" bis "paramcount" folgen die Parameter. Das hat mit den null-basierenden Geschichten von Delphi nichts zu tun, darum sieht die Abfrage der Parameter immer so aus:
Delphi-Quellcode:
for i := 1 to paramcount do
  { ... }
Bei der Lösung dieses Problems:
Zitat:

Zitat von Alex_ITA01
Also mehrere markieren und sagen öffnen mit...

muss man den Vorgang bedenken, der intern abläuft -

Wenn du einen Dateityp registrierst (bzw. wenn du einfach nur "Öffnen mit ..." wählst), dann ruft Windows das zugeordnete/ausgewählte Programm auf und übergibt die Datei als Parameter. Wenn du mehrere Dateien auswählst, dann wird nur dein Programm mehrfach gestartet, und jeder Instanz wird wieder jede ausgewählte Datei als Parameter übergeben.

Im Klartext: Wählst du 10 Dateien aus, startet Windows normalerweise dein Programm 10x und übergibt jedem Programm eine Datei als ersten Parameter (sofern in der Registry nicht anders angegeben, wenn du den Dateityp registriert hast).

Um das zu verhindern musst du drei Sachen machen -
  1. Dafür sorgen, dass nur eine Instanz deines Programms starten kann ([dp]"Mutex"[/dp], [dp]"Semaphore"[/dp])
  2. Dafür sorgen, dass jede zusätzliche Instanz ihren Parameter an die bereits laufende weiterreicht (bspw. mit [dp]"WM_COPYDATA"[/dp]) und sich dann beendet.
  3. Intern dafür sorgen, dass dein Programm auch mit vielen Dateien umgehen kann, aber das versteht sich sicher von selbst.
Falls sich im Forum keine Lösungen finden (was ich aber nicht glaube), hänge ich mal Code an.

Alex_ITA01 23. Jun 2004 09:43

Re: Datei mit meinem Programm öffnen
 
Hallo Mathias,
danke für dein Tip.
Das nur eine Instanz von meinem Programm gestartet wird, habe ich schon soweit programmiert.
WM_COPYDATA habe ich auch verwendet aber weiß nicht ob das sorecht funktioniert.
Wäre toll wenn du mir den Source mal zur Verfügung stellen könntest.
Danke
Alex

MathiasSimmack 23. Jun 2004 09:44

Re: Datei mit meinem Programm öffnen
 
Gerade passiert. ;)

Alex_ITA01 23. Jun 2004 10:18

Re: Datei mit meinem Programm öffnen
 
danke schön hab mir grade dein source gezogen
ich gebe dir mal trotzdem mein beispiel-prog vielleicht siehst du ja auch ein fehler drinne.

Delphi-Quellcode:
dpr:

uses
  hSemaphore    : DWORD;
  hWindow       : DWORD;
  cdWork        : TcsCopyDataStruct;
  dwMSGFilepath : DWORD;
  i : Integer;

  dwMSGFilePath := RegisterWindowMessage('{06007663-C0F6-4069-A835-D85AD31B5011}');
  hSemaphore := CreateSemaphore(nil,1,1,'{E564BC8A-FBBE-42BF-B3A0-9C153FBBA03D}');
  if not ((hSemaphore = 0) or ((hSemaphore <> 0) and (GetLastError = ERROR_ALREADY_EXISTS))) then begin
    Application.Initialize;
    Application.Title := 'ITA';
    Application.CreateForm(TMain_Window, Main_Window);
    Application.Run;
  end
  else
  begin
    hWindow := FindWindow(nil,'ITA');
    if hWindow <> 0 then begin
      for i := 1 to ParamCount do
      begin
        if (paramcount > 0) and FileExists(paramstr(i)) then begin
          cdWork.dwData := dwMSGFilepath;
          cdWork.cbData := Length(paramstr(i)) + 1;
          cdWork.lpData := AllocMem(cdWork.cbData);
          try
            CopyMemory(cdWork.lpData,@paramstr(i)[1],cdWork.cbData-1);
            SendMessage(hWindow,WM_COPYDATA,0,lParam(@cdWork));
          finally
            FreeMem(cdWork.lpData,cdWork.cbData);
          end;
        end;
      end;
    end;
    //Application.MessageBox('Programm läuft bereits','Hinweis',0);
  end;

Main_Window:

public
  procedure WndProc (var Msg: TMessage); override;

type
  PcsCopyDataStruct = ^TcsCopyDataStruct;
  TcsCopyDataStruct =
  packed record
    dwData : DWORD;
    cbData : DWORD;
    lpData : Pointer;
  end;

procedure TMain_Window.WndProc(var Msg: TMessage);
var
  cdWork  : PcsCopyDataStruct;
begin

  if msg.Msg = WM_COPYDATA then
  begin
    cdWork := PcsCopyDataStruct(msg.lParam);
    MP3FileList.Add(PChar(cdWork.lpData));
    exit;
  end;
  inherited;
end;

FORMSHOW:
  for i := 1 to ParamCount do
  begin
    if (paramcount > 0) and FileExists(paramstr(i)) then
      FileList.Add(paramstr(i));
  end;
Danke nochmal
Alex

Luckie 23. Jun 2004 10:29

Re: Datei mit meinem Programm öffnen
 
Zitat:

Zitat von Alex_ITA01
danke schön hab mir grade dein source gezogen
ich gebe dir mal trotzdem mein beispiel-prog vielleicht siehst du ja auch ein fehler drinne.

Also ehrlich gesagt, musste ich mich eben ziemlich zusammen reißen, als ich das gelesen habe. Wird das jetzt eine Quiz-Sendung? Wer die Zeile findet bekommt einen Punkt, wer die Art des Fehlers findet zwei, wer den genauen Fehler findet drei und wer ihn dir behebt und den Code hier einstellt bekommt den Jackpot? :roll:

MathiasSimmack 23. Jun 2004 10:46

Re: Datei mit meinem Programm öffnen
 
@Alex_ITA01: Ich will dich nicht kritisieren, aber das Record
Zitat:

Delphi-Quellcode:
type
  PcsCopyDataStruct = ^TcsCopyDataStruct;
  TcsCopyDataStruct =
  packed record
    dwData : DWORD;
    cbData : DWORD;
    lpData : Pointer;
  end;

kannst du dir bspw. sparen, weil es IMHO dem Windows-Original "TCopyDataStruct" entspricht. Das wäre also meiner Ansicht nach ein typischer Fall von "doppelt gemoppelt". ;)

Dann solltest du zumindest den Tipp von MrKnogge beherzigen und den Parameter im "OnCreate" der Form auslesen. "OnShow" wird(soweit ich weiß :?) auch wirksam, wenn dein Programm im Hintergrund war und nun wieder angezeigt wird. Das heißt, im ungünstigsten Fall liest du den Parameter einige Male ein. "OnCreate" wird dagegen nur einmal ausgeführt: nämlich beim Erzeugen der Form.

Dann beim Suchen des Fensters gehst du auf Nummer Sicher, wenn du auch den Klassennamen (= den Namen der Form angibst:
Delphi-Quellcode:
hWindow := FindWindow('TMain_Form','ITA');
Und das hier ist aus zwei Gründen zuviel:
Zitat:

Delphi-Quellcode:
      for i := 1 to ParamCount do
      begin
        if (paramcount > 0) and
           FileExists(paramstr(i)) then
        begin
          cdWork.dwData := dwMSGFilepath;
          cdWork.cbData := Length(paramstr(i)) + 1;
          cdWork.lpData := AllocMem(cdWork.cbData);
          try
            CopyMemory(cdWork.lpData,@paramstr(i)[1],cdWork.cbData-1);
            SendMessage(hWindow,WM_COPYDATA,0,lParam(@cdWork));
          finally
            FreeMem(cdWork.lpData,cdWork.cbData);
          end;
        end;
      end;

  1. glaube ich, dass nur eine Datei (= ein Parameter) pro Programm übergeben wird, wenn du es über den Explorer machst (sprich: mehrere markieren, öffnen mit ...). Die Schleife wäre also IMHO nicht notwendig.
  2. ist die gesonderte Prüfung
    Delphi-Quellcode:
            if (paramcount > 0) and
    -sorry!- Unfug, denn die Schleife wird nur ausgeführt, wenn "paramcount" >= Eins ist.
Und diese Prüfung:
Zitat:

Delphi-Quellcode:
if not ((hSemaphore = 0) or
  ((hSemaphore <> 0) and (GetLastError = ERROR_ALREADY_EXISTS))) then

kannst du auch besser gestalten, wenn du auf das "not" verzichtest. Das irritiert bloß, ehrlich gesagt. Laut PSDK gibt es nur 3 Möglichkeiten:
  1. Semaphore wird angelegt, Rückgabewert = Handle
  2. Semaphore existiert schon, Rückgabewert = Handle, GetLastError = ERROR_ALREADY_EXISTS
  3. Semaphore kann nicht angelegt werden, Rückgabewert = Null, GetLastError = Grund
Wenn dein Programm also zwingend vom Semaphore abhängen soll, dann prüfe nach dem Erzeugen einfach auf Null und beende das Programm ggf. Ansonsten verzweigst du für den Fall, dass der/die/das Semaphore schon existiert, indem du auf "ERROR_ALREADY_EXISTS" prüfst und bspw. mit "Halt" das Programm dann abbrichst.
Schau dir dazu mal den Projektquelltext meines Beispiels an. Ich habe bloß nicht geprüft ob der Semaphore Null ist. Den Rest findest du allerdings, und ich hatte keine Probleme damit.

Kurz gesagt: Mir kommt dein Programmcode (bei allem Respekt) zu umständlich vor. :)


Habe ich jetzt den Jackpot? :stupid:

shmia 23. Jun 2004 11:03

Re: Datei mit meinem Programm öffnen
 
Hallo,
ich würde dringend empfehlen, auf jeglichen eigenen Programmcode zu verzichten und statt dessen
die Unit JclAppInst aus der JCL zu verwenden.
Gründe:
  • JCL Programmcode wurde schon tausendfach getestet und funktioniert auch unter allen Windows-Versionen
  • die Aufgabe "Kontrolle der Instanzen+Weitergabe von Paramters zwischen Instanzen" ist sauber gekappselt und "gammelt" nicht auf dem Hauptformular rum
  • bein nächsten Mal kann die gleiche Aufgabe mit wenigen Zeilen und Zeitaufwand erledigt werden

Luckie 23. Jun 2004 11:17

Re: Datei mit meinem Programm öffnen
 
Zitat:

Zitat von shmia
ich würde dringend empfehlen, auf jeglichen eigenen Programmcode zu verzichten

Wieso dringend? Was ich selber machen kann, mache ich lieber auch selber - wenn der Aufwand gerechtfertigt ist. dann habe ich zu mindest nicht das Gefühl meine Anwendung zusammengeklickt zu haben.


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

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