Einzelnen Beitrag anzeigen

Marco Steinebach

Registriert seit: 4. Aug 2006
502 Beiträge
 
Delphi 5 Enterprise
 
#1

Demo für ShellExtension - brauche noch Hilfe

  Alt 31. Aug 2009, 19:47
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
Angehängte Dateien
Dateityp: zip shellextension_157.zip (5,4 KB, 4x aufgerufen)
Marco Steinebach
  Mit Zitat antworten Zitat