这两天作的截图自动识别窗口。最终要求效果:将当前鼠标所在的窗口用颜色框框起来,单击后选中该区域。
实现步骤:
利用EnumWindows函数遍历了桌面上的全部窗口,用这个函数遍历完获得上百个窗口,本身总共才开了3、四个窗口,居然能遍历到这么多,只能进行筛选,将不须要的窗口进行过滤。ide
//在主函数中调用该函数 EnumWindows(EnumWindowsProc, NULL);
BOOL CaptureWindow::EnumWindowsProc(HWND hWnd, LPARAM lParam) { LONG gwl_style = GetWindowLong(hWnd, GWL_STYLE); if (!(gwl_style & WS_POPUP)&&GetParent(hWnd) == NULL && IsWindowVisible(hWnd)&&IsWindowEnabled(hWnd)) { //能够对过滤后所获得的窗口进行处理 //、、、 // EnumChildWindows(hWnd, EnumChildWindowsProc, NULL); //获取父窗口的全部子窗口 } return true; }
BOOL CaptureWindow::EnumChildWindowsProc(HWND hWnd, LPARAM lParam) { LONG gwl_style = GetWindowLong(hWnd, GWL_STYLE); if (!(gwl_style & WS_POPUP) && GetParent(hWnd) == NULL && IsWindowVisible(hWnd) && IsWindowEnabled(hWnd)) { WCHAR WindowTitle[100] = { 0 }; ::GetWindowText(hWnd, WindowTitle, 100);//获取句柄对应的窗体名字 HWND hq = FindWindowEx(hWnd, NULL, NULL, WindowTitle);//根据窗体名字找到对应句柄,这里重复了,只是熟悉一下这个函数 if (hq == NULL) { return TRUE; } RECT rect; GetWindowRect(hq, &rect);//获取该句柄所掌控的区域 //这里能够作一些本身须要的操做 return true; } //这里也能够作一些操做 return true; }
EnumWindows函数会遍历桌面上全部的窗口,当回调函数EnumWindowsProc返回false时,终止遍历,返回true继续遍历剩下的。当找到你须要的窗口,能够返回false,下降函数复杂度,顺带减小点运行时间。由于我须要获取全部的窗口,最后根据鼠标位置来匹配句柄所在的区域,因此返回我都是用的true。
获取到桌面上咱们看的见的窗口句柄及其对应的区域后,获取鼠标当前位置,遍历句柄,肯定当前鼠标在哪一个句柄掌控的区域中,利用GetCursorPos(p),此处的p为POINT类型。而后调用下述函数:函数
HCR CaptureWindow::getRect(const POINT pt) { HCR rect = 0; vector<Handle_Correspondence_Region>::iterator it = Handle_Correspondence_Region_vector.begin(); for (it; it != Handle_Correspondence_Region_vector.end(); it++) { if (it->left <= pt.x&&it->right >= pt.x&&it->top <= pt.y&&it->bottom >= pt.y) { return *it; } } return rect; }
HCR是本身定义的一个结构体:.net
typedef struct Handle_Correspondence_Region { Handle_Correspondence_Region(int p = 0) { hwd = NULL; }; HWND hwd; long int left; long int right; long int top; long int bottom; long int wide; long int high; bool operator <(const Handle_Correspondence_Region &m)const { return (wide*high) < (m.wide*m.high); } bool operator == (const Handle_Correspondence_Region &eq) const { return ((left == eq.left) && (right == eq.right) && (top == eq.top) && (bottom == eq.bottom)); } }HCR;
到这就已经能根据鼠标位置返回所在区域了,接下来开始绘制就能够啦~
这里本身搞了个坑,自己经过枚举桌面上全部的窗口时,就是按Z-order的顺序,按序存储好了,刚开始不知道,还对枚举的窗口进行了排序和筛选,想着确定是窗口小的在上面,遍历的时候从小到大,结果形成窗口被覆盖,鼠标放在被覆盖的窗口位置时,还能显示。(刚开始想着遍历筛选主要是发现枚举出来的窗口数量比较大,并且存在着重复)。
解决方法:枚举出来的窗口不要进行排序,它本省就是按Z-order的顺序遍历出来的。code
这里再贴一个Z-order讲解的博客
https://blog.csdn.net/henter/article/details/51314475blog