首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

怎样得到Dialog的resource ID ?解决方法

2012-02-21 
怎样得到Dialog的resource ID ?这个问题摸索了很久还没有很好的解决。大问题是这样的,要做一个dialogkiller

怎样得到Dialog的resource ID ?
这个问题摸索了很久还没有很好的解决。

大问题是这样的,要做一个dialog   killer,   就是监视我们的软件中弹出的对话框,有些对话框需要点适当的按钮关掉。

我的实现是这样的,设定一个全局钩子监视所有的WM_INITDIALOG消息,如果有对话框窗口创建,则:
1:比较对话框标题,
2:比较对话框内static空间的text
3:搜索对应的button,如果是我们要的那个,则发送消息,模拟点击鼠标

这套机制实现得很好。

现在问题是,如果根据dialog的文字来识别对话框,涉及到多语言的问题,需要提供一个配置文件(txt)以提供dialog的相关信息,我们共支持13种语言,如果每种语言提供一个配置文件,很麻烦,而且配置文件容易输入错误。

因此,老板建议通过resource   id来识别对话框,这样这套识别机制和语言种类无关。

但是,现在问题的关键是,怎样在运行期间得到对话框的resource   id,我试过Getwindowlong这个函数,得到的对话框ID全为0,单能正确得到自定义空间的resource   id

大家有什么建议么?


[解决办法]
获取本进程内窗口的窗口过程确实很简单,直接调用GetWindowLong(hWnd,GWL_WNDPROC)就可以了(注意,根据窗口是否是Unicode的,你要判断是调用GetWindowLongA,还是GetWindowLongW,可以用IsWindowUnicode来判断), 但是GetWindowLong这个函数内部会检查调用进程和该窗口句柄是否属于同一进程,如果不是,就简单的返回0了
[解决办法]
调用 GetWindowThreadProcessId ,得到该窗口所属进程的Id,存放在 dwProcess中;
调用 OpenProcess,打开该进程(如果打开失败,可能是权限不够,需要调用AdjustTokenPrivileges提升一下当前进程的权限),得到一个该进程的句柄,存放在hProcess中 ;
调用 IsWindowUnicode,判断下一步应该调用 GetWindowLongA 还是 GetWindowLongW函数;
调用 VirtualAllocEx,在目标进程中分配一些内存,供我们写入线程函数使用。函数返回的就是分配的内存的起始地址,就是我们的线程函数的起始地址,假设叫fnStartAddr;根据我们上边分析的结果,需要33个字节,另外,线程函数最后要有一个 ret指令,占用一个字节,共需34个字节;
把以上分析的结果写入一个临时的缓冲区里;
调用 WriteProcessMemory,把刚才的结果写入远程进程 fnStartAddr的地址处 ;
调用 CreateRemoteThread,指定线程函数地址为 fnStartAddr;
进行一个小的消息循环,等待我们的返回结果; MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
if(msg.message == uMsgSendBack)
{
procRet = msg.lParam;
break;
}
}

进行一些善后工作,关闭打开的线程句柄、进程句柄,释放分配的远程内存;
[解决办法]
1:对话框的创建你们都是可以控制的嘛。所以在你们的工程中,在WM_INITDIALOG消息响应函数中
SetWindowLong( hWnd,DWL_USER,nDialogId );
2: 然后在你的钩子函数中
UINT nDialogId = GetWindowLong( hWnd,DWL_USER );


[解决办法]
先获取CWnd对象,HWND句柄,然后

使用GetClassName
The GetClassName function retrieves the name of the class to which the specified window belongs.

int GetClassName(
HWND hWnd, // handle of window
LPTSTR lpClassName, // address of buffer for class name
int nMaxCount // size of buffer, in characters
);

对话框的类名字是“#32770”,确定该对象是对话框后再用GetDlgCtrlID

The GetDlgCtrlID function returns the identifier of the specified control.

int GetDlgCtrlID(
HWND hwndCtl // handle of control
);

即可得到对话框的ID

热点排行