How to get instance of TForm from a Handle?

时光毁灭记忆、已成空白 提交于 2021-02-07 02:59:43

问题


I'm converting some functions into a DLL which relate to Windows 7 functionality. I can't pass a TForm through DLL, so I need to pass its handle instead. except, once I have that handle on the other side, how do I reconstruct it back into a TForm instance? Also, what's the appropriate way to pass the handle (HWND) through a Delphi DLL to be compatible to call from C# for example?

If not possible, then I at least need to know how to change the color of a window using windows API only, no reference to the TForm. The goal is that from within this DLL, it needs to somehow change the color of a Form. Passing the handle to the DLL is no problem, but how to use that handle to work with the form that the handle represents?

What I'm doing specifically is putting together a single DLL that contains everything needed to make a Delphi7 application compatible with Windows7, for example, drawing glass, properly showing multiple forms in the taskbar (and minimizing forms), showing the green progress in the taskbar's icon, and whatever else might be involved. This type of work though requires modifying the form. I need to be able to do those modifications from within the DLL.


回答1:


You can't get a TForm from a handle. There's no such thing outside of your Delphi app, unless you're using packages (as David's answer said).

You can use the Handle (HWND) directly in API calls, but only for API calls.

You can pass that HWND directly to API calls like GetDC to get a device context (DC), and then use that DC directly with the DrawTheme related functions like DrawThemeText or anything else that requires a windows DC. You can also pass it to other API calls that require an HWND.




回答2:


In general, you can convert an HWND to a VCL TWinControl-derived object pointer using the VCL's FindControl() function in the Controls unit. You can then check if the TWinControl is actually a TForm using the is operator.

However, as others have stated, passing VCL objects over the DLL boundary in general is dangerous and can cause problems if both EXE and DLL are not compiled with the exact same VCL version, RTL version, memory manager, etc. To pass VCL objects over the DLL boundary safely, change your DLL project into a BPL Package project, and make sure Dynamic RTL is enabled in both EXE and BPL.




回答3:


You can't pass Delphi objects across DLL boundaries. It simply does not work. There is no mechanism to export a Delphi class from a DLL.

You are aware of this but passing a handle across the boundary does not help. You wish to operate on a TForm on the other side of the boundary. But the only TForm instance that can make sense is the only which created the handle, and that instance is trapped by the module boundary.

There are some objects which can be recreated from just a handle. For example, bitmaps and icons have this property. This is because they have no state beyond what is stored in the GDI handle. More complex VCL objects do have such state and therein lies the problem.

Your options are:

  1. Use packages. This works a treat but you must use the same compiler version for all modules.
  2. Use interfaces or COM. This gives you freedom of mixing compiler versions and even different languages.


来源:https://stackoverflow.com/questions/8190224/how-to-get-instance-of-tform-from-a-handle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!