這兩天作的截圖自動識別窗口。最終要求效果:將當前鼠標所在的窗口用顏色框框起來,單擊後選中該區域。
實現步驟:
利用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