转换为c++;使用消息处理程序调用delphi的dll 我需要在我的Delphi XE3应用程序中使用一个DLL,我已经收到了一个用C++编写的演示应用程序,它演示了如何调用DLL。 我已成功调用DLL和DLL的初始化方法,但没有从DLL返回任何消息。 这是C++的来源: 正在创建消息处理程序: #define WM_POSSTATE WM_APP+1 #define ON_WM_POSSTATE() \ { WM_POSSTATE, 0, 0, 0, AfxSig_vwl, \ (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM))&OnPOS },

转换为c++;使用消息处理程序调用delphi的dll 我需要在我的Delphi XE3应用程序中使用一个DLL,我已经收到了一个用C++编写的演示应用程序,它演示了如何调用DLL。 我已成功调用DLL和DLL的初始化方法,但没有从DLL返回任何消息。 这是C++的来源: 正在创建消息处理程序: #define WM_POSSTATE WM_APP+1 #define ON_WM_POSSTATE() \ { WM_POSSTATE, 0, 0, 0, AfxSig_vwl, \ (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM))&OnPOS },,c++,delphi,dll,delphi-xe3,C++,Delphi,Dll,Delphi Xe3,初始化方法的定义: typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p ); INITIALIZE *Initialize; HMODULE hPosDll; res=::Initialize('com3', WM_POSSTATE , &m_hWnd); if( res ) { MessageBox( "Error opening comms",NULL,MB_OK); F

初始化方法的定义:

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
INITIALIZE *Initialize;

HMODULE         hPosDll;
res=::Initialize('com3', WM_POSSTATE , &m_hWnd);

if( res )
{
    MessageBox( "Error opening comms",NULL,MB_OK);
    FreeLibrary( hPosDll );
    exit(1);
}
正在加载DLL:

if( (hPosDll = LoadLibrary( "posdll.dll" ) ) == NULL )
{
    MessageBox( "Error: can not open posdll.dll",NULL,MB_OK);
    exit(1);
}

if( (::Initialize = (INITIALIZE*)GetProcAddress( hPosDll, "Initialize" )) == NULL )
{
    MessageBox( "Error: can not find function",NULL,MB_OK);
    FreeLibrary( hPosDll );
    exit(1);
}
调用初始化方法:

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
INITIALIZE *Initialize;

HMODULE         hPosDll;
res=::Initialize('com3', WM_POSSTATE , &m_hWnd);

if( res )
{
    MessageBox( "Error opening comms",NULL,MB_OK);
    FreeLibrary( hPosDll );
    exit(1);
}
初始化调用后,从DLL到应用程序的消息由OnPos方法处理:

void CPosDemoDlg::OnPOS(UINT Result, LPARAM Param )
{
    DoStuff;
}
在德尔福,我已经做到了:

unit UFrmMain;

interface

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

const
  WM_POSSTATE = WM_APP + 1;
  MCDLL = 'posdll.dll';

type
  TInitialize = function(cport: PAnsiChar; Msg: Integer; Handle: HWND):Integer; stdcall;

  TFrmMain = class(TForm)
    EdCOMPort: TEdit;
    BtnConnect: TButton;
    LblCOMPort: TLabel;
    procedure ON_WM_POSSTATE(var Msg: TMessage); message WM_POSSTATE;
    procedure BtnConnectClick(Sender: TObject);
  private
    DLLHandle: THandle;
  public
    { Public declarations }
  end;

var
  FrmMain: TFrmMain;

implementation

{$R *.dfm}

{-------------------------------------------------------------------------------}
 procedure TFrmMain.BtnConnectClick(Sender: TObject);
 var
   MCInitialize: TInitialize;
   Res: Integer;
 begin
   DLLHandle := LoadLibrary(PChar(MCDLL));

   if DLLHandle <> 0 then
     begin
       @MCInitialize := getProcAddress(DLLHandle, 'Initialize');

       if @MCInitialize <> NIL then
         begin
           Res := MCInitialize(PAnsiChar('com3'), WM_POSSTATE, Self.Handle);

           if Res <> 0 then
             begin
               MessageDlg('Error opening comms', mtWarning, [mbOK], 0);
             end;
         end;
     end
   else
     begin
       MessageDlg('posdll.dll could not be located.', mtWarning, [mbOK], 0);
     end;
 end;

{-------------------------------------------------------------------------------}
 procedure TFrmMain.ON_WM_POSSTATE(var Msg: TMessage);
 begin
   showmessage('Message received');
 end;

end.
单元UFrmMain;
界面
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、StdCtrls、MCPOSDLL;
常数
WM_POSSTATE=WM_APP+1;
mcdl='posdll.dll';
类型
TInitialize=函数(cport:PAnsiChar;Msg:Integer;Handle:HWND):整数;stdcall;
TFrmMain=类(TForm)
EdCOMPort:TEdit;
BTN连接:t按钮;
LblCOMPort:TLabel;
关于WM postate的程序(var Msg:TMessage);消息WM_postate;
过程BtnConnectClick(发送方:TObject);
私有的
德尔汉德尔:坦德尔;
平民的
{公开声明}
终止
变量
FrmMain:TFrmMain;
实施
{$R*.dfm}
{-------------------------------------------------------------------------------}
过程TFrmMain.BtnConnectClick(发送方:ToObject);
变量
MCInitialize:TInitialize;
Res:整数;
开始
DLLHandle:=加载库(PChar(MCDLL));
如果DLLHandle为0,则
开始
@MCInitialize:=getProcAddress(DLLHandle,'Initialize');
如果@MCInitialize NIL,则
开始
Res:=MCInitialize(PAnsiChar('com3'),WM_POSSTATE,Self.Handle);
如果是0那么
开始
MessageDlg('Error opening comms',mtWarning,[mbOK],0);
终止
终止
终止
其他的
开始
MessageDlg('posdll.dll找不到',mtWarning,[mbOK],0);
终止
终止
{-------------------------------------------------------------------------------}
程序TFrmMain.ON_WM_POSSTATE(var Msg:TMessage);
开始
showmessage(“收到的消息”);
终止
终止
使用此解决方案,我可以激活连接到com3的设备,但messagehandler永远不会被触发。
我认为用C++中的初始化方法发送的<代码>和MyHWND <代码>与 Sub不一样。句柄< /Cord>我在Delphi中发送。
有人能帮我吗?提前谢谢。

乍一看,它看起来像你的声明

TInitialize = function(cport: PAnsiChar; Msg: Integer; Handle: HWND):Integer;
不匹配

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
请注意,C声明需要一个指向持有句柄的变量的指针

试一试


看看你能走多远。

乍一看,它就像你的宣言

TInitialize = function(cport: PAnsiChar; Msg: Integer; Handle: HWND):Integer;
不匹配

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
请注意,C声明需要一个指向持有句柄的变量的指针

试一试


看看你有多大。

< P> C++函数被声明为:

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
TInitialize = function(cport: PAnsiChar; Msg: Integer; 
  Handle: HWND): Integer; stdcall;
您的德尔福等效物声明为:

typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
TInitialize = function(cport: PAnsiChar; Msg: Integer; 
  Handle: HWND): Integer; stdcall;
我可以在您的Delphi声明中看到以下差异:

  • Msg
    参数是无符号的,但是Delphi翻译是有符号的
  • hWnd\u p
    参数是指向
    hWnd
    的指针。在Delphi中,按值传递窗口句柄
  • C++代码的调用约定是代码> CDECL < /C>,但是您把Delphi代码声明为<代码> STDCALL> /COD> < < 因此,在德尔福,声明应为:

    TInitialize = function(cport: PAnsiChar; Msg: Cardinal; 
      Handle: PHWND): Integer; cdecl;
    
    其中,
    PHWND
    是声明为
    ^HWND
    的类型。我怀疑这样一个类型是在
    Windows
    单元中声明的,但是如果不是,那么您可以很容易地声明它

    或者更简单的翻译是:

    TInitialize = function(cport: PAnsiChar; Msg: Cardinal; 
      var Handle: HWND): Integer; cdecl;
    
    当然,当你抄写C++代码时,你忽略了调用约定是合理的。也许函数实际上是
    stdcall
    ,即使您在问题中的声明没有这样说

    除此之外,您的代码正在使用窗体的窗口句柄。这可能有风险。在某些情况下,VCL会重新创建窗口。这将导致传递给DLL的句柄被销毁。DLL将继续向该窗口发送消息,但您的窗体将停止接收消息,因为其窗口已更改

    解决方法是使用VCL不会重新创建的窗口句柄。通过调用
    AllocateHwnd
    获取其中一个


    调用
    初始化
    时要小心。您将
    PAnsiChar('com3')
    作为端口名传递。您需要确保文本
    'com3'
    确实是ANSI编码的。理想情况下,您应该将
    'com3'
    直接传递到
    初始化
    。如果这不编译(我不确定是否会在我的头上),然后通过<代码> PAnsiChar(AnsiString('COM3)) ./P> < P> C++函数被声明为:

    typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
    
    TInitialize = function(cport: PAnsiChar; Msg: Integer; 
      Handle: HWND): Integer; stdcall;
    
    您的德尔福等效物声明为:

    typedef int (INITIALIZE)( char * cPort , UINT Msg, HWND *hWnd_p );
    
    TInitialize = function(cport: PAnsiChar; Msg: Integer; 
      Handle: HWND): Integer; stdcall;
    
    我可以在您的Delphi声明中看到以下差异:

  • Msg
    参数是无符号的,但是Delphi翻译是有符号的
  • hWnd\u p
    参数是指向
    hWnd
    的指针。在Delphi中,按值传递窗口句柄
  • C++代码的调用约定是代码> CDECL < /C>,但是您把Delphi代码声明为<代码> STDCALL> /COD> < < 因此,在德尔福,声明应为:

    TInitialize = function(cport: PAnsiChar; Msg: Cardinal; 
      Handle: PHWND): Integer; cdecl;
    
    其中,
    PHWND
    是声明为
    ^HWND
    的类型。我怀疑这样一个类型是在
    Windows
    单元中声明的,但是如果不是,那么您可以很容易地声明它

    或者更简单的翻译是:

    TInitialize = function(cport: PAnsiChar; Msg: Cardinal; 
      var Handle: HWND): Integer; cdecl;
    
    当然,当你抄写C++代码时,你忽略了调用约定是合理的。也许函数实际上是
    stdcall
    ,即使您在问题中的声明没有这样说

    除此之外,您的代码正在使用窗体的窗口句柄