2012-07-19 120 views
3

在ResourceHacker中,打开可执行文件(窗口)时,可以看到与对话框关联的标识符。有没有人有他们来自哪里的想法?我的意思是,我如何在我的C++程序中执行相同的操作以从HWND获取ID?从hWnd获取(资源)ID

顺便说一句,GetWindowLong(HWND,GWL_ID)返回0

由于

+0

找出该HWND的可执行文件,并从中提取资源。咄。 – 2012-07-19 21:35:41

+0

@CatPlusPlus:例如,如果该对话框是在运行时创建的,那么通过调用[CreateDialogIndirect](例如https://msdn.microsoft.com/en-us/library/windows/desktop/ms645436.aspx)?该对话框甚至没有资源ID,因为模板是在内存中创建的。您将活动对象与资源混淆。 – IInspectable 2016-03-08 02:28:12

回答

10

GetWindowLong(hwnd, GWL_ID)返回在对话框的控制的标识符,但是它不能被用于对话本身,因为对话只是没有标识符。

与对话框关联的标识符实际上用于引用资源blob本身,而不是窗口。它们被用来创建对话框(见CreateDialog()

一旦创建对话框有原来的模板或该标识符没有关系。其实,有没有使用该ID,对话是简单地通过其HWND鉴定需要注意的是,你可以使用相同的对话框资源创建多个不同的对话框。

这些标识符由资源编辑器分配(通常)顺序,或者手动你手工创建资源。

要了解更多有关您可以阅读有关CreateDialogIndirect()功能的主题,该功能会创建一个对话框withou t使用资源。

4

这里你可以找到一个很好的答案:“鉴于一盘菜,我该如何恢复原来 菜谱和页码为配方” http://blogs.msdn.com/b/oldnewthing/archive/2005/07/08/436815.aspx

这就像问,通过对食物进行化学分析 ,您可能能够恢复“a”配方,但是 食物本身没有任何内容说“我来自 烹饪的快乐”,第253页。“

所以答案是微软没有办法提供对话框ID。他们可以很容易地将其存储在任何地方以使其可用,但他们没有。

但是仍然有办法做到这一点,虽然它不是防弹的。你可以:

1)通过GetWindowModuleFileName()

2.获取对话框的创建者文件)通过LoadLibraryEx(..., LOAD_LIBRARY_AS_IMAGE_RESOURCE)

3.加载该EXE或DLL)枚举EXE或DLL所有RT_DIALOG资源通过EnumResourceNames()其中对话ID是在名称:ResourceName = MAKEINTRESOURCE(IDD_DIALOG_ID)

4.)通过LoadResource()LockResource()CreateDialogIndirect()但没有示出与ShowWindow()对话框无形创建每个列举的对话框。

5.)通过EnumChildWindows()列举每个对话框中的子控件,并将它们与您的对话框进行比较。

6。)释放所有句柄并销毁对话框。

在Exe/Dll文件中有两个相同的对话框不太可能。但问题是在WM_INITDIALOG程序员可能会消除(销毁)或添加或修改子控件。所以你的搜索算法必须是容错的。这可以通过计算每个对话与资源和对话之间的一致性来实现。您可以计算出有多少个孩子控制ID(GetDlgCtrlID())和班级名称(GetClassName())匹配。 (例如Class =“BUTTON”和ID = 311“)程序员可以很容易地更改控件的文本或移动它,但改变ID不太可能,并且没有多大意义,并且改变了子控件的类甚至是不可能的

正如我所说的:它不是防弹的,但你会发现,有最有可能被用来创建对话框资源的ID

请注意,并非所有的对话都来自一个Microsoft资源 它们可以通过使用自己类型的模板的GUI框架来创建,在这种情况下,您永远不会找到对话ID,因为它根本不存在

+0

正如你所说,这个算法并不完全符合防弹要求。其他可能需要考虑的事情:在运行时创建的控件,以及在运行时删除的控件。除此之外,这是一个相当不错的答案,有一个值得信赖的介绍性链接到旧新事物。绝对值得赞赏。 – IInspectable 2016-03-08 02:23:59