当前位置:首页 > c++ > 正文内容

C++获取windows桌面图标的位置信息

xuwenyan2年前 (2021-02-04)c++610

要获取windows桌面图标的位置,大致是下面几个步骤,具体请参阅后面的代码:

  • 1:获取桌面图标层的窗口句柄,也就是SysListView32层,当然xp系统和非xp系统父窗口是不同的,具体请看GetIconRect中的代码。

  • 2:根据窗口句柄获取到进程id,然后往进程中分配一块内存,用于存储图标信息,32位系统和64位系统分配的内存大小是不一样的。

  • 3:通过LVM_GETITEMCOUNT获取到图标的个数,通过LVM_GETITEMTEXTA获取图标的名字判断是否为我们需要获取的图标,然后通过LVM_GETITEMRECT获取图标的位置信息。

#include <tchar.h>
#include <Commctrl.h>
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")

typedef void (WINAPI* LPFN_PGNSI)(LPSYSTEM_INFO);

typedef struct tagLVITEM64A {
  UINT mask;
  int iItem;
  int iSubItem;
  UINT state;
  UINT stateMask;
  INT64 pszText;
  int cchTextMax;
  int iImage;
  LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
  int iIndent;
#endif
#if (_WIN32_WINNT >= 0x501)
  int iGroupId;
  UINT cColumns; // tile view columns
  PUINT puColumns;
#endif
} LVITEM64A, * LPLVITEM64A;

//==取桌面图标位置=======================
BOOL GetIconRect(char* strIconName, LPRECT lpRect, HWND& hDeskListView) {
  HWND hDeskWnd = NULL;//桌面上SysListView32的窗口句柄
  HWND hWnd = ::FindWindow(_T("WorkerW"), NULL);//先当WIN7系统查找
  while (hWnd) {
    HWND hShellView = ::FindWindowEx(hWnd, NULL, _T("SHELLDLL_DefView"),
      NULL);
    if (hShellView) {
      hDeskWnd = ::FindWindowEx(hShellView, NULL, _T("SysListView32"), NULL);
      break;
    }
    hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  }
  if (!hDeskWnd) { // 如果没找到,再按XP方式查找
    hWnd = ::FindWindow(_T("Progman"), _T("Program Manager"));
    if (hWnd) {
      hWnd = ::FindWindowEx(hWnd, NULL, _T("SHELLDLL_DefView"), NULL);
      hDeskWnd = ::FindWindowEx(hWnd, NULL, _T("SysListView32"), NULL);
    }
  }
  if (!hDeskWnd) {
    return FALSE;
  }
  hDeskListView = hDeskWnd;
  BOOL bRet = FALSE;
  if (Is64Bit_OS()) {
    bRet = GetIconRect64(hDeskWnd, strIconName, lpRect);
  }
  else {
    bRet = GetIconRect32(hDeskWnd, strIconName, lpRect);
  }
  if (bRet) {
    POINT pt;
    pt.x = lpRect->left;
    pt.y = lpRect->top;
    ::ClientToScreen(hDeskWnd, &pt);
    OffsetRect(lpRect, pt.x - lpRect->left, pt.y - lpRect->top);
  }
  return bRet;
}

BOOL GetIconRect32(HWND hDeskWnd, char* strIconName, LPRECT lpRect) {
  BOOL bRet = FALSE;
  //-----------------------------
  //遍历外部进程所有图标
  DWORD PID = 0;
  GetWindowThreadProcessId(hDeskWnd, &PID);
  HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  if (hProcess != NULL) {
    LVITEMA* pLVITEM = (LVITEMA*)VirtualAllocEx(hProcess, NULL,
      sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
    char* pszText = (char*)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT,
      PAGE_READWRITE);
    RECT* pItemRc = (RECT*)VirtualAllocEx(hProcess, NULL, sizeof(RECT),
      MEM_COMMIT, PAGE_READWRITE);
    RECT rc;
    if (pItemRc != NULL && pLVITEM != NULL) {
      LVITEMA LVITEM;
      LVITEM.mask = LVIF_TEXT;
      LVITEM.cchTextMax = 512;
      LVITEM.pszText = pszText;
      char ItemBuf[512];
      int nCount = ::SendMessage(hDeskWnd, LVM_GETITEMCOUNT, 0, 0);
      for (int iItem = 0; iItem < nCount; iItem++) {
        LVITEM.iItem = iItem;
        LVITEM.iSubItem = 0;
        //将设置好的结构插入目标进程
        WriteProcessMemory(hProcess, pLVITEM, &LVITEM, sizeof(LVITEM), NULL);
        //发送LVM_GETITEM消息
        BOOL r = (BOOL)::SendMessage(hDeskWnd, LVM_GETITEMTEXTA, iItem, (
          LPARAM)pLVITEM);
        //获取pszText
        ReadProcessMemory(hProcess, pszText, ItemBuf, 512, NULL);
        if (StrCmpA(ItemBuf, strIconName) == 0) {
          ::SendMessage(hDeskWnd, LVM_GETITEMRECT, iItem, (LPARAM)pItemRc);
          ReadProcessMemory(hProcess, pItemRc, &rc, sizeof(RECT), NULL);
          memcpy(lpRect, &rc, sizeof(RECT));
          bRet = TRUE;
          break;
        }
      }
      VirtualFreeEx(hProcess, pLVITEM, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, pItemRc, 0, MEM_RELEASE);//释放内存
    }
    CloseHandle(hProcess);
  }
  return bRet;
}

BOOL GetIconRect64(HWND hDeskWnd, char* strIconName, LPRECT lpRect) {
  BOOL bRet = FALSE;
  //遍历外部进程所有图标
  DWORD PID = 0;
  GetWindowThreadProcessId(hDeskWnd, &PID);
  HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  if (hProcess != NULL) {
    LVITEM64A* pLVITEM = (LVITEM64A*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM64A), MEM_COMMIT, PAGE_READWRITE);
    char* pszText = (char*)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
    RECT* pItemRc = (RECT*)VirtualAllocEx(hProcess, NULL, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);
    RECT rc;
    if (pItemRc != NULL || pLVITEM != NULL) {
      LVITEM64A LVITEM;
      LVITEM.mask = LVIF_TEXT;
      LVITEM.cchTextMax = 512;
      LVITEM.pszText = (INT64)pszText;
      char ItemBuf[512];
      int nCount = ::SendMessage(hDeskWnd, LVM_GETITEMCOUNT, 0, 0);
      for (int iItem = 0; iItem < nCount; iItem++) {
        LVITEM.iItem = iItem;
        LVITEM.iSubItem = 0;
        //将设置好的结构插入目标进程
        WriteProcessMemory(hProcess, pLVITEM, &LVITEM, sizeof(LVITEM), NULL);
        //发送LVM_GETITEM消息
        BOOL r = (BOOL)::SendMessage(hDeskWnd, LVM_GETITEMTEXTA, iItem, (LPARAM)pLVITEM);
        //获取pszText
        ReadProcessMemory(hProcess, pszText, ItemBuf, 512, NULL);
        if (StrCmpA(ItemBuf, strIconName) == 0) {
          ::SendMessage(hDeskWnd, LVM_GETITEMRECT, iItem, (LPARAM)pItemRc);
          ReadProcessMemory(hProcess, pItemRc, &rc, sizeof(RECT), NULL);
          memcpy(lpRect, &rc, sizeof(RECT));
          bRet = TRUE;
          break;
        }
      }
      VirtualFreeEx(hProcess, pLVITEM, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, pItemRc, 0, MEM_RELEASE);//释放内存
    }
    CloseHandle(hProcess);
  }
  return bRet;
}

BOOL Is64Bit_OS() {
  BOOL bRetVal = FALSE;
  SYSTEM_INFO si = { 0 };
  LPFN_PGNSI pGNSI =
    (LPFN_PGNSI)GetProcAddress(GetModuleHandle(_T("kernel32.dll")),
      "GetNativeSystemInfo");
  if (pGNSI == NULL) {
    return FALSE;
  }
  pGNSI(&si);
  if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
    si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
    bRetVal = TRUE;
  }
  return bRetVal;
}

void main() {
  GetIconRect("Internet Explorer", ...)
}
    文章作者:xuwenyan
    版权声明:本文为本站原创文章,转载请注明出处,非常感谢,如版权漏申明或您觉得任何有异议的地方欢迎与本站取得联系。

    扫描二维码推送至手机访问。

    版权声明:本文由艺文笔记发布,如需转载请注明出处。

    本文链接:https://www.xuwenyan.com/archives/101

    分享给朋友:

    “C++获取windows桌面图标的位置信息” 的相关文章

    使用GDI、MFC_GDI、GDI+绘制数组RGBA序列

    使用GDI、MFC_GDI、GDI+绘制数组RGBA序列

    学习ffmpeg时遇到一个问题,ffmpeg解码出RGB颜色后怎么绘制到屏幕上,于是将GDI、MFC_GDI、GDI+等方式都记录一下 1:注意按windows的要求,R、G、B、A顺序要调整为B、G、R、A 。 2:GDI不支持透明通道A,透明通道A的值读进去以后没有作用。想要支持透...

    C++ 获取进程所在目录(进程全路径)

    C++ 获取进程所在目录(进程全路径)

    打开windows任务管理器,会看到很多的进程在运行,随机挑选一个,如何通过c++代码获取某一个进程的所在全路径呢?这也是在windows软件开发中经常遇到的需求。通过进程名获取进程全路径由于可能很多进程叫同一个名字,所以获得的结果也有可能是多个#include <windows.h...

    c++函数模板参数类型限定

    c++函数模板参数类型限定

    函数模板函数模板可以实现对不同数据类型做统一操作,比如比较两个数据的大小:template<typename T> bool compare(T& a,T& b) {   return a...

    static_assert和assert有什么区别?

    static_assert和assert有什么区别?

    static_assert和assert都是断言,都可用于判断一个条件是否成立,并且在条件不成立时及时给出错误提示。那它们用什么不同和需要注意的地方呢? 1:static_assert在编译期执行,而assert在运行期执行。2:static_assert无论在debug模式还是relea...

    c++为什么不能在构造函数里调用虚函数?

    c++为什么不能在构造函数里调用虚函数?

    c++为什么不能在构造函数里调用虚函数? c++的构造顺序先构造父类,然后构造子类,析构顺序相反。 如果在构造函数调用虚函数,例如:ClassB继承于ClassA,如果在ClassA的构造函数里调用虚函数,此时因为ClassB并没有构造,所以ClassB的成员都没有初始化,如果编译执行...

    排序算法-选择排序

    排序算法-选择排序

    选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。时间复杂度O(n²)最坏情况合适发生?数组顺序与需要的顺序正好相反。步骤首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。再...