如何使用 syslistview32 从桌面或 Windows 资源管理器获取突出显示的项目?

发布于 2024-11-06 11:58:34 字数 64 浏览 0 评论 0原文

我如何使用 Delphi 和 syslistview32 从桌面或 Windows 资源管理器获取突出显示的项目?

How might I, using Delphi and syslistview32, get the highlighted item from the desktop or Windows Explorer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

亢潮 2024-11-13 11:58:34

我不确定您的获取项目是什么意思,所以我在这里发布了如何获取焦点项目文本。这是更复杂的任务,因为列表视图消息无法填充进程之间的缓冲区,因此您需要通过在外部进程中分配的虚拟内存页面传递它。但对于任何直接对外国物品进行的操纵,原则都是相同的。我不熟悉进程内存分配;任何有用的编辑将不胜感激。

注意:下面的代码已经在32位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;

,调用方法如下;只需将句柄传递给它,您就会获得该项目的文本

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

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

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文