问题
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:
- Use packages. This works a treat but you must use the same compiler version for all modules.
- 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