我正在编写一个测试自动化程序,它必须与传统MFC应用程序中的网格控件进行交互。我的程序必须连接到遗留应用程序,并从网格中读取数据。
我知道包含网格的窗口的HWND,所以现在我需要找到与该HWND关联的CWnd派生类指针。 CWnd::FromHandlePermanent
似乎是我的朋友,但是,我知道,您无法从应用程序外部调用CWnd::FromHandlePermanent
,因为AFX窗口地图(afxMapHWND()
)仅包含在目标应用程序中。
因此,我将DLL(使用CreateRemoteThread
/ LoadLibrary
)注入目标应用程序,然后将其调用FromHandlePermanent
。但即使这样也不够好,因为我不在HWND的线程中,afxMapHWND()
正在查看错误的本地线程存储。
因此,在我注入的DLL中,我(暂时)继承了HWND的WndProc(SetWindowLong
等),然后调用SendMessage
。现在我在正确的线程(目标应用程序的主线程)中,我尝试用我的HWND调用CWnd::FromHandlePermanent
,但它返回NULL !!
如果我查看afxMapHWND()->m_permanentMap->m_nCount
,我们会看到它是0.所以在permanentMap中有 NO 附加的类,这对我来说似乎不对。
那么如何获得派生的CWnd指针?
其他一些信息:
以下是注入的DLL中的代码:
// this is how we pass the HWND to the target DLL
// (this shared segment is also loaded in calling app)
#pragma data_seg (".shared")
__declspec(dllexport) HWND g_hWnd = 0;
#pragma data_seg ()
#pragma comment(linker,"/SECTION:.shared,RWS")
BEGIN_MESSAGE_MAP(CLibSpyMFCDllApp, CWinApp)
END_MESSAGE_MAP()
CLibSpyMFCDllApp::CLibSpyMFCDllApp()
{
}
CLibSpyMFCDllApp theApp;
extern CHandleMap* PASCAL afxMapHWND(BOOL bCreate = FALSE);
UINT g_WM_GETGRIDDATA = 0;
WNDPROC wpOrigEditProc;
LRESULT CALLBACK SpySubProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (g_WM_GETGRIDDATA != 0 && message == g_WM_GETGRIDDATA) {
CWnd * target1 = CWnd::FromHandlePermanent(hWnd);
// fails - target1 is null
return 0;
}
return CallWindowProc((WNDPROC ) wpOrigEditProc, hWnd, message, wParam, lParam);
}
BOOL CLibSpyMFCDllApp::InitInstance()
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CWinApp::InitInstance();
if (g_hWnd) {
g_WM_GETGRIDDATA = RegisterWindowMessage(L"GetGridData");
wpOrigEditProc = (WNDPROC) SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG) SpySubProc);
::SendMessage(g_hWnd, g_WM_GETGRIDDATA, 0, 0);
SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG) wpOrigEditProc);
}
return TRUE;
}