我觉得我这两个窗口要处理的消息非常简单,同样也想做点与众不同。于是我设计了这样的方案,方案是融合了方案1和方案2的优点:
SetWindowsHookEx勾住被注入进程的消息,同时设置Hook类型为WH_CALLWNDPROCRET。
[cpp]
VOID HookWindowsFn()
{
do {
g_hhook = SetWindowsHookEx( WH_CALLWNDPROCRET, CallWndRetProc, NULL, GetCurrentThreadId() );
if ( NULL == g_hhook ) {
_ASSERT(FALSE);
}
InitializeCriticalSection( &g_cs );
} while (0);
}
这样我们将在原程序处理完消息后进行消息处理。
[cpp]
LRESULT CALLBACK CallWndRetProc( __in int nCode, __in WPARAM wParam, __in LPARAM lParam )
{
if ( NULL != lParam ) {
LPCWPRETSTRUCT lptagCWPRETSTRUCT = (LPCWPRETSTRUCT)lParam;
DealMsg( lptagCWPRETSTRUCT->hwnd, lptagCWPRETSTRUCT->message, lptagCWPRETSTRUCT->wParam, lptagCWPRETSTRUCT->lParam );
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
当我们收到消息时,我们要判断是否是我们关心的消息,这样将减少我们处理消息的线程的工作量。
[cpp]
BOOL IsNeedDealMsg( UINT uMsg )
{
return ( IsNeedShowMsg( uMsg )
|| ( WM_DESTROY == uMsg )
|| ( WM_CLOSE == uMsg ) );
}
BOOL IsNeedShowMsg( UINT uMsg )
{
return ( ( WM_SHOWWINDOW == uMsg )
|| ( WM_MOVE == uMsg )
|| ( WM_MOVING == uMsg )
|| ( WM_SIZE == uMsg )
|| ( WM_WINDOWPOSCHANGED == uMsg )
);
}
[cpp]
VOID DealMsg( HWND hAttachedWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if ( FALSE == IsNeedDealMsg( uMsg ) ) {
return;
}
其次判断该窗口是否为我们自己创建的“吸附”窗口。如果是我们的“吸附”窗口,我们将不会做任何处理。
[cpp]
VOID DealMsg( HWND hAttachedWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if ( IsHelperWindow( hAttachedWnd ) ) {
return;
}
[cpp] view plaincopy
BOOL IsHelperWindow( HWND hwnd )
{
WCHAR wszClassNameBuffer[MAX_PATH] = {0};
int nClassNameLength = GetClassName( hwnd , wszClassNameBuffer, MAX_PATH - 1 );
if ( 0 != nClassNameLength ) {
std::wstring wszClassName = wszClassNameBuffer;
if ( 0 == wcscmp( wszClassNameBuffer, TITILEWINDOWCLASS ) ||
0 == wcscmp( wszClassNameBuffer, OUTSIDEWINDOWCLASS ) ) {
return TRUE; // 通过类名判断
}
}
return FALSE;
}
然后我们需要根据消息类型,对窗口句柄做个判断。因为如果我们“宿主”窗口处理完WM_DESTROY后,我们再将不能对其调用GetWindowLong以获取其样式。于是对WM_DESTORY消息,我们只是判断其是否为顶层窗口。如果不是该消息,我们将判断该窗口是否为顶层窗口,且其窗口样式包含WS_SYSMENU(我试验了下,我所遇到的我认为该处理的窗口都有该属性,这个属于经验之谈,不一定准确)。
[cpp]
if ( WM_DESTROY != uMsg ) {
if ( FALSE == IsValibleWindow( hAttachedWnd ) ) {
return;
}
}
else {
if ( FALSE == IsBaseWindow(hAttachedWnd) ) {
return;
}
}
if ( FALSE == IsNeedDealMsg( uMsg ) ) {
return;
}
[cpp]
BOOL IsValibleWindow( HWND hWnd )
{
if ( FALSE == IsBaseWindow( hWnd ) )
{
return FALSE;
}
DWORD dwStyle = ::GetWindowLong( hWnd, GWL_STYLE );
if ( !( WS_SYSMENU & dwStyle ) ) {
return FALSE;
}
return TRUE;
}
BOOL IsTopWindow( HWND hwnd )
{
BOOL bTop = FALSE;
do {
HWND hParentHwnd = NULL;
HWND hParenthwnd = GetParent( hwnd );
if ( NULL == hParenthwnd ){
bTop = TRUE;
}
} while (0);
return bTop;
}
BOOL IsBaseWindow( HWND hWnd )
{
if ( FALSE == ::IsWindow(hWnd)
|| FALSE == IsTopWindow(hWnd) )
{
return FAL