https://blog.csdn.net/jiangqin115/article/details/78368767
テーマは、以下が自動的にマウスの位置に応じて、ウィンドウの輪郭を描くことができます新しいウィンドウQQ自動認識機能の追加。今日誰かがのは、この機能の実装原理を説明しましょう、フォーラムでこの質問をしました。
私たちは、QQなどのソフトウェアのスクリーンショットのほとんどがそうしている、実際には、新しいフルスクリーンウィンドウを作成した際に、ソフトウェアのスクリーンショット、スクリーンショットの基本原則を理解して、上記の現在のデスクトップのスクリーンショットを描画する必要があります。ウィンドウを下げるに従って、マウスの位置を取得し、いくつかの同様のAPIがあります(WindowFromPoint、ChildWindowFromPoint、ChildWindowFromPointEx、RealChildWindowFromPoint)を使用することができます。
ここでは、トップをカバーするフルスクリーンウィンドウがある知っているので、我々は最初のフルスクリーンウィンドウのスクリーンショットを撮るようにしてください、マウスの位置を取得するために窓を通って、ChildWindowFromPointExに焦点を当て、私たちは窓の外をフィルタリングする必要があるが、唯一ChildWindowFromPointExこのAPI窓フィルタリングがあります。
HWND ChildWindowFromPointEx(
HWND hwndParent、点PT、UINT uFlags)。
パラメーター
hwndParent
[中]親ウィンドウへのハンドル。
PT
[IN]はチェックされる点の(hwndParentに対する)クライアント座標を定義するPOINT構造体を指定します。
uFlags
子ウィンドウをスキップするかを指定し、[中]。このパラメータには、次のいずれかの値以上とすることができます。
CWP_ALLは、
任意の子ウィンドウをスキップしません
CWP_SKIPINVISIBLE
目に見えない子ウィンドウスキップ
CWP_SKIPDISABLED
無効の子ウィンドウスキップ
CWP_SKIPTRANSPARENT
透明子ウィンドウをスキップします
あなたは目に見えないとレイヤードウィンドウをフィルタリングして、再帰を通じてAPIを呼び出すことができるようにあなたが、することができます|(CWP_SKIPTRANSPARENT hWndDesktop、ptCursor、CWP_SKIPINVISIBLE)だから我々は、WS_EX_LAYEREDプロパティでそのQQフルスクリーンウィンドウを信じる理由、ChildWindowFromPointExを呼び出すことにより、QQを持っています子ウィンドウの中に入ります。
あなたが自分でレイヤードウィンドウを構築し、その後、QQのスクリーンショットを使用することができますどのように、私たちの推測を検証するには、そのQQはウィンドウに認識されていません見ることができます。
加えて、我々はQQのスクリーンショットの後に、Windowsキーは、タスクバーを有効にするには起動し、ショットに含まれ、ウィンドウを最小化したり閉じたりするタスクバーを変更し、スクリーンショットがない識別QQを見つける続けることができます。また、これはChildWindowFromPointExの下の窓を介して取得するためのリアルタイムキャプチャQQを示しています。これはバグQQのスクリーンショットと考えることができます。
多くは背後その後、識別するための情報を格納している、そうでも変更以下のウィンドウの後ろにこれらの問題は、私は、ショットの開始時に、彼らが保存されるべきだと思うし、デスクトップ上のすべてのウィンドウの階層関係エリアソフトウェアをキャプチャしませんでした認識は影響を受けません。
また、ソフトウェアの一部のスクリーンショットは、このようなツールバーコントロールの各項目などの要素、のウィンドウサイズよりも小さいを認識することができ、それらの使用は、標準のコントロールは、一般的にインタフェースをサポートし、MSAA(マイクロソフトアクティブなユーザー補助)する必要があります。
一部の人々は、ウィンドウを識別するための方法を列挙することによって、コードを見ることに興味がある、ここに私のコードは次のとおりです。
クラスCSCWinFilter
{
パブリック:
静的BOOL IsFilterWindow(HWND hWndを)
{
_ASSERTE(!hWndは= NULL);
DWORD dwProcessID = GetCurrentProcessId()。
IF(!= NULLのhWnd && IsWindow(のhWnd))
{
DWORD dwWinProcessId(0)。
GetWindowThreadProcessId(hWndを、&dwWinProcessId)。
(dwProcessID == dwWinProcessId)場合は
{
TRUEを返します。
}
}
FALSEを返します。
}
静的DWORD GetIncludeStyle()
{
WS_VISIBLEを返します。
}
静的DWORD GetExcludeStyleEx()
{
WS_EX_TRANSPARENTを返します。
}
静的BOOL IsTargetPopupWindow()
{
FALSEを返します。
}
}。
クラスCSCWinInfo
{
パブリック:
HWND m_hWndを。
CRect m_rtWin; //ウィンドウの矩形の
INT m_nLevel。// 1 -ウインドウをポップアップ。2N -子ウィンドウ
};
//ポップアップ勝利1(レベル1)..第Zオーダー
// child11(レベル2)
// child12(レベル2)
// chilld121(レベル3)
// chilld122(レベル3)
//
// child3(レベル2)
// WIN2がポップアップ
// child21(レベル2)
// child21(レベル2)
//。
//。
// WINNをポップアップ表示。最後のZオーダー
テンプレート<型名CWinFilterTraits = CSCWinFilter>
クラスCSCWinSpy:公共CHYSingleton <CSCWinSpy>
{
パブリック:
BOOL SnapshotAllWinRect()
{
clearDataメソッド()。
//キャッシュ現在のウィンドウのZオーダー場合、この関数呼び出し
EnumWindows(EnumWindowsSnapshotProc、1)。
TRUEを返します。
}
//デスクトップの現在のZ順序から取得
HWND GetHWNDByPoint(CPointのPT)
{
m_hWndTarget = NULL;
EnumWindows(EnumWindowsRealTimeProc、MAKELPARAM(pt.x、pt.y))。
m_hWndTargetを返します。
}
CRect GetWinRectByPoint(CPoint ptHit、BOOL bGetInRealTime = FALSE)
{
CRect rtRect(0、0、0、0);
(bGetInRealTime)場合//現在のZ順序から取得
{
HWND hWndTarget = GetHWNDByPoint(ptHit)。
(hWndTarget!= NULL)の場合
{
GetWindowRect(hWndTarget、&rtRect)。
}
}
他//スナップショットのキャッシュから取得
{
GetRectByPointFromSnapshot(ptHit、rtRect)。
}
rtRectを返します。
}
保護:
静的BOOL CALLBACK EnumWindowsRealTimeProc(HWNDのHWND、LPARAM lParamに)
{
TRUEを返す場合、(PtInWinRect(HWND、CPoint(GET_X_LPARAM(lParamには)、GET_Y_LPARAM(lParamに)))!)
(ShouldWinBeFiltered(HWND))場合にtrueを返します。
m_hWndTarget = HWND;
もし(CWinFilterTraits :: IsTargetPopupWindow())戻りFALSE; //これは、終了検索対象ウィンドウです
EnumChildWindows(HWND、EnumChildRealTimeProc、lParamに)。
FALSEを返します。
}
静的BOOL CALLBACK EnumChildRealTimeProc(HWNDのHWND、LPARAM lParamに)
{
場合(PtInWinRect(HWND、CPoint(GET_X_LPARAM(lParamには)、GET_Y_LPARAM(lParamに)))!)TRUEを返します。
(ShouldWinBeFiltered(HWND))場合にtrueを返します。
m_hWndTarget = HWND;
EnumChildWindows(HWND、EnumChildRealTimeProc、lParamに)。
FALSEを返します。
}
保護:
BOOL CALLBACK EnumWindowsSnapshotProc(HWNDのHWND、LPARAM lParamに)静的
{
INT nLevel =たlParam。
(ShouldWinBeFiltered(HWND))場合にtrueを返します。
SaveSnapshotWindow(HWND、nLevel)。
もし(CWinFilterTraits :: IsTargetPopupWindow()!)
{
++ nLevel。
EnumChildWindows(HWND、EnumChildSnapshotProc、nLevel)。
}
TRUEを返します。
}
静的BOOL CALLBACK EnumChildSnapshotProc(HWNDのHWND、LPARAM lParamに)
{
INT nLevel =たlParam。
(ShouldWinBeFiltered(HWND))場合にtrueを返します。
SaveSnapshotWindow(HWND、nLevel)。
++ nLevel;
EnumChildWindows(HWND、EnumChildSnapshotProc、nLevel)。
TRUEを返します。
}
保護:
静的BOOL PtInWinRect(HWND hWndは、CPointのPT)
{
CRect rtWin(0、0、0、0);
GetWindowRect(hWndを、&rtWin)。
PtInRect(&rtWin、PT)を返します。
}
静的BOOL ShouldWinBeFiltered(HWNDのhWnd)
{
(CWinFilterTraits :: IsFilterWindow(のhWnd))がTRUEを返す場合、
DWORD dwStyle = GetWindowLong(hWndは、GWL_STYLE)。
DWORD dwStyleMust = CWinFilterTraits :: GetIncludeStyle()。
((dwStyle&dwStyleMust)= dwStyleMustが!)場合はtrueを返します。
DWORD dwStyleEx = GetWindowLong(hWndは、GWL_EXSTYLE)。
DWORD dwStyleMustNot = CWinFilterTraits :: GetExcludeStyleEx()。
((dwStyleMustNot&dwStyleEx)!= 0)場合はtrueを返します。
FALSEを返します。
}
レベルが最大である第一のウィンドウを//検索します
静的BOOL GetRectByPointFromSnapshot(CPoint ptHit、CRect&rtRet)
{
int型nCount = m_arSnapshot.size()。
_ASSERTE(nCount> 0)。
CSCWinInfo * pInfoは= NULL;
CSCWinInfo *をpTarget = NULL;
以下のために(0 = I int型、iはnCountを<; ++ I)
{
pInfoは= m_arSnapshot [I]。
_ASSERTE(pInfoは= NULL!)。
//ターゲットウィンドウが発見され
、//とレベルは、増加していない
、それはその兄弟や親ウィンドウをチェックしている//終了検索
(をpTarget = NULL!場合
&& pInfo-> m_nLevel <= pTarget-> m_nLevel)
{
破ります。
}
IF(PtInRect(&pInfo-> m_rtWin、ptHit))
{
IF(をpTarget == NULL)
{
をpTarget = pInfoは。
}
他
{
IF(pInfo-> m_nLevel> pTarget-> m_nLevel)
{
をpTarget = pInfoは。
}
}
}
}
もし(!をpTarget = NULL)
{
_DEBUGの#ifdef
場合(!をpTarget = NULL)
{
HWNDのhWnd = pTarget-> m_hWndを。
TCHAR szText [128] = {0}。
_sntprintf(szText、127、_T( "GetRectByPointFromSnapshot:PT(%のD、%d)は、のhWnd(%Xの)")、
ptHit.x、ptHit.y、(UINT)(pInfo-> m_hWndを));
OutputDebugString(szText)。
}
#endifの
rtRet.CopyRect(&pTarget-> m_rtWin);
TRUEを返します。
}
FALSEを返します。
}
静的ボイドSaveSnapshotWindow(HWND hWndは、INT nLevel)
{
_ASSERTE(hWndは= NULL && IsWindow(のhWnd)!)。
CRect rtWin(0、0、0、0);
GetWindowRect(hWndを、&rtWin)。
(rtWin.IsRectEmpty())の復帰であれば、
CSCWinInfo * pInfoは=新しいCSCWinInfo。
(pInfoは== NULL)を返すと、
pInfo-> m_hWndを=のhWnd;
pInfo-> m_nLevel = nLevel。
pInfo-> m_rtWin = rtWin。
m_arSnapshot.push_back(pInfoは)。
}
静的VOID clearDataメソッド()
{
INT nCount = m_arSnapshot.size()。
(I 0 = int型、iがnCountを<; ++ i)のための
{
[I] m_arSnapshotを削除します。
}
m_arSnapshot.clear()。
}
保護:
友人クラスCHYSingleton <CSCWinSpy>。
CSCWinSpy(){NULL。}
〜CSCWinSpy(){clearDataメソッド()。}
静的HWND m_hWndTarget。
静的のstd ::ベクトル<CSCWinInfo *> m_arSnapshot。
}。
テンプレート<型名T> HWND CSCWinSpy <T> :: m_hWndTarget = NULL;
テンプレート<型名T>のstd ::ベクトル<CSCWinInfo *> CSCWinSpy <T> :: m_arSnapshot。
ショットが起動したときに、デスクトップウィンドウのすべてのレベルを保存するような使用:
CSCWinSpy <CSCWinFilter> ::でGetInstance() - > SnapshotAllWinRect();
その後、場所に、このようにウィンドウの上部を照会することができます:
CRect rtSelect = CSCWinSpy <CSCWinFilter> ::でGetInstance() - > GetWinRectByPoint(PT、FALSE)。
http://www.cppblog.com/weiym/archive/2012/05/06/173845.html