文章目录

  • 一、首先是获取桌面窗口句柄
  • 二、获取桌面图标位置
  • 三、效果展示

经常使用windows系统的同学可能都会遇到这样一种情况,刚按照完的应用程序,可能会在桌面产生一个提示信息,指示当前快捷方式可以使用了,并给出相应的文字说明,指示该快捷方式的功能。那么大家有没有考虑过这供功能是怎么实现的呢,使用一般的窗口spy工具应该都能抓取windows系统桌面使用的窗口类,我使用彗星小助手抓取了下,效果如图1所示。原来windows桌面窗口是一个listview,那么问题就变得简单了,我们只需要拿到窗口句柄,并向其发送消息LVM_GETITEMCOUNT消息,获取到窗口item数量后,在发送LVM_GETITEMTEXTA消息,并读取每一项的文本名称,在和我们自己想要的桌面文件名称对比,如果是目标文件在发送LVM_GETITEMRECT消息,就可以拿到具体的桌面文件位置。下面看具体的实现过程。

看到这篇文章的同学,我推荐一下这个彗星小助手工具,功能挺丰富的,看图1的标题栏就知道了,在没有发现彗星小助手工具之前我采集屏幕颜色一致使用的是picpick,也挺好用,推荐大家使用。除此之外还推荐大家:everything硬盘搜索工具、小屁孩桌面便签

一、首先是获取桌面窗口句柄

获取桌面窗口句柄需要区分xp系统和win7系统,首先我们按win7方式获取,如果获取失败,那么我们再按win xp方式获取,代码如下,拿到桌面窗口句柄后,我们就可以进一步的给桌面窗口发送消息,并获取桌面图标相关信息,不过在此之前我们还需要做一件事,就是区分当前系统的位数,因为32位系统和64位系统的结构有所不一样,需要我们分开做处理。

CRect cRect;HWND hDeskWnd = nullptr;//桌面上SysListView32的窗口句柄HWND hWnd = ::FindWindow(L"WorkerW", nullptr);//先当WIN7系统查找while (hWnd){HWND hShellView = ::FindWindowEx(hWnd, nullptr, L"SHELLDLL_DefView", nullptr);if (hShellView){hDeskWnd = ::FindWindowEx(hShellView, nullptr, L"SysListView32", nullptr);break;}hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);}if (hDeskWnd == nullptr){qDebug() << QStringLiteral("WIN7系统查找方式失败");//如果没找到,再按XP方式查找hWnd = ::FindWindow(L"Progman", L"Program Manager");if (hWnd){hWnd = ::FindWindowEx(hWnd, nullptr, L"SHELLDLL_DefView", nullptr);hDeskWnd = ::FindWindowEx(hWnd, nullptr, L"SysListView32", nullptr);}}if (hDeskWnd == nullptr){QMessageBox::warning(nullptr, QStringLiteral("警告"), QStringLiteral("查找桌面窗口句柄失败"));return false;}

判断系统位数的方法不难,代码如下:

BOOL Is64Bit_OS()//判断操作系统位数{BOOL bRetVal = false;SYSTEM_INFO si = { 0 };LPFN_PGNSI pGNSI = (LPFN_PGNSI)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo");if (pGNSI == nullptr){return false;}pGNSI(&si);if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64|| si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64){bRetVal = true;}else{// 32 位操作系统//_tprintf(L"is 32 bit OS\r\n");}return bRetVal;}

在桌桌面引导的时候你可能还需要显示桌面,我使用的代码如下:

void ShowDesktop(void)//显示桌面{CoInitialize(0);IShellDispatch4 * pdisp = nullptr;CoCreateInstance(CLSID_Shell, nullptr, CLSCTX_ALL, __uuidof(IShellDispatch4), (void **)&pdisp);if (pdisp){pdisp->ToggleDesktop();//这句是用来切换桌面的pdisp->Release();}}

二、获取桌面图标位置

从第一步我们可以成功拿到桌面窗口句柄,接下来我们就只需要给桌面窗口发送一些列的消息,然后拿到我们自己需要的信息。下面我一步一步讲解,贴上关键代码。

注意:32位系统和64位系统发送消息的流程一模一样,只是定义的结构体不一样,因此我只讲解32位的代码,64位的自己一看便明白,文章最后我会附上相关的示例demo。

1、首先是打开一个已存在的进程对象,并返回进程的句柄

GetWindowThreadProcessId(hDeskWnd, &PID); 2 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);

2、在一些机器上,可能会存在打开进程失败的情况,比如我在xp系统上就出现这个问题,那么这个时候就需要提升进程的访问权限,提升进程访问权限代码如下:

BOOL EnableDebugPrivilege(){HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;}

3、如果进程打开失败,则提升进程访问权限,并在此打开进程

if (hProcess == nullptr){unsigned short errorCode = GetLastError();qDebug() << QStringLiteral("获取进程句柄操作失败32 hWnd=%1,PID=%2,errorCode=%3").arg((int)hDeskWnd).arg(PID).arg(errorCode);if (errorCode == 5){qDebug() << QStringLiteral("拒绝访问");if (EnableDebugPrivilege()){qDebug() << QStringLiteral("提升进程访问权限成功");}else{qDebug() << QStringLiteral("提升进程访问权限失败");}GetWindowThreadProcessId(hDeskWnd, &PID);hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);if (hProcess == nullptr){qDebug() << QStringLiteral("进程依然打开失败");}else{qDebug() << QStringLiteral("提升权限后开成功");}}}

4、进程打开成功后,想桌面程序发送LVM_GETITEMCOUNT消息,并获取桌面文件个数

5、遍历桌面所有文件,并发送LVM_GETITEMTEXTA消息,拿到文件的名称,如果是目标文件则进行下一步,否则一直遍历,直到遍历完所有文件并结束

6、如果是目标文件,则发送LVM_GETITEMRECT消息,拿到文件在位置,并返回。

下面我提上完整的获取桌面图标位置代码(32系统上)

if (hProcess){LVITEMA * pLVITEM = (LVITEMA *)VirtualAllocEx(hProcess, nullptr, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);char* pszText = (char *)VirtualAllocEx(hProcess, nullptr, 512, MEM_COMMIT, PAGE_READWRITE);RECT* pItemRc = (RECT *)VirtualAllocEx(hProcess, nullptr, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);RECT rc;if (!pItemRc || !pLVITEM){qDebug() << QStringLiteral("无法分配内存!");}else{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), nullptr);//发送LVM_GETITEM消息BOOL r = (BOOL)::SendMessage(hDeskWnd, LVM_GETITEMTEXTA, iItem, (LPARAM)pLVITEM);//获取pszTextReadProcessMemory(hProcess, pszText, ItemBuf, 512, nullptr);QString str = QString::fromLocal8Bit(ItemBuf);//AfxMessageBox(str);if (str == strIconName){::SendMessage(hDeskWnd, LVM_GETITEMRECT, iItem, (LPARAM)pItemRc);ReadProcessMemory(hProcess, pItemRc, &rc, sizeof(RECT), nullptr);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);}

三、效果展示

下面我展示下我自己在各个平台下测试的结果

1、windows xp 32位,如图2

2、windows 7 32位 如图3

3、windows 10 64位 如图4

demo下载链接

如果需要定制好看的界面可以参考:

QPainterPath 不规则提示框

QPainterPath 不规则提示框(二)

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!

很重要–转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


windows之桌面程序引导功能相关推荐

  1. 有了Windows Defender应用程序防护功能,再也不担心电脑免遭恶意***

    测试者发现,Windows 10 Creators Update (Redstone 2) build 15031中的Edge浏览器已经集成了Windows Defender应用程序防护功能,用户可以 ...

  2. 从零开始用 Windows C++ 桌面程序制作方舟同人游戏(一)

    前言 阅读本博客的前置技能: C++ 基础 好像没了 qwq 为什么开这个坑 很惭愧,虽然每每想要认真的做一个游戏 demo 时,我要么只是停留在了纸面描述上,要么只是建了几个新类,用一个又一个框架/ ...

  3. Go实战--使用golang开发Windows Gui桌面程序(lxn/walk)

    生命不止,继续 go go go!!! golang官方并没有提供Windows gui库,但是今天还是要跟大家分享一下使用golang开发Windows桌面程序,当然又是面向github编程了. 知 ...

  4. 基于Windows的桌面程序——记事本的制作

    1.新建项目 启动Visual Studio .NET ,在"文件"菜单上,指向"添加",然后单击"新建项目"打开"新建项目&qu ...

  5. windows虚拟桌面_如何在Windows 10的新虚拟桌面中打开应用程序或文件

    windows虚拟桌面 Microsoft has finally added virtual desktops as a built-in feature to Windows 10. Virtua ...

  6. 树莓派蓝屏_树莓派刷写Windows 10 ARM版后成功运行桌面程序

    微软在2015年时推出Windows 10 IoT物联网版供树莓派系列以及其他单板电脑安装和部署更多的应用程序. 不过树莓派系列设备本身都是使用博通的ARM处理器,所以也只能运行Windows 10商 ...

  7. windows虚拟桌面_在Windows中使用虚拟桌面的最佳免费程序

    windows虚拟桌面 If you often open a lot of applications at once, a virtual desktop program can help you ...

  8. windows 服务程序和桌面程序集成(一)

    本系列文章介绍如何将windows服务程序和桌面程序集成在一起,也就是说一个EXE程序,既可以作为服务程序运行,也可以作为桌面程序运行的双模程序. 在十几年前,曾经给客户开发一套C/S架构的出单程序, ...

  9. 如何使用Snap功能同时运行两个Windows 8应用程序

    Windows 8's Modern interface includes support for running two Windows 8 apps side-by-side. This feat ...

最新文章

  1. python3并发性能_python几种并发实现方案的性能比较
  2. 深入分析Spark任务调度的原理--Java后端同学入门Spark编程系列
  3. Pytorch 计算参数量与计算量Flops
  4. SQL语句执行效率及分析(note)
  5. python练手_Python数据分析练手项目
  6. 《JavaScript100例|01》之javaScript实现俄罗斯方块,唤起了女朋友儿时的回忆!
  7. js的alert和confirm美化
  8. 华为发布国行版P40系列,售价4188元起;大疆回应“至少50%的裁员清扫计划”;Firefox 75发布 | 极客头条...
  9. 马库斯:DeepMind新出的机器心智网络不错,但有误导性
  10. directUI的心得
  11. 百度以侵犯商业秘密起诉前高管王劲 索赔5000万 内附王劲离职承诺函
  12. 分布式通用爬虫管理平台Crawlab
  13. MapXtreme 根据名称搜索图元
  14. 数学系教材推荐(转载)
  15. c语言设计数字增量pi控制器,PI控制器的工作原理是什么?
  16. 服务器ubuntu系统调节亮度,Ubuntu系统下调节屏幕亮度的两种Linux命令
  17. ambari全攻略流程,编译ambari(三)
  18. 使用putty下载文件
  19. 初学风水-某商务中心店铺
  20. 社区动态|Apache Doris 携手 Tapdata,联合共建开放数据生态

热门文章

  1. 纽曼欲借“机”上位,纽扣获YunOS力挺
  2. 可解释机器学习-shap value的使用
  3. Word2Vec原文翻译
  4. 丁香园样式库DXY-UI正式开源!
  5. [486]Anyproxy的安装和使用
  6. Matlab编程时是否加分号的区别
  7. MATLAB音频数字水印
  8. GIS二次开发学习专题(一)C#入门
  9. 谷歌chrome xp_从Chrome向Google笔记本添加便笺
  10. 香港举办首个轮椅花车巡游 特首冀提升香港通达程度