2012-07-19 218 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