Delphi XE2、Delphi 10、应用程序句柄、Dll、操作错误

Delphi XE2、Delphi 10、应用程序句柄、Dll、操作错误,delphi,delphi-xe2,delphi-10-seattle,Delphi,Delphi Xe2,Delphi 10 Seattle,我在Delphi XE2中创建了App.exe应用程序,然后在Delphi 10中创建了DLL。调用DLL后,当我将Application.Handle传递给DLL时,我会得到一个错误“Exception class…‘浮点堆栈检查…’”。当我从EXE分配中删除Application.Handle时,DLL是正常的。我注意到这与连接到controlek的触觉动作有关。例如转到主菜单。我还要补充一点,当从用Delphi 10编写的EXE调用DLL时,一切正常 谢谢你的帮助 下面我附上一些代码 代码

我在Delphi XE2中创建了App.exe应用程序,然后在Delphi 10中创建了DLL。调用DLL后,当我将Application.Handle传递给DLL时,我会得到一个错误“Exception class…‘浮点堆栈检查…’”。当我从EXE分配中删除Application.Handle时,DLL是正常的。我注意到这与连接到controlek的触觉动作有关。例如转到主菜单。我还要补充一点,当从用Delphi 10编写的EXE调用DLL时,一切正常

谢谢你的帮助

下面我附上一些代码

代码delphixe2

unit Form_MainApp;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons;

type
  TfrmMainApp = class(TForm)
    btnRunDLL: TBitBtn;
    procedure btnRunDLLClick(Sender: TObject);
  private
  public

  end;

var
  frmMainApp: TfrmMainApp;

implementation

{$R *.dfm}

procedure TfrmMainApp.btnRunDLLClick(Sender: TObject);
const
  LibraryFolder = '\Library\';
    DLLName = LibraryFolder + 'TestDLL.dll';
type
  TDLLProc = Function(pAppHandle:HWND; pAppTitle:PChar; pId:Integer; var pOUTId:Integer): TModalResult; StdCall;
var
  DLLHandle: THandle;
    DLLProc: TDLLProc;
  DLLResult: TModalResult;
  OUTId: Integer;
  LibraryName: String;
begin
  LibraryName:=ExtractFileDir(Application.ExeName) + DLLName;
  DLLHandle:=Winapi.Windows.LoadLibrary(PChar(LibraryName));
    try
    if DLLHandle <> 0 then
      begin
        @DLLProc:=Winapi.Windows.GetProcAddress(DLLHandle, PChar('Run_TestDLL'));
        if (@DLLProc <> nil) then
          DLLResult:=DLLProc(Application.Handle, PChar(Application.Title), 0, OUTId);
      end;
    finally
    if DLLHandle <> 0 then
      Winapi.Windows.FreeLibrary(DLLHandle);
    end;
end;

end.
DLL中的窗体

unit Form_MainDLL;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  cxEdit, dxBar, Vcl.ExtCtrls, System.Actions,
  Vcl.ActnList, Vcl.Menus, Vcl.StdCtrls;

type
  TfrmMainDLL = class(TForm)
    mmMain: TMainMenu;
    mmEdit: TMenuItem;
    mmAdd: TMenuItem;
    mmData: TMenuItem;
    mmClose: TMenuItem;
    mmOpen: TMenuItem;
    btnSetAction: TButton;
    alMain: TActionList;
    acAdd: TAction;
    procedure acAddExecute(Sender: TObject);
    procedure btnSetActionClick(Sender: TObject);
  private
    fName: String;
  public
    constructor Create(pName:String);reintroduce; virtual;
    destructor Destroy; Override;
  end;

var
  frmMainDLL: TfrmMainDLL;

implementation

{$R *.dfm}

constructor TfrmMainDLL.Create(pName:String);
begin
  inherited Create(Nil);
  fName:=pName;
end;

destructor TfrmMainDLL.Destroy;
begin

  inherited;
end;

procedure TfrmMainDLL.acAddExecute(Sender: TObject);
begin
  ShowMessage('TEST');
end;

procedure TfrmMainDLL.btnSetActionClick(Sender: TObject);
begin
  mmAdd.Action:=acAdd;
  mmAdd.OnClick:=acAddExecute;
end;


end.

您需要确保消息
CM_ACTIONEXECUTE
CM_ACTIONUPDATE
不会从DLL中的VCL代码发送到EXE中的VCL代码(因为它们具有不同的运行时和不同的战术对象)

有几种方法:

  • 挂起应用程序的窗口程序。处理窗口并过滤消息。 例如,请参见以下位置的HookApplication和UnHookApp:
  • 将OnUpdate和OnExecute处理程序添加到所有TAction对象
  • 完全不要使用TAction

  • 另外,您需要捕获Run_TestDLL中的所有异常。

    请显示一个我设法添加了一些代码的示例。我准备了一个简单的例子。DLL是一个只有TMainMenu,TActionList的表单。主菜单已连接到操作。尝试运行此操作会导致错误。这不是错误。请再试一次。也许你会告诉我我有什么准备让你看看这个问题?你好。谢谢你的帮助。我应用了解决方案2,效果很好。所以在普通代码中,我必须为所有操作创建一个OnUpdate方法。对于解决方案1,我必须读一点。到目前为止,我还不知道我应该在哪里做出建议的修改?你能写更多关于这个(发送)吗?我将尝试将DXE2版本的系统与D10Seattle中编写的新模块进行集成,我希望我仍能找到一些有趣的案例。我想问一下,为什么在这两个不同的编译器中编译(在我的例子中)会出现这种情况。(DXE2中的Exe,D10E中的dll)。在相同的编译器中编译exe和dll时,一切正常。基本原则:不能在exe和dll之间传递对象、字符串(WideString除外)和动态数组。要有可能传递字符串/动态数组,您需要使用共享内存管理器。要有可能传递对象,您需要使用packages.CM_ACTIONEXECUTE和CM_ACTIONUPDATE将对象从DLL传递到EXE运行时。我知道,并尝试应用“基本原则”。关于内存管理器,我也知道。不幸的是,我不能使用软件包。
    unit Form_MainDLL;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
      System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
      cxEdit, dxBar, Vcl.ExtCtrls, System.Actions,
      Vcl.ActnList, Vcl.Menus, Vcl.StdCtrls;
    
    type
      TfrmMainDLL = class(TForm)
        mmMain: TMainMenu;
        mmEdit: TMenuItem;
        mmAdd: TMenuItem;
        mmData: TMenuItem;
        mmClose: TMenuItem;
        mmOpen: TMenuItem;
        btnSetAction: TButton;
        alMain: TActionList;
        acAdd: TAction;
        procedure acAddExecute(Sender: TObject);
        procedure btnSetActionClick(Sender: TObject);
      private
        fName: String;
      public
        constructor Create(pName:String);reintroduce; virtual;
        destructor Destroy; Override;
      end;
    
    var
      frmMainDLL: TfrmMainDLL;
    
    implementation
    
    {$R *.dfm}
    
    constructor TfrmMainDLL.Create(pName:String);
    begin
      inherited Create(Nil);
      fName:=pName;
    end;
    
    destructor TfrmMainDLL.Destroy;
    begin
    
      inherited;
    end;
    
    procedure TfrmMainDLL.acAddExecute(Sender: TObject);
    begin
      ShowMessage('TEST');
    end;
    
    procedure TfrmMainDLL.btnSetActionClick(Sender: TObject);
    begin
      mmAdd.Action:=acAdd;
      mmAdd.OnClick:=acAddExecute;
    end;
    
    
    end.