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