レガシ MFC アプリケーションのグリッド コントロールと対話する必要があるテスト自動化プログラムを作成しています。私のプログラムはレガシー アプリに接続し、グリッドからデータを読み取る必要があります。
グリッドを含むウィンドウの HWND はわかっているので、その HWND に関連付けられている CWnd 派生クラス ポインターを見つける必要があります。CWnd::FromHandlePermanent
私の友人のようですがCWnd::FromHandlePermanent
、AFX ウィンドウ マップ ( afxMapHWND()
) はターゲット アプリケーションにのみ含まれているため、アプリケーションの外部から呼び出すことはできません。
したがって、ターゲット アプリにDLL を ( CreateRemoteThread
/を使用して) 挿入し、 を呼び出すようにします。しかし、これでも十分ではありません。私は HWND のスレッドに参加しておらず、間違ったローカル スレッド ストレージを見ているからです。LoadLibrary
FromHandlePermanent
afxMapHWND()
したがって、挿入した DLL では、(一時的に) HWND の WndProc (SetWindowLong
など)をサブクラス化し、 SendMessage
. 今、私は正しいスレッド (ターゲット アプリケーションのメイン スレッド)CWnd::FromHandlePermanent
にいて、HWND で呼び出そうとしましたが、NULL が返されました!! を見るとafxMapHWND()->m_permanentMap->m_nCount
、それが 0 であることがわかります。したがって、 permanentMapにはクラスが添付されていません。これは私には間違っているようです。
では、派生した CWnd ポインターを取得するにはどうすればよいでしょうか??
その他の情報:
- ターゲット アプリケーションが MFC に静的にリンクされている
- これは MFC の別のバージョンで、windowclass は AfxWnd70s です。
- VS2010 を使用して、挿入された DLL をコンパイルしています
- 挿入された DLL は、(VS2010) MFC ライブラリにも静的にリンクします。
挿入された 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;
}