怎么在桌面上嵌入窗口(使用FindWindow(),FindWindowEx(),EnumChildWindows())

打开spy++

我们可以发现桌面窗口是一个位于Progman的类名下的类名为SHELLDLL_DefView的子窗口的子窗口,也就是说我们把我们自己的窗口设置为SHELLDLL_DefView的子窗口就可以实现窗口邦定桌面,好了我们下面介绍一下两函数

HWND FindWindow( LPCTSTR lpClassName,
LPCTSTR lpWindowName);
.参数说明:
lpClassName
指向一个以null结尾的、用来指定窗口类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个在调用此函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。
lpWindowName
指向一个以null结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。
返回值:
如果函数执行成功,则返回值是拥有指定窗口类名或窗口名的窗口的句柄。
如果函数执行失败,则返回值为 NULL 。

函数原型:
HWND FindWindowEx(HWND hwndParent,HWND hwndchildAfter,LPCTSTR lpszClass,LPCTSTR lpszWindow);
参数:
hwndParent:要查找的子窗口的父窗口句柄。如果值为null这查找桌面窗口的所有子窗口。
hwndchildAfter:子窗口句柄。从Z序中的下一个子窗口开始。子窗口必须为hwndParent的直接子窗口而非后代窗口。如果hwndchildAfter为NULL,查找从hwndParent的第一子窗口开始。如果hwndParent和hwndChildAfter同时为NULL,则函数查找所有的顶层窗口及消息窗口。
lpszClass:指向了类名的空结束字符串,或一个标识类名字符串的成员指针。如果该参数为一个成员,则它必须为前次调用theGlobalAddAtom函数产生的全局成员。该成员为16,必须位于lpClassName的低16位,高位必须为0.
lpzWindow:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为NULL,则为所有窗口全匹配。如果该参数为NULL,则为所有窗口全匹配。
返回值:
如果匹配成功则返回指定类名和窗口名的窗口句柄。如果失败则返回NULL。
SetParent(HWND hwndchild,HWND hwndparent);
作用设置窗口父子关系,hwndchild子窗口句柄,hwndparent父窗口句柄。
ok下面我们可以写程序了。
实现代码:

#include <windows.h>
HWND hwnd=NULL;
LRESULT CALLBACK child_dohandle(HWND hWnd,UINT message,WPARAM wparam,LPARAM lparam)
{HDC hdc;char str[100];switch(message){case WM_PAINT:hdc=GetDC(hWnd);sprintf(str,"%s","hello world!");TextOut(hdc,10,0,str,strlen(str));ReleaseDC(hWnd,hdc);break;case WM_LBUTTONDOWN:break;case WM_TIMER:break;case WM_CREATE:break;case WM_COMMAND:break;case WM_CLOSE:DestroyWindow(hWnd);break;case WM_DESTROY:PostQuitMessage(0);break;default://如果没有需要处理的消息,就调用默认的过程函数return DefWindowProc(hWnd,message,wparam,lparam);}return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR     lpCmdLine,int       nCmdShow)
{// TODO: Place code here.HWND hWndProgram=NULL,hWnd;WNDCLASSEX win={0};int width,height;char str[100];MSG msg = {0};win.style=CS_HREDRAW|CS_VREDRAW|WS_EX_TOOLWINDOW;win.cbSize=sizeof(WNDCLASSEX);win.cbClsExtra = 0;win.hInstance = hInstance;win.cbWndExtra=sizeof(long);win.hIcon = NULL;win.hCursor = LoadCursor(NULL,IDC_ARROW);win.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);win.lpszClassName = TEXT("poppy");win.lpszMenuName = 0;win.lpfnWndProc = child_dohandle;hWndProgram=FindWindow(TEXT("Progman"),TEXT("Program Manager"));//hWndProgram=FindWindow(TEXT("WorkerW"),NULL);if(hWndProgram==NULL){MessageBox(NULL,TEXT("Progman句柄获取失败"),TEXT("提示"),0);return 0;}hwnd=FindWindowEx(hWndProgram,NULL,TEXT("SHELLDLL_DefView"),NULL);if(hwnd==NULL){MessageBox(NULL,TEXT("SHELLDLL_DefView句柄获取失败"),TEXT("提示"),0);return 0;}if (!RegisterClassEx(&win)){MessageBox(NULL,TEXT("窗口注册失败"),TEXT("提示"),0);return -1;}width=GetSystemMetrics(SM_CXSCREEN);height=GetSystemMetrics(SM_CYSCREEN);hWnd=CreateWindow("poppy",//结构体的名称,也就是Name属性NULL,WS_POPUP | WS_VISIBLE,//窗体的层叠样式,通常为WS_OVERLAPPEDWINDOWwidth-100,//窗口位置,X坐标,可以给具体的的值,一般为CW_USEDFAULT即可height-100-10,//窗口位置,Y坐标,可以给具体的的值,一般为CW_USEDFAULT即可100,//窗口的宽100,//窗口的高hwnd,//窗体的父窗体,为NULL,意思就是如果一个窗体打开两次,那么第一次的就是父窗体NULL,//窗体的菜单资源,这里给NULL,表示没有hInstance,//(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),//窗体的实列,直接给WinMain函数里面的参数就行了NULL);SetParent(hWnd,hwnd);ShowWindow(hWnd,nCmdShow);UpdateWindow(hWnd);while (msg.message!=WM_QUIT)//判断是否退出程序,如果没有退出,就一直循环读取消息{if (PeekMessage(&msg,//存消息信息的结构体0,//窗体的句柄,0表示获取所有消息0,//消息最小值,为0即可0,//消息最大值,为0即可PM_REMOVE)//读取后,如果存在,发送消息,并移除该条信息)//读取消息{TranslateMessage(&msg);//将虚拟键消息转换为字符消息DispatchMessage(&msg);//把这个消息发给窗口程序}}UnregisterClass("poppy",hInstance);return 0;
}


如图我们已经可以看到窗口成功嵌在了桌面上了,因为这个窗口是桌面的子窗口我们在任务栏也看不到进程的图标。
然而这样并不是很完美,当小编使用了VMWare虚拟机后一切都变。

用spy++获取桌面句柄时变成了这样,SHELLDLL_DefView类名的窗口变成了类名为WorkerW类名的子窗口,这还不是最操蛋的,最坑的是WorkerW类名的窗口没有窗口标题并且WorkerW类名的窗口一大堆。这可是坑死小编我了。不过小编有强迫症,一定要解决这个问题。
下面介绍另一个功能更强大的函数
BOOL
WINAPI
EnumChildWindows(
HWND hWndParent,
WNDENUMPROC lpEnumFunc,
LPARAM lParam);

参数:
hWndParent父窗口句柄,lpEnumFunc回调函数,lParam回调函数传递的参数
注意回调函数应该这样构造(BOOL CALLBACK findhwnds(HWND hWnd,LPARAM lParam))
回调函数返回TRUE时继续枚举父窗口下的子窗口句柄,为FLASE时停止枚举。
GetDesktopWindow()
作用返回桌面窗口句柄(即所有窗口的始祖)。
改进后的核心代码`在这里插入代码片`

BOOL CALLBACK findhwnds(HWND hWnd,LPARAM lParam)
{
HWND h,d,c;
h=FindWindowEx(hWnd,NULL,TEXT(“SHELLDLL_DefView”),NULL);
if(h!=NULL)
{
printf(“ojbk\r\n”);
d=FindWindowEx(h,NULL,TEXT(“SysListView32”),NULL);
if(dNULL)
return TRUE;
c=FindWindowEx(d,NULL,TEXT(“SysHeader32”),NULL);
if(cNULL)
return TRUE;
hwnd=h;
return FALSE;
}
return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
HWND hWndProgram=NULL,hWnd;
WNDCLASSEX win={0};
int width,height;
char str[100];
MSG msg = {0};

win.style=CS_HREDRAW|CS_VREDRAW|WS_EX_TOOLWINDOW;
win.cbSize=sizeof(WNDCLASSEX);
win.cbClsExtra = 0;
win.hInstance = hInstance;win.cbWndExtra=sizeof(long);
win.hIcon = NULL;
win.hCursor = LoadCursor(NULL,IDC_ARROW);
win.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
win.lpszClassName = TEXT("poppy");
win.lpszMenuName = 0;
win.lpfnWndProc = child_dohandle;hWndProgram=FindWindow(TEXT("Progman"),TEXT("Program Manager"));
//hWndProgram=FindWindow(TEXT("WorkerW"),NULL);
if(hWndProgram==NULL)
{MessageBox(NULL,TEXT("Progman句柄获取失败"),TEXT("提示"),0);return 0;
}
hwnd=FindWindowEx(hWndProgram,NULL,TEXT("SHELLDLL_DefView"),NULL);
if(hwnd==NULL)
{EnumChildWindows(GetDesktopWindow(),(WNDENUMPROC)findhwnds,(LPARAM)NULL);
}
if(hwnd==NULL)
{MessageBox(NULL,TEXT("SHELLDLL_DefView句柄获取失败"),TEXT("提示"),0);return 0;
}
if (!RegisterClassEx(&win))
{MessageBox(NULL,TEXT("窗口注册失败"),TEXT("提示"),0);return -1;
}
width=GetSystemMetrics(SM_CXSCREEN);
height=GetSystemMetrics(SM_CYSCREEN);
hWnd=CreateWindow("poppy",//结构体的名称,也就是Name属性NULL,WS_OVERLAPPEDWINDOW | WS_VISIBLE,//WS_POPUP | WS_VISIBLE,//窗体的层叠样式,通常为WS_OVERLAPPEDWINDOWwidth-100,//窗口位置,X坐标,可以给具体的的值,一般为CW_USEDFAULT即可height-100-10,//窗口位置,Y坐标,可以给具体的的值,一般为CW_USEDFAULT即可100,//窗口的宽100,//窗口的高hwnd,//窗体的父窗体,为NULL,意思就是如果一个窗体打开两次,那么第一次的就是父窗体NULL,//窗体的菜单资源,这里给NULL,表示没有hInstance,//(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),//窗体的实列,直接给WinMain函数里面的参数就行了NULL);
SetParent(hWnd,hwnd);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while (msg.message!=WM_QUIT)//判断是否退出程序,如果没有退出,就一直循环读取消息
{if (PeekMessage(&msg,//存消息信息的结构体0,//窗体的句柄,0表示获取所有消息0,//消息最小值,为0即可0,//消息最大值,为0即可PM_REMOVE)//读取后,如果存在,发送消息,并移除该条信息)//读取消息{TranslateMessage(&msg);//将虚拟键消息转换为字符消息DispatchMessage(&msg);//把这个消息发给窗口程序}
}
UnregisterClass("poppy",hInstance);
return 0;

}

演示如下图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190710125120566.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1Nzc4NDgz,size_16,color_FFFFFF,t_70)![在这里插入图片描述](https://img-blog.csdnimg.cn/20190710125129792.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1Nzc4NDgz,size_16,color_FFFFFF,t_70)
貌似网吧里面的打广告的程序就是这样实现的。OK了。

怎么在桌面上嵌入窗口(使用FindWindow(),FindWindowEx(),EnumChildWindows())相关推荐

  1. java怎么捕捉游戏窗口_捕捉桌面上的窗口信息

    今天我为大家带来一个有趣的例子,有点像Spy++的功能,通过鼠标在屏幕上移动,并实时捕捉指定坐标点处的窗口信息. 窗口信息包括窗口标题,窗口句柄,窗口类名,以及呈现所捕捉窗口的缩略图. 现在我们不妨来 ...

  2. linux把终端嵌入桌面,在Ubuntu Linux桌面上嵌入终端窗口

    除了Tilda 和 Yakuake 终端具有嵌入桌面的效果之外,使用 Devil's Pie 这个小程序你同样可以将终端窗口嵌入到你的 Linux 桌面. 下面就以 GNOME Terminal 为例 ...

  3. win10计算机从桌面消失了,Windows10家庭版程序窗口在桌面上消失了解决方法

    相信大家对于电脑非常不陌生吧,当你遇到Win10程序窗口桌面上消失了怎么办这个问题该怎么解决吗?不知道了吧,接下来小编就以程序窗口时所遇到的Win10程序窗口桌面上消失了怎么办问题来给大家讲讲,看看小 ...

  4. java swing 悬浮_[Java教程]JAVA Swing窗口在桌面上浮动_星空网

    JAVA Swing窗口在桌面上浮动 2012-02-15 0 1 class Util { 2 private Toolkit tool; 3 private int width; 4 privat ...

  5. Android 如何预置桌面上的应用程序图标、快捷方式图标或者窗口小部件?

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  6. 在windows7桌面上新建一个快捷方式,指向cmd命令窗口

    1,桌面上右键-新建-快捷方式: 2,项目的位置:cmd.exe /k "bootsect.exe" 3,名称:自己起,确定: 4,右键单击刚才创建的快捷方式-属性-高级,勾选&q ...

  7. 如何在移动和桌面网络应用程序上嵌入YouTube视频?

    Why host your videos on Youtube? 为什么要在YouTube上托管您的视频? Though, it is possible to get the video file U ...

  8. 如何在PC桌面上添加便笺

    现在大家使用的电脑大多数都有自带的便笺,windows7系统的电脑在开始菜单中的附件可以找到,windows10系统的电脑直接在开始菜单中就能找到,打开后就可以在桌面上使用,系统自带的便笺功能单一,现 ...

  9. 桌面上倒计时提醒的好用软件有哪些 热门好看桌面倒计时软件推荐

    在使用电脑办公时,有很多好用的办公工具都能用来辅助日常工作,能实时显示某些重要任务还有多久时间到期的倒计时软件就是其中之一.那桌面上倒计时的好用软件有哪些?小编给大家整理了一些热门且值得推荐的好看的桌 ...

最新文章

  1. 时序数据库连载系列: 时序数据库一哥InfluxDB之存储机制解析
  2. 成功解决 from ._conv import register_converters as _register_converters
  3. 【Redis】有序集合的交集与并集
  4. 普朗克黑体辐射定律python代码实现
  5. 吴恩达《深度学习》第四门课(4)特殊应用:人脸识别和神经风格迁移
  6. python socket tcp实战_python socket 实战
  7. java报错:java:xxx包不存在
  8. linux性能架构,Linux性能及调优指南(翻译)之Linux内存架构
  9. shiro实战系列(十一)之Caching
  10. sql中毫秒数与格式化时间的转换
  11. 科学计算器 java_用Java编写的标准计算器、科学计算器、时间转换。
  12. PyQt5--google快捷翻译
  13. https 双向认证基本配置学习
  14. 邮箱格式怎么填写才正确?Tom邮箱格式怎么写?邮箱的正确填写?
  15. VR火灾隐患排查,模拟多种火灾场景
  16. 全国一二线城市各大互联网(IT)公司,各位找工作的小伙伴可以参考
  17. mysql migration 使用_DbMigration的使用方法
  18. Linux的基础文件操作1
  19. 互联网创业公司的管理
  20. Unity 自发光(燃烧)溶解Shader

热门文章

  1. 3dsmax模型导入unity3d新手操作
  2. Android Camera HDR 拍照模式的原理
  3. 什么是HDR拍摄模式及使用方法
  4. Linux设置防火墙允许icmp,Linux下防火墙设置
  5. 视频智能分析结果存储方案
  6. 克里金插值法(kringing)与PHPnow集成开发环境
  7. 阿里云服务器安装配置nginx
  8. flashfxp使用方法,偷偷告诉你flashfxp使用方法
  9. iphone绑定教育邮箱_如何将iPhone绑定到Linux PC
  10. 【小程序模板】功能模块+仿vivo手机商城微信小程序+品牌手机APP购物网页模板