这里所谓“窗口盗窃”,是指把其余窗口“装”进程序自身,感受就像是把其余程序“偷”到了本身的袋里。程序还有另外一个重要功能,就是让其余程序没法响应键盘、鼠标消息——固然,这就有点邪恶了,不过实现方法倒是有时在编写Win32程序常常用到的一种技术。本文先简单讲解功能一的实现,下一篇文章将会对功能二进行介绍。函数
要想知道如何把其余程序“装”入自身,那么首先须要理解父窗口的概念。先从窗口提及。
在Win32中,窗口有着丰富的含义,除了常见的大多数应用程序都有的矩形区域是窗口之外,还有不少部分其实也是窗口,好比按钮、编辑框、标签等控件也是窗口,因此在理解什么是窗口时,咱们必定不能仅仅局限于矩形区域这种思惟模式下。
为了能更深刻地读懂窗口以及窗口背后的代码,先来看一下Win32 Platform SDK中用于建立窗口的API CreateWindow的定义:指针
HWND WINAPI CreateWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowName, _In_ DWORD dwStyle, //指定要建立的窗口的样式 _In_ int x, _In_ int y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam );
这里咱们只关心其中的dwStyle参数,关于CreateWindow
的具体用法和更多API介绍,我会在以后的其余文章中陆续给出。
dwStyle是一个32位的双字,也就是说咱们能够用位或操做(|)
将多个属性组合到一块儿,好比,要建立一个按钮时,咱们就能够这么写:code
CreateWindow( "BUTTON", "OK", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, //只看这里 10, 10, 100, 100, hwnd, NULL, (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
这里,咱们就用了三个属性的组合,其中WS_CHILD
代表这是一个子窗口,BS_DEFPUSHBUTTON
说明要建立一个按钮。orm
那么为何要说明这个按钮是一个子窗口呢?由于独立的按钮是不存在的,任何控件都是为了更好的协助用户与主窗口(程序)之间的交互而存在的,控件脱离了所属的窗口是没有意义的。因此,这里的按钮就有一个父窗口,也就是说,按钮所在的窗口就是按钮的父窗口。
不过这里的按钮可不是简单地画在父窗口上,而是附着。说得再直白点,父窗口若是被关闭了,那么按钮也就没有了附着的空间,因而按钮也要被销毁。若是把父窗口当成一面墙,那么按钮就比如是粘在墙上的挂钩;要是墙不存在了,那难道挂钩还能粘在空气上吗?进程
窗口上粘着一大堆控件,咱们也能够把别的程序的窗口当成控件一块儿粘在咱们的窗口上。因此,核心思想就是把别的程序的父窗口设置成咱们的窗口,并且不去管它本来到底有没有父窗口。
这里咱们要用到的最关键的API是CWnd
类中的成员函数 SetParent(这里的示例程序用MFC完成,因此不使用Plaform SDK版本的)。这个函数很简单:get
CWnd* SetParent(CWnd* pWndNewParent);
参数指明要成为该窗口新的父窗口的指针。form
既然把大象装进冰箱要三步,那么通常地,把别的窗口装进咱们的窗口也须要三步:class
找到别的窗口原理
获取该窗口的句柄(指针)程序
装进咱们的窗口
是否是很是的简单?