关于子类化控件

liaomingdong 2009-02-27 03:51:53
问题是这样,我做了个钩子程序调用Setwindowlongptr来子类化一个窗口上listview控件,钩子没有任务问题,setwindowlongptr也能调用有返回,但被我hook的那个窗口却出了问题,老是弹出0xXXXXX内存不能read,然后就崩掉了。调试许久找不出原因,后来我尝试了一下用我的dll去子类化别的窗口,结果却正确了,我用spy++,查看了一下两个窗口,发现失败的那个窗口,原先是已经被子类化了的。而成功被我子类化的那个窗口则没有,除此两者没有太大差别。不知是不是因为已经子类化过的窗口就不能再被子类了?因为我的程序去子类化别的窗口的时候可都是成功的。就子类化listview的时候有问题。源码我回去后再贴出来给大家看看,希望可以得到高价指示!
...全文
219 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
liaomingdong 2009-02-28
  • 打赏
  • 举报
回复
终于发现原因了,居然不是我的dll的问题,昏啊。
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{

SendMessage(HwndOfSeverForm,WM_USER+87,Msg,lParam);

//return DefWindowProc(hWnd,Msg,wParam,lParam);

return CallWindowProc(OldWndProc,hWnd, Msg, wParam, lParam);

}


。。。
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {

static BOOL bFirstTime = TRUE;

if (bFirstTime) {
// The DLL just got injected.
bFirstTime = FALSE;


// LRESULT (CALLBACK* )(HWND, UINT, WPARAM, LPARAM)OldWndProc=(LRESULT (CALLBACK* )(HWND, UINT, WPARAM, LPARAM))GetWindowLong(g_HandleOfAlarmLV,GWL_WNDPROC);

OldWndProc=(WNDPROC)SetWindowLongPtr(g_HandleOfAlarmLV,GWLP_WNDPROC,(LONG_PTR)MyWndProc);
if(OldWndProc!=NULL)
MessageBox(NULL, TEXT("DLL已成功改变预警系统窗口消息。"), TEXT("信息"), MB_ICONINFORMATION );

// Uncomment the line below to invoke the debugger
// on the process that just got the injected DLL.
// ForceDebugBreak();

// Create the DIPS Server window to handle the client request.

// Tell the DIPS application that the server is up
// and ready to handle requests.
}

return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}






BOOL WINAPI SetMyHook(DWORD ThreadId,HWND handleOfAlarmLV,HWND handleOfSever)
{
BOOL OK=FALSE;
if(ThreadId!=0)
{
//chASSERT(g_hHook==NULL);
if(g_hHook!=NULL)
return false;

HwndOfSeverForm=handleOfSever;
g_HandleOfAlarmLV=handleOfAlarmLV;

g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,g_HandleOfDll,ThreadId);

OK=(g_hHook!=NULL);
if(OK)
{
OK=PostThreadMessage(ThreadId,WM_NULL,0,0);
}
}
else
{
if(g_hHook==NULL)return false;
OK=UnhookWindowsHookEx(g_hHook);
g_hHook=NULL;
}
return OK;
}



我在测试该dll的时候用的时候win32控制台项目,用两个EnumChildWindows(NULL,EnumChildProc,NULL)来查找目标窗口的句柄,因为窗口标题是变化的,而类名又是#32770 (对话框),这个样子根本没法用findwindow来找,只能enumchildwindows来一个个搜,但enumchildwindows中再用enumchildwindows,最后才sethook这个样子,还没等开始hook主线程就已经结束了,我当时只好createthread来另开线程,并用waitforsingleobject来等待,这个样子之后就能sethook了,逐步调试来做就很成功,能够子类化目标窗口,但若不设断点直接运行就会出问题,我反复调试觉得好像是线程返回的时候有些东西没处理好,可惜到现在也没发现是什么问题。只知道如若直接把目标窗口的句柄(及线程ID)传给我的钩子函数,一切就能正常。很奇怪!

如下为测试项目代码:
BOOL CALLBACK EnumChildProc2(HWND hwnd, LPARAM lParam )
{


if (!hwnd)
{
return 0;
}

WCHAR str[14];
GetClassName(hwnd,str,14);

WCHAR str2[14]=TEXT("SysListView32");

int i;

for(i=0;i<14;i++)
{
if(str[i]!=str2[i])
break;
}

if(i!=14)
return true;

WCHAR str3[6]=TEXT("List2");
GetWindowText(hwnd,str,6);



for(i=0;i<5;i++)
{
if(str[i]!=str3[i])
break;
}

if(i!=5)
return true;

HwndOfLV=hwnd;


HINSTANCE Hinst=LoadLibrary(TEXT("HookMsg.dll"));
SetHook=(BOOL (WINAPI * )(DWORD ,HWND,HWND ))GetProcAddress(Hinst,"SetMyHook");


BOOL k=SetHook(GetWindowThreadProcessId(hwnd,NULL),hwnd,HwndOfSeverForm);
return false;
}



BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam )
{

if (!hwnd)
{
return false;
}

WCHAR str[6];;

GetWindowText(hwnd,str, 6);

int i;


WCHAR str2[3]=TEXT("预警");

for(i=0;i<2;i++)
{
if(str2[i]!=str[i])
break;
}
if(i==2)
{
EnumChildWindows(hwnd,EnumChildProc2,NULL);
return false;
}
return true;
}




DWORD WINAPI GetWinHwnd (PVOID pvParam)
{



HwndOfSeverForm=FindWindow(TEXT("WindowsForms10.Window.8.app.0.378734a"),TEXT("服务器主端"));

if(HwndOfSeverForm==NULL)
{
MessageBox(NULL,TEXT("找不到SEVER!"),TEXT("注意"),MB_ICONINFORMATION);
return 0;
}


EnumChildWindows(NULL,EnumChildProc,NULL);

return 0;

}



int _tmain(int argc, _TCHAR* argv[])
{
//HwndOfSeverForm=FindWindow(TEXT("WindowsForms10.Window.8.app.0.378734a"),TEXT("服务器主端"));
HANDLE Handle=CreateThread(NULL,0,GetWinHwnd,NULL,0,NULL);
WaitForSingleObject(Handle,INFINITE);
//if(HwndOfLV==NULL)
// {
//MessageBox(NULL,TEXT("找不到预警窗口!"),TEXT("注意"),MB_ICONINFORMATION);
// return 0;
//}

//BOOL ok=InjectLib(GetWindowThreadProcessId(hwnd,NULL),TEXT("HookMsg.dll"));

/////////////////
//
/// 注意线程的操作即可,dll已无问题!!!!!!!!!!
///
/////////////////////////



while(1)
{}
return 0;

}
liaomingdong 2009-02-27
  • 打赏
  • 举报
回复
用了,且旧的地址还是通过setwindowlong的返回值得到,但每次都崩。。。
yc_8301 2009-02-27
  • 打赏
  • 举报
回复
另,在子类化后是否使用了
CallWindowProc
进行默认处理。。
yc_8301 2009-02-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 akirya 的回复:]
子类化只是替换消息循环,应该可以多次被子类化的呀.
[/Quote]
顶。。
即使是MFC对象中使用的SubclassWindow 最后调用的也是SetWindowLong
  • 打赏
  • 举报
回复
子类化只是替换消息循环,应该可以多次被子类化的呀.

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧