截圖時窗口自動識別

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

相關文章
相關標籤/搜索