Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Demo für ShellExtension - brauche noch Hilfe (https://www.delphipraxis.net/139559-demo-fuer-shellextension-brauche-noch-hilfe.html)

Marco Steinebach 31. Aug 2009 18:47


Demo für ShellExtension - brauche noch Hilfe
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich möchte gern eine Demo für eine Shellextension erstellen, also eine DLL, die wiederum ein Testprogramm aufruft, dem mehrere, markierte, Dateien gleichzeitig, also als Liste, übergeben werden können.

Nach viel gehampel mit dem Delphi beiliegenden Demo und viel Suche, bin ich, denke ich, schon mal auf dem richtigen Weg.

Aber ich habe, im Moment, zwei fragen:
1. kann man ein TstringList-Objekt via WM_COPYDATA übergeben?
2. kann man das finden des Handles, an das die Messag egeschickt wird, eleganter lösen?

Delphi-Quellcode:
// beim Sender:
function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
  function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
  begin
    TList(lParam).Add(Pointer(hWnd));
    Result := True;
  end;

var
  SI: TStartupInfo;
  PI: TProcessInformation;
  List: TList;
  ProcessId: DWORD;
  AppHWnd: HWND;
  I: Integer;
  cds: TCopyDataStruct;
begin
  Result := E_FAIL;
  // Make sure we are not being called by an application
  if (HiWord(Integer(lpici.lpVerb)) <> 0) then
  begin
    Exit;
  end;

  // Make sure we aren't being passed an invalid argument number
  if (LoWord(lpici.lpVerb) <> 0) then begin
    Result := E_INVALIDARG;
    Exit;
  end;

  AppHWnd := 0;
  FillChar(SI, SizeOf(TStartupInfo), 0);
  SI.cb := SizeOf(TStartupInfo);
  SI.dwFlags := STARTF_USESHOWWINDOW;
  SI.wShowWindow := lpici.nShow;
  if CreateProcess(
      nil, // Application name
      pChar(GetCompilerPath), // commandline
      nil,
      nil,
      False,
      0,
      nil,
      nil,
      SI,
      PI) then
  begin
    WaitForInputIdle(PI.hProcess, INFINITE);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
    List := TList.Create;
    try
      if EnumWindows(@EnumWindowsProc, Longint(List)) then
      begin
        for I := 0 to List.Count - 1 do
          if GetWindowThreadProcessId(HWND(List.Items[I]), @ProcessId) <> 0 then
            if ProcessId = PI.dwProcessId then
            begin
              AppHWnd := HWND(List.Items[I]);
              Break;
            end;
        if IsWindow(AppHWnd) then
        begin
          cds.dwData := 0;
          cds.cbData := SizeOf (fFileNames);
          cds.lpData := @fFileNames;
          SendMessage (AppHwnd, WM_COPYDATA,
            longint(AppHwnd), longint(@cds));
        end;
      end;
    finally
      List.Free;
    end;
    result := NOERROR;
  end
  else
    ShowMessage ('Something wrong!');
end;

// beim empfänger
procedure TMainForm.WMCOPYDATA(var Msg: TWMCopyData);
var
  l: tStringList;
  i: integer;
begin
  Memo1.Lines.Add ('copy data called!');
  l := TStringList(msg.CopyDataStruct.LPData);
  for i := 0 to l.count -1 do
    Memo1.Lines.Add (l[i]);
end;
Wer das ganze schonmal testen will, bitte, erstmal, die dll mittels regsvr32 registrieren, und dann auf eine, oder mehrere, .pas-Dateien klicken.

Viele Grüße
Marco

Apollonius 31. Aug 2009 18:57

Re: Demo für ShellExtension - brauche noch Hilfe
 
Objekte kannst du per WM_COPYDATA nicht ohne ziemich viel Gehampel verschicken. Bei der TStringList genügt es aber, wenn du einfach den ganzen String verschickst, also alle Einträge der Stringliste mit Zeilenumbrüchen zusammengehängt (Eigenschaft Text). Auf der Empfangsseite kannst du dann einfach die Eigenschaft Text einer neuen Liste auf den empfangenen String setzen.

Bezüglich der zweiten Frage: Ich würde einfach mit RegisterWindowMessage eine eigene Nachricht registrieren und dann mit HWND_BROADCAST an alle Fenster schicken.

Marco Steinebach 31. Aug 2009 20:13

Re: Demo für ShellExtension - brauche noch Hilfe
 
Zitat:

Zitat von Apollonius

Bezüglich der zweiten Frage: Ich würde einfach mit RegisterWindowMessage eine eigene Nachricht registrieren und dann mit HWND_BROADCAST an alle Fenster schicken.

ähm, wie jetzt: wenn ich mit RegisterWindowMessage eine Nachricht registriere, wie weiß ich dann in meinem Testprogramm, welche Nummer die hat? Die Nummer ändert sich doch jedesmal ... oder bin ich völlig auf dem Holzweg...
Viele Grüße
Marco

Apollonius 31. Aug 2009 20:24

Re: Demo für ShellExtension - brauche noch Hilfe
 
Der Punkt an RegisterWindowMessage ist doch, dass der gleiche String den gleichen Rückgabewert erzeugt. In beiden Programmen rufst du also RegisterWindowMessage('Meine Shellextension') auf und erhältst den gleichen Nachrichtencode.
Diese Nachricht kannst du nutzen, um aus deinem Zielprogramm ein Handle an das Senderprogramm zu schicken, sodass das Senderprogramm wiederum WM_COPYDATA schicken kann.
Startest du eigentlich immer das Zielprogramm selbst? Dann kannst du doch gleich über die Kommandozeile gehen: Einfach direkt den String oder aber ein Fensterhandle bzw. Pipehandle übergeben. Man muss es sich ja nicht unnötig schwierig machen.

Edit: In der DLL ist es natürlich etwas schwierig mit RegisterWindowMessage, da dafür ein Fenster und eine Nachrichtenschleife nötig sind. Mal wieder zu kurz gedacht.

Marco Steinebach 1. Sep 2009 18:35

Re: Demo für ShellExtension - brauche noch Hilfe
 
Hallo zusammen,
Dank eurer Hilfe gibt’s jetzt eine Lauffähige Version, siehe 1. Post.
Ich habe das Demo insofern erweitert, als daß jetzt nur noch eine Instanz auf einmal laufen darf.
aber:
Meine Anwendung wird von der DLL gestartet – stellt fest, daß sie schon läuft, und beendet sich gleich wieder. Eigentlich würde die DLL gern die Message, wo sich die zu kopierenden Daten befinden, also WM_COPYDATA noch an mein Programm schicken, aber das ist schon weg. *lach
Ich stehe, gedanklich, im moment ein bißchen auf dem Schlauch.
Kann mir da mal bitte jemand runterhelfen?
Muß ich das Handle der ersten Instanz rauskriegen, oder wie? hä?
Viele Grüße
Marco

Marco Steinebach 2. Sep 2009 20:29

Re: Demo für ShellExtension - brauche noch Hilfe
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Zusammen,
so. Jetzt ist sie fertig, lauffähig und enthält, soweit ich sehen kann, keine Fehler mehr.
Die Unit InstanceManager
Autor: Evan Simpson - esimpson@eramp.net
Veröffentlicht in http://www.undu.com/Articles/980422a.htm
ist hier, allerdings in veränderter Form zum Einsatz gekommen.
Das Testprogramm kann direkt mit Kommandozeile gefüttert werden, auch Parameter wie „ich bin ein Dateiname.doc“ funktionieren, oder, mittels kontextmenü, über die beigefügte DLL zur Shell Extension.

Wer Fragen, Anregungen, Verbesserungsvorschläge hat, immer her damit.

Und jetzt wünsche ich allen, die das nie finden konnten, viel Spaß damit!
Viele Grüße
Marco


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:15 Uhr.

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