Tr0j4n上次你叫我注入ExtTextOut。我照着做了。
我写个例子打算获取QQ2009聊天记录,采用屏幕取词技术。把鼠标移动到QQ聊天窗口上,按Ctrl键后,获取鼠标下面窗体的句柄,然后大概计算出发送区域的RECT.
接着发送重绘消息给QQ聊天窗体。此时对ExtTextout进行了拦截,按我的理解QQ调用ExtTextOut重绘文字时参数str中应该放的是在聊天窗口中输入的文字.
运行后,正常拦截到ExtTextOut了,但发现str为空,什么也没有。难道重绘的文字不放在str里吗?大家都来看看。窗体初始化时加载 Hook.dll
BOOL CTestDlg::PreTranslateMessage(MSG* pMsg) 
{
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_CONTROL)
{
POINT ptMousePos = {0, 0};
if (GetCursorPos(&ptMousePos))
{
GetWords(ptMousePos);
}
}

return CDialog::PreTranslateMessage(pMsg);
}void CTestDlg::GetWords(POINT &ptMousePos)
{ char szAppClassName[65];
HWND hAppWin;
HWND hChildWnd=NULL;
int  nFlyWinLeft;
int  nFlyWinWidth;
RECT rcAppWin;        Intercept();  //调用Hook.dll中的Intercept()
         hAppWin = ::WindowFromPoint(ptMousePos);
GetClassName(hAppWin, szAppClassName, 64);
if (stricmp(szAppClassName, "TXGuiFoundation") == 0)
{
char strName[101];
::GetWindowText(hAppWin,strName,100);
if(stricmp(strName,"QQ2009")!=0)   //此处对QQ主程序窗口过滤 (此处假设能过滤掉)
{
::GetWindowRect(hAppWin, &rcAppWin);
RECT rectSend;
CWnd *cwdText=CWnd::FromHandle(hAppWin);
cwdText->GetClientRect(&rectSend);
rectSend=此处计算出发送窗口的大概范围。 cwdText->InvalidateRect(&rectSend,true);  //此处我的理解是触发重绘消息后,QQ会调用ExtTextOut来重绘,会被MyExtTextOutW或MyExtTextOutA拦截
} }
}下面是Hook.DLL部分static HWND g_wndDest=NULL;
HHOOK g_hHook = NULL;
HMODULE g_hInst = NULL;
bool g_bIntercepted = false;BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);void Intercept();
void UnIntercept();
void UninstallHook();
BOOL WINAPI MyExtTextOutA
 (
  HDC         hdc,
  INT         x,
  INT         y,
  UINT        flags,
  const RECT* lprect,
  LPCSTR      str,
  UINT        count,
  const INT*  lpDx
 );
 BOOL WINAPI MyExtTextOutW
 (
  HDC         hdc,
  INT         x,
  INT         y,
  UINT        flags,
  const RECT* lprect,
  LPCWSTR     str,
  UINT        count,
  const INT*  lpDx
 );// ---------------------------------------------------------------------------DETOUR_TRAMPOLINE(BOOL WINAPI RealExtTextOutA( HDC         hdc,
INT         x,
INT         y,
UINT        flags,
const RECT* lprect,
LPCSTR     str,
UINT        count,
const INT*  lpDx),
ExtTextOutA);DETOUR_TRAMPOLINE( BOOL WINAPI RealExtTextOutW( HDC         hdc,
INT         x,
INT         y,
UINT        flags,
const RECT* lprect,
LPCWSTR     str,
UINT        count,
const INT*  lpDx),
ExtTextOutW);// ---------------------------------------------------------------------------BOOL WINAPI DllMain(
HINSTANCE hinstDLL,  // handle to DLL module
DWORD fdwReason,     // reason for calling function
LPVOID lpvReserved   // reserved
){
g_hInst = hinstDLL; switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnIntercept();
break;
} return TRUE;
}LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//Intercept();
return CallNextHookEx(g_hHook,nCode,wParam,lParam);
}void InstallHook()
{
if(g_hHook == NULL)
g_hHook = ::SetWindowsHookEx(WH_MOUSE , MouseHookProc ,(HINSTANCE)g_hInst, 0);
}void UninstallHook()
{
if(::UnhookWindowsHookEx( g_hHook ))
g_hHook = NULL;
}BOOL WINAPI MyExtTextOutA(HDC hdc,INT x,INT y,UINT flags,const RECT* lprect,LPCSTR  str,UINT count,const INT*  lpDx)
{
BOOL res = 0;
__try 
{
MessageBoxA(NULL,str,"测试",MB_OK); //str里面什么也没有。郁闷
res = RealExtTextOutA(hdc,x,y,flags,lprect,str,count,lpDx);

__finally 
{
};
return res;
}BOOL WINAPI MyExtTextOutW(HDC hdc,INT x,INT y,UINT flags,const RECT* lprect,LPCWSTR  str,UINT count,const INT*  lpDx)
{
BOOL res = 0;
__try 
{
//MessageBoxW(NULL,str,L"测试",MB_OK);
res=RealExtTextOutW(hdc,x,y,flags,lprect,str,count,lpDx);

__finally 
{
};
return res;
}void Intercept()
{
DetourFunctionWithTrampoline((PBYTE)RealExtTextOutA, (PBYTE)MyExtTextOutA);
DetourFunctionWithTrampoline((PBYTE)RealExtTextOutW, (PBYTE)MyExtTextOutW);
}void UnIntercept()
{
DetourRemove( (PBYTE)RealExtTextOutA,(PBYTE)MyExtTextOutA);
DetourRemove( (PBYTE)RealExtTextOutW,(PBYTE)MyExtTextOutW);
}