不过下载附带的源代码,编译无法成功,报告“RealChildWindowFromPoint()”未定义错误。找到两个解决方法如下,
gobr的文章(http://proxy3.zju88.net/agent/thread.do?id=VC-447ef74f-eaaf138a67271197a124c259cc530eee&page=0&bd=VC&bp=25&m=2)中提供了第3种方法,利用WM_NCHITTEST消息返回值,效果的确和RealChildWindowFromPoint 相同。
但还是有一个小问题,利用WM_NCHITTEST消息返回值获得窗口时,将鼠标拖动到文件管理器标题栏,这时目录树视图窗口被捕获,错误在于发送消息的SendMessage函数,返回的值误导了下面的判断条件,因为鼠标在标题栏,所以任何窗口中的子窗口都不可能成功捕获HITTEST坐标,即总应返回0。实际上返回值可能是 0x01,0x0B等。
uHitTest = SendMessage(hChildWnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x,pt.y));
改用 DefWindowProc 函数则可以解决这个问题
uHitTest = ::DefWindowProc(hChildWnd,WM_NCHITTEST,0, MAKELPARAM(pt.x,pt.y));
为了获得和一样的效果,修改gobr的函数如下
typedef HWND (WINAPI *REALCHILDWINDOWFROMPOINT) (HWND hwndParent, POINT ptParentClientCoords); HWND RealWindowFromPoint(HWND hParentWnd, POINT pt) { HWND hChildWnd = NULL; REALCHILDWINDOWFROMPOINT fnRealWndFromPoint; if ( !hParentWnd ) { return NULL; } if ( (hUser32 = ::LoadLibrary("User32.dll"))&& (fnRealWndFromPoint = (REALCHILDWINDOWFROMPOINT)GetProcAddress(hUser32, "RealChildWindowFromPoint")) ) { hChildWnd = fnRealWndFromPoint(hParentWnd, pt); } // RealChildWindowFromPoint doesn't exist, might slower but can work else { UINT uHitTest; hChildWnd = GetWindow(hParentWnd,GW_CHILD); // Iterator through the child windows while ( hChildWnd ) { // test whether pt in the child window ? // uHitTest = SendMessage(hChildWnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x,pt.y)); uHitTest = ::DefWindowProc(hChildWnd,WM_NCHITTEST,0, MAKELPARAM(pt.x,pt.y)); if ((int)uHitTest > 0 ) { break; // find that window !! break loop } // look for next child window hChildWnd = GetNextWindow(hChildWnd, GW_HWNDNEXT); } if( NULL == hChildWnd ) { hChildWnd = hParentWnd; // if no window matched, will return hParentWnd; } } if(hUser32) { ::FreeLibrary(hUser32); } return hChildWnd; }