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

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

xuwenyan3年前 (2021-02-04)c++1052

要获取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桌面图标的位置信息” 的相关文章

    C++智能指针基本原理

    C++智能指针基本原理

    什么是智能指针?最简单来说就是会自动释放内存的指针,使用方便,不用担心内存泄漏问题。它其实就是通过封装,利用对象的析构函数释放申请的内存,基本上自动释放的用法都是利用析构函数去做一些释放工作。如:自动释放的句柄智能指针的基本实现class TestClass {  p...

    Visual Studio编译7z源代码

    Visual Studio编译7z源代码

    源代码下载打开地址https://www.7-zip.org/download.html,选择源码下载,可以选择自己需要的版本下载7z.dll编译1:解压源代码包,打开vs解决方案,CPP7zipBundlesFormat7zFFormat7z.dsw,vs会提示升级,不用管,选择升级。2:修改7z...

    C++指针*为什么靠后会比较好?

    C++指针*为什么靠后会比较好?

    大多数书中和大神的代码里,往往指针的*都是靠变量而不是靠类型的,这主要是为了不造成我们第一眼对变量类型的误解和对指针类型的误解,比如: int* p1,p2 我们一眼看上去是不是通常会觉得p1、p1都是一个int*的指针呢?因为我们通常会误把int*当作一个类型,然而无论int*还是i...

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    例如,我用VC2015的工程向导新建一个ATL的工程名字叫myAtl,那么VC会同时给我生成一个叫做myAtlPS的工程。这个myAtlPS工程是做什么的?什么情况下可以不需要它?什么情况下它又是必须存在的? PS工程是什么?可以不要吗? 这个PS工程叫做代理与存根(proxy&nbs...

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    现象:程序在xp系统上面总是莫名其妙的崩溃,检查代码看不出任何问题,感觉代码都很好。即使你远程调试,找到了崩溃的点,当你注释了崩溃点之后,还是会崩溃到别的地方。当你遇到了这种情况的时候,不妨参照一下下面的方法看看,说不定可以解决问题。如何解决?将崩溃程序相关的所有工程代码全部关闭全局变量的线程安全检...

    uafxcwd.lib(afxmem.obj) : error LNK2005:

    uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法

    如果在编译MFC程序的时候出现下列及类似的错误: 1˃uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMTD.lib(new...