I have a legacy application written in Delphi, and need to build a mechanism for
data from/to a TStringGrid.
I don't have the source code of the application, there is no automation interface and it is very unlikely that the vendor will provide one.
Therefore I've created
DLL 2 gets access to the TStringGrid instance inside the legacy application, reads cell values and writes them into the debug log.
Reading works fine. But, when I try to write data into a grid cell using a call like
realGrid.Cells[1,1] := 'Test';
an access violation occurs.
Here's the code:
procedure DllMain(reason: integer) ;
type
PForm = ^TForm;
PClass = ^TClass;
PStringGrid = ^TStringGrid;
var
[...]
begin
if reason = DLL_PROCESS_ATTACH then
begin
handle := FindWindow('TForm1', 'FORMSSSSS');
formPtr := PForm(GetVCLObjectAddr(handle) + 4);
if (not Assigned(formPtr)) then
begin
OutputDebugString(PChar('Not assigned'));
Exit;
end;
form := formPtr^;
// Find the grid component and assign it to variable realGrid
[...]
// Iterate over all cells of the grid and write their values into the debug log
for I := 0 to realGrid.RowCount - 1 do
begin
for J := 0 to realGrid.ColCount - 1 do
begin
OutputDebugString(PChar('Grid[' + IntToStr(I) + '][' + IntToStr(J) + ']=' + realGrid.Cells[J,I]));
// This works fine
end;
end;
// Now we'll try to write data into the grid
realGrid.Cells[1,1] := 'Test'; // Crash - access violation
end;
end; (*DllMain*)
How can I write data into a TStringGrid without getting access violation problem?
This approach simply is not going to work. You have two VCL instances in the target executable. One owned by the target app and one owned by the DLL. That's one VCL instance too many. You might be able to get away with that if the exact same version of Delphi is used to build both the target app and your DLL.
However, you will still have two heap managers in play. And your code passes heap allocated memory between your different VCL instances. You will be allocating in one heap and deallocating in the other. That doesn't work and will result in access violations.
You are passing a string allocated in the DLL's heap to the string grid object that uses the target app's heap. That just cannot work.
I think the access violation will occur at the point at which the DLL code attempts to deallocate the previous value of Cells[i,j]
, that was allocated by the target app's heap manager.
Basically what you are attempting is not going to work. You could find out the address of the target app's implementation of TStringGrid.SetCell
and fake a call to that. But you'd also need to find the target app's implementation of GetMem
, FreeMem
etc. and make sure that all dynamic memory that crossed from your DLL to the target app was allocated and deallocated by the target app's heap. You are going to have a devil of a job making this work. Of course, if both target app and the DLL used the shared memory manager, then you might just be able to make this approach fly.
Much simpler would be to fake keyboard input. I personally would scope out the feasibility of that using AutoHotKey.