当前位置: 首页 > article >正文

Windows动态桌面原理

测试所用系统版本

OS 名称:Microsoft Windows 10 家庭版;版本号:10.0.14393 暂缺 Build 14393
OS 名称:Microsoft Windows 7   企业版;版本号: 6.1.7600 暂缺 Build 7600(已启用Aero)
本章原理在以上Windows系统版本均已测试成功

原理阐述以及实践操作

Windows顾名思义即窗口的意思,我们平常所接触的桌面、任务栏实际上也是窗口,就和我们所使用的应用软件窗口一样,而且对于开启Aero的Win7和Win10,桌面图标所在的窗口层和桌面背景(壁纸)所在的窗口层不是同一个。通过使用VS自带的工具spy对桌面窗口进行剖析,获取窗口信息,获得下图:

图中窗口类SysListView32(红色箭头所指)即为桌面图标的窗口,可见,正常情况下该窗口是父窗口Progman的子窗口。通过下列代码可以激发窗口发生一个有趣的变化。

//获取Progman的窗口句柄
HWND windowHandle = FindWindow(L"Progman", NULL);
//向Progman发送特殊消息
SendMessageTimeout(windowHandle, 0x052c, 0 ,0, SMTO_NORMAL, 0x3e8,(PDWORD_PTR)&result);

在执行了上述代码后,重新使用spy获取桌面窗口的信息,得到下图:

可以轻松的发现,多出了两个WorkerW窗口(蓝线所标),而原来的SysListView32窗口不再以Progman为父窗口,而是以第一个WorkerW窗口为父窗口,这种设计的原因可能是微软为了防止壁纸更换时出现画面撕裂所采取,而动态桌面的原理便是利用这种设计。所谓的动态桌面就是把自己的应用程序嵌入桌面背景的窗口层,比如:把视频用作动态桌面,实际上就是写一个播放视频的程序,然后把该程序的窗口嵌入到桌面背景的窗口。要想实现这种嵌入,需要获取程序的窗口句柄,然后获取桌面背景的窗口句柄,最后通过SetParent函数把程序窗口作为桌面背景窗口的子窗口即可,由于上图中的第二个WorkerW与Progman都可作为桌面背景窗口(桌面背景窗口可以不只一个),对此,下面将分别介绍针对这两个窗口具体操作实现(至于为什么不以第一个WorkerW为父窗口或者以发送特殊消息前的Progman为父窗口?因为SysListView32与你的程序窗口以同一个窗口为父窗口会导致桌面图标与程序处于同一窗口层,就好像一个窗口下的两个控件,不好看啊):
1、程序窗口将Progman作为父窗口

HWND workerw=NULL;     //第二个WorkerW窗口句柄inline BOOL CALLBACK EnumWindowsProc(HWND handle,LPARAM lparam)
{//获取第一个WorkerW窗口HWND defview = FindWindowEx(handle, 0, L"SHELLDLL_DefView", NULL);if (defview != NULL) //找到第一个WorkerW窗口{//获取第二个WorkerW窗口的窗口句柄workerw = FindWindowEx(0, handle, L"WorkerW", 0);}return true;
}//参数myAppHwnd为你开发的窗口程序的窗口句柄
void SetDesktop(HWND myAppHwnd)
{int result;HWND windowHandle = FindWindow(L"Progman", NULL);SendMessageTimeout(windowHandle, 0x052c, 0 ,0, SMTO_NORMAL, 0x3e8,(PDWORD_PTR)&result);//枚举窗口EnumWindows(EnumWindowsProc,(LPARAM)NULL);//隐藏第二个WorkerW窗口,当以Progman为父窗口时需要对其进行隐藏,//不然程序窗口会被第二个WorkerW覆盖ShowWindow(workerw,SW_HIDE);SetParent(myAppHwnd,windowHandle);
}

2、程序窗口将第二个WorkerW作为父窗口
代码与上面的代码基本一致,只需要将ShowWindow(workerw,SW_HIDE)删除,并将SetParent(myAppHwnd,windowHandle)的第二个参数更改为workerw即可。

注意:
1、WorkerW其实不只有两个,本文中的第一个与第二个WorkerW窗口指的是向Progman发送特殊消息后产生的两个窗口,这两个窗口在Z序上邻近,正因为如此,所以我们需要锁定第一个WorkerW,再找到第二个WorkerW;
2、程序窗口嵌入到桌面背景,作为桌面背景后,程序窗口将无法响应你的键盘和鼠标操作,OS不会对其进行聚焦,需要另外进行处理;
3、理论上,这种方法对于其它程序窗口也适用,比如自己开发一个浏览器,你可以把浏览器变为桌面背景;
4、细心的同学会发现,SysListView32桌面图标的父窗口其实为SHELLDLL_DefView,SHELLDLL_DefView的父窗口才是Progman或第一个WorkerW,这里为了方便叙述,省略掉了。

http://www.lryc.cn/news/2417432.html

相关文章:

  • 旗胜限价房让我深刻体会到我很傻很天真
  • crash调试linux dump信息
  • UT AUSTINVILLA 3D
  • 主板维修从入门到精通
  • activity启动模式应用,如FLAG_ACTIVITY_CLEAR_TOP
  • 分支语句——switch-case
  • 毕业论文中的图表目录
  • 单片机定时器中断(之中断概念)
  • 使用nlite制作集成驱动windows安装光盘及实践心得
  • 关于sqlserver中SqlParameter的用法注意事项
  • ccbp 知识点
  • 服务器出现大量 TIME_WAIT,如何解决
  • JavaSE:实现象棋游戏
  • 古典密码(部分合集)
  • VC6.0常见错误之::Debug Assertion Failed!
  • C#使用FileSystemWatcher来监控指定文件夹,并使用TCP/IP协议通过Socket发送到另外指定文件夹
  • 虚拟机Linux IP地址更改
  • 13 | 如何为团队设定合理的目标呢?
  • input标签 各属性解释
  • 热插拔机制之udev和mdev
  • MFC教程(Visual C++ 6.0)|合集 |更新中
  • bluetooth 外围设备 驱动有问题 解决办法
  • java中Date/Time/Timestamp对应sql
  • 数据库之 MongoDB and SQLite
  • img文件制作linux启动u盘,制作Linux的U盘启动盘
  • Python后端---使用Django+Mysql搭建一个简单的网站
  • 1.4种权限控制
  • Oracle INSERT INTO的几种用法
  • 效率工具:分享7款实用的任务管理软件,值得收藏!
  • d3dx9_25.dll文件丢失的解决方法