CoverCollector专门用作遮盖区域收集
整体耗时大约100us~300us左右
IsWindowVisible为true的时候,窗口依旧可能被遮挡,依旧不需要显示数据
使用此函数,可以避免UI线程做不必要的界面刷新,降低CPU使用频率
bool IsWindowCoveredTotally(HWND hWnd)
{
class CoverCollector{
RECT m_rect;
HRGN m_region[2];
HRGN m_exclude;
int m_select;
public:
CoverCollector(RECT rt) :m_rect(rt)
{
m_select = 0;
m_region[0] = CreateRectRgnIndirect(&m_rect);
m_exclude = CreateRectRgn(0, 0, 1, 1);
m_region[1] = CreateRectRgn(0, 0, 1, 1);
}
~CoverCollector()
{
DeleteObject(m_region[0]);
DeleteObject(m_region[1]);
DeleteObject(m_exclude);
}
bool AddCoverAndTestEmpty(const RECT& cover)
{
if (cover.right <= m_rect.left || cover.left >= m_rect.right ||
cover.bottom <= m_rect.top || cover.top >= m_rect.bottom)
return false;
RECT box;
::SetRectEmpty(&box);
GetRgnBox(m_region, &box);
if (cover.right <= box.left || cover.left >= box.right ||
cover.bottom <= box.top || cover.top >= box.bottom)
return false;
SetRectRgn(m_exclude, cover.left, cover.top, cover.right, cover.bottom);
int target = m_select == 0 ? 1 : 0;
int ret = CombineRgn(m_region[target], m_region[m_select], m_exclude, RGN_DIFF);
m_select = target;
return (ret == NULLREGION || ret == ERROR )? true : false;
}
};
RECT rcTarget, rcWnd;
GetWindowRect(hWnd, &rcTarget);
CoverCollector cover(rcTarget);
bool isChild = (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD));
if (GetDesktopWindow() == hWnd)
hWnd = GetWindow(GetTopWindow(hWnd), GW_HWNDLAST);
do
{
HWND hCurWnd = hWnd;
while (NULL != (hWnd = GetNextWindow(hWnd, GW_HWNDPREV)))
{
if (!IsWindowVisible(hWnd))
continue;
GetWindowRect(hWnd, &rcWnd);
if (cover.AddCoverAndTestEmpty(rcWnd))
return true;
}
if (isChild)
{
hWnd = GetParent(hCurWnd);
isChild = hWnd ? (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)) : false;
}
else
{
break;
}
} while (true);
return false;
}