开发者

How to get the highlighted item from the desktop or Windows Explorer with syslistview32?

Ho开发者_如何学Gow might I, using Delphi and syslistview32, get the highlighted item from the desktop or Windows Explorer?


I'm not sure what you mean with get item, so I posted here how to get the focused item text. It's more complicated task because list view messages can't fill the buffer between processes, so you need to pass it through the virtual memory pages allocated in the foreign process. But the principle would be the same for any kind of manipulation with foreign items directly. I'm not familiar with process memory allocation; any useful edit will be appreciated.

Note: the code below has been tested on 32 bit Windows XP

function GetFocusedItemText(const LVHandle: HWND): string;
var Size: cardinal;
    Process: THandle;
    ProcessId: DWORD;
    MemLocal: pointer;
    MemRemote: pointer;
    NumBytes: cardinal;
    ItemIndex: integer;

begin
  Result := '';

  ItemIndex := SendMessage(LVHandle, LVM_GETNEXTITEM, -1, LVNI_SELECTED);

  GetWindowThreadProcessId(LVHandle, @ProcessId);
  Process := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, ProcessId);

  if (ItemIndex <> -1) and (Process <> 0) then
  try
    Size := SizeOf(TLVItem) + SizeOf(Char) * MAX_PATH + 1;
    MemLocal := VirtualAlloc(nil, Size, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
    MemRemote := VirtualAllocEx(Process, nil, Size, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);

    if Assigned(MemLocal) and Assigned(MemRemote) then
      try
        ZeroMemory(MemLocal, SizeOf(TLVItem));

        with PLVItem(MemLocal)^ do
          begin
            mask := LVIF_TEXT;
            iItem := ItemIndex;
            pszText := LPTSTR(Cardinal(MemRemote) + Cardinal(SizeOf(TLVItem)));
            cchTextMax := MAX_PATH;
          end;

        NumBytes := 0;

        if WriteProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) then
          if SendMessage(LVHandle, LVM_GETITEM, 0, LPARAM(MemRemote)) <> 0 then
            if ReadProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) then
              Result := string(PChar(Cardinal(MemLocal) + Cardinal(SizeOf(TLVItem))));

      except on E: Exception do
        ShowMessage('Something bad happened :(' + sLineBreak + E.Message);
      end;

    if Assigned(MemRemote) then
      VirtualFreeEx(Process, MemRemote, 0, MEM_RELEASE);

    if Assigned(MemLocal) then
      VirtualFree(MemLocal, 0, MEM_RELEASE);

  finally
    CloseHandle(Process);
  end;
end;

And here's how to call; just pass the handle to it and you'll get the item's text

procedure TForm1.Button1Click(Sender: TObject);
var s: string;
begin
  s := GetItemText(123456);

  if s <> '' then
    ShowMessage(s);
end;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜