Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the (resource) ID from hWnd

Tags:

c++

winapi

In ResourceHacker, when you open an executable (windows), you can see identifiers associated with dialogs. Does anyone have an idea from where they come? I mean, how can I do the same in my C++ program to get the ID from a HWND?

BTW, GetWindowLong(hwnd, GWL_ID) returns 0.

Thanks

like image 498
Steven Van Ingelgem Avatar asked Jul 19 '12 21:07

Steven Van Ingelgem


2 Answers

The GetWindowLong(hwnd, GWL_ID) returns the identifier of a control in a dialog, but it cannot be used for the dialog itself, because dialogs simply don't have identifiers.

The identifiers associated with dialogs are actually used to refer to the resource blob itself, not to the window. They are used to create the dialog (see CreateDialog().

Once the dialog is created there is no connection to the original template or to that identifier. Actually there is no use for that ID, the dialog is simply identified by its HWND. Note that you can create several different dialog using the same dialog resource.

These identifiers are assigned (usually) sequentially by the resource editor, or manually if you create the resources by hand.

For more insight on the topic you can read about the CreateDialogIndirect() function, that creates a dialog without using a resouce.

like image 85
rodrigo Avatar answered Oct 18 '22 23:10

rodrigo


Here you find a good answer: http://blogs.msdn.com/b/oldnewthing/archive/2005/07/08/436815.aspx

It's like asking, "Given a plate of food, how do I recover the original cookbook and page number for the recipe?" By doing a chemical analysis of the food, you might be able to recover "a" recipe, but there is nothing in the food itself that says, "I came from The Joy of Cooking, page 253."

So the answer is that there is no way provided by Microsoft to obtain the dialog ID. They could have easily stored it anywhere to make it available, but they did not.

But there would still be a way to do it, although it is not bulletproof. You could:

1.) Get the creator file of the dialog via GetWindowModuleFileName()

2.) Load this Exe or Dll via LoadLibraryEx(..., LOAD_LIBRARY_AS_IMAGE_RESOURCE)

3.) Enumerate all RT_DIALOG resources in the Exe or Dll via EnumResourceNames() where the dialog ID is in the name: ResourceName = MAKEINTRESOURCE(IDD_DIALOG_ID)

4.) Create each enumerated dialog invisibly via LoadResource(), LockResource(), CreateDialogIndirect() but without showing the dialog with ShowWindow().

5.) Enumerate the child controls in each dialog via EnumChildWindows() and compare them to your dialog.

6.) Release all handles and destroy the dialogs.

It is not very probable that there are two identical dialogs in a Exe/Dll file. But the problem is that in WM_INITDIALOG the programmer may eliminate (destroy) or add or modify child controls. So your search algorithm would have to be fault tolerant. This would be possible by counting the congruency between each dialog from the resources and your dialog. You could count for how many child controls the ID (GetDlgCtrlID())and class name (GetClassName()) match. (e.g. Class="BUTTON" and ID = 311") While a programmer can easily change the text of a control or move it around, changing the ID is not very probable and does not make much sense and changing the class of a child control is even impossible.

As I said: It is not bullet proof, but you will find the ID of the resource that has most probably been used to create the dialog.

Be aware that not all dialogs come from a Microsoft resource. They can be created by a GUI framework that uses its own type of templates. In this case you will never find the Dialog ID because it simply does not exist.

like image 5
Elmue Avatar answered Oct 19 '22 00:10

Elmue