如。自關閉相關問題以來-下面添加了更多示例。下面的簡單代碼(可找到頂級Ie窗口并枚舉其子窗口)可以在“ 32位Windows”目標平臺上正常運行。早期版本的Delphi也沒有問題:procedure TForm1.Button1Click(Sender: TObject); function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; const Server = 'Internet Explorer_Server'; var ClassName: array[0..24] of Char; begin Assert(IsWindow(hwnd)); // <- Assertion fails with 64-bit GetClassName(hwnd, ClassName, Length(ClassName)); Result := ClassName <> Server; if not Result then PUINT_PTR(lParam)^ := hwnd; end;var Wnd, WndChild: HWND;begin Wnd := FindWindow('IEFrame', nil); // top level IE if Wnd <> 0 then begin WndChild := 0; EnumChildWindows(Wnd, @EnumChildren, UINT_PTR(@WndChild)); if WndChild <> 0 then .. end;我插入了,Assert以指示在使用“ 64位Windows”目標平臺時失敗的地方。如果我沒有嵌套回調,則代碼沒有問題。我不確定參數傳遞的錯誤值只是垃圾,還是由于某些錯誤的內存地址(調用約定?)引起的。嵌套回調實際上是我一開始不應該做的事情嗎?還是這僅僅是我必須忍受的缺陷?
3 回答

30秒到達戰場
TA貢獻1828條經驗 獲得超6個贊
該技巧從未得到該語言的正式支持,并且由于32位編譯器的實現細節,您到目前為止一直在使用它。該文檔很清楚:
嵌套過程和函數(在其他例程中聲明的例程)不能用作過程值。
如果我沒記錯的話,一個額外的隱藏參數將通過指向封閉堆棧框架的指針傳遞給嵌套函數。如果未引用封閉環境,則在32位代碼中將其省略。在64位代碼中,總是傳遞額外的參數。
當然,問題的很大一部分是Windows單元將無類型的過程類型用作其回調參數。如果使用了鍵入程序,則編譯器可能會拒絕您的代碼。實際上,我認為這是對您所使用的欺騙絕不合法的信念的證明。對于類型化的回調,即使在32位編譯器中,也永遠無法使用嵌套過程。
無論如何,最重要的是您不能將嵌套函數作為參數傳遞給64位編譯器中的另一個函數。

HUH函數
TA貢獻1836條經驗 獲得超4個贊
事情是我被迫使用'@'運算符,盡管我為回調提供了準確的簽名,因為編譯器破壞了類型系統,因為如果不使用隱藏參數(至少在64位上),它將無法處理局部函數。 。
添加回答
舉報
0/150
提交
取消