有没有办法在组件方法上添加参数?
is there a way to add a parameter on a component method?
我正在使用 Delphi 10.3,以及一个从 phone 读取短信的组件。
该组件的工作方式如下:
cmp.ReadSms;
之后,有一个事件 onReadSMS
,每条消息都会被调用。
我需要将每条消息保存在数据库中,但数据库对象在我的主程序中。我无法从活动访问我的数据库。
我想知道是否有办法将我的数据库对象传递给事件,以便我可以在那里进行插入。
编辑:
这是一些代码:
unit myUnit;
TEventHandlers = class
procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
var myEvents: TEventHandlers;
function SMSReceive(dbMain: TFDConnection): Boolean;
var cSMS: TGSMObj;
begin
cSMS: TGSMObj.create(nil);
cSMS.OnReadMessage := myEvents.ReadMessage;
cSMS.ReadSms;
end;
procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
// Here I can read the SMS.
// I would like to do:
// dbMain.ExecSQL('INSERT INTO ...')
// But dbMain is unknown here.
end;
我还要补充一点,这个单元是从某个外部线程调用的,所以我不能有一个全局数据库对象,但我需要在调用 SMSReceive
函数时传递它。
您无法将自定义参数添加到预先存在的事件中(不更改组件的源代码)。但是您可以尝试通过一些选项来操纵事件处理程序的运行方式。
最简单的解决方案是从 TGSMObj
派生一个新的 class 并向其添加一个 TFDConnection
字段,例如:
type
TMyGSMObj = class(TGSMObj)
DB: TFDConnection;
end;
// 'class' methods can be used as event handlers, so you don't
// need to create a global object instance of this class...
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TMyGSMObj;
begin
cSMS := TMyGSMObj.Create(nil);
cSMS.DB := dbMain;
cSMS.OnReadMessage := TEventHandlers.ReadMessage;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TMyGSMObj(Sender).DB.ExecSQL('INSERT INTO ...');
end;
或者,如果 TGSMObj
是一个 TComponent
descendant, you can use its Tag
属性 来保存 TFDConnection
指针,例如:
type
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
begin
cSMS := TGSMObj.Create(nil);
cSMS.Tag := NativeInt(dbMain);
cSMS.OnReadMessage := TEventHandlers.ReadMessage;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(TGSMObj(Sender).Tag).ExecSQL('INSERT INTO ...');
end;
或者,您可以使用 TMethod
记录强制事件处理程序的 Self
参数指向您想要的任何内容,例如:
type
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
Handler: TWhateverTypeOnReadMessageUses;
begin
Handler := TEventHandlers.ReadMessage;
TMethod(Handler).Data := dbMain;
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := Handler;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(Self).ExecSQL('INSERT INTO ...');
end;
或者,无论如何使用 TMethod
,您可以使用独立的过程而不是 class 方法,例如:
procedure ReadMessage(Self: Pointer; Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(Self).ExecSQL('INSERT INTO ...');
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
Handler: TWhateverTypeOnReadMessageUses;
begin
TMethod(Handler).Data := dbMain;
TMethod(Handler).Code := @ReadMessage;
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := Handler;
cSMS.ReadSms;
end;
或者,class helper 可能有效(我自己没试过这个),例如:
type
TFDConnectionHelper = class helper for TFDConnection
public
procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
begin
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := dbMain.ReadMessage;
cSMS.ReadSms;
end;
procedure TFDConnectionHelper.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
Self.ExecSQL('INSERT INTO ...');
end;
我正在使用 Delphi 10.3,以及一个从 phone 读取短信的组件。 该组件的工作方式如下:
cmp.ReadSms;
之后,有一个事件 onReadSMS
,每条消息都会被调用。
我需要将每条消息保存在数据库中,但数据库对象在我的主程序中。我无法从活动访问我的数据库。
我想知道是否有办法将我的数据库对象传递给事件,以便我可以在那里进行插入。
编辑:
这是一些代码:
unit myUnit;
TEventHandlers = class
procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
var myEvents: TEventHandlers;
function SMSReceive(dbMain: TFDConnection): Boolean;
var cSMS: TGSMObj;
begin
cSMS: TGSMObj.create(nil);
cSMS.OnReadMessage := myEvents.ReadMessage;
cSMS.ReadSms;
end;
procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
// Here I can read the SMS.
// I would like to do:
// dbMain.ExecSQL('INSERT INTO ...')
// But dbMain is unknown here.
end;
我还要补充一点,这个单元是从某个外部线程调用的,所以我不能有一个全局数据库对象,但我需要在调用 SMSReceive
函数时传递它。
您无法将自定义参数添加到预先存在的事件中(不更改组件的源代码)。但是您可以尝试通过一些选项来操纵事件处理程序的运行方式。
最简单的解决方案是从 TGSMObj
派生一个新的 class 并向其添加一个 TFDConnection
字段,例如:
type
TMyGSMObj = class(TGSMObj)
DB: TFDConnection;
end;
// 'class' methods can be used as event handlers, so you don't
// need to create a global object instance of this class...
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TMyGSMObj;
begin
cSMS := TMyGSMObj.Create(nil);
cSMS.DB := dbMain;
cSMS.OnReadMessage := TEventHandlers.ReadMessage;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TMyGSMObj(Sender).DB.ExecSQL('INSERT INTO ...');
end;
或者,如果 TGSMObj
是一个 TComponent
descendant, you can use its Tag
属性 来保存 TFDConnection
指针,例如:
type
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
begin
cSMS := TGSMObj.Create(nil);
cSMS.Tag := NativeInt(dbMain);
cSMS.OnReadMessage := TEventHandlers.ReadMessage;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(TGSMObj(Sender).Tag).ExecSQL('INSERT INTO ...');
end;
或者,您可以使用 TMethod
记录强制事件处理程序的 Self
参数指向您想要的任何内容,例如:
type
TEventHandlers = class
class procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
Handler: TWhateverTypeOnReadMessageUses;
begin
Handler := TEventHandlers.ReadMessage;
TMethod(Handler).Data := dbMain;
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := Handler;
cSMS.ReadSms;
end;
class procedure TEventHandlers.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(Self).ExecSQL('INSERT INTO ...');
end;
或者,无论如何使用 TMethod
,您可以使用独立的过程而不是 class 方法,例如:
procedure ReadMessage(Self: Pointer; Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
TFDConnection(Self).ExecSQL('INSERT INTO ...');
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
Handler: TWhateverTypeOnReadMessageUses;
begin
TMethod(Handler).Data := dbMain;
TMethod(Handler).Code := @ReadMessage;
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := Handler;
cSMS.ReadSms;
end;
或者,class helper 可能有效(我自己没试过这个),例如:
type
TFDConnectionHelper = class helper for TFDConnection
public
procedure ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
end;
function SMSReceive(dbMain: TFDConnection): Boolean;
var
cSMS: TGSMObj;
begin
cSMS := TGSMObj.Create(nil);
cSMS.OnReadMessage := dbMain.ReadMessage;
cSMS.ReadSms;
end;
procedure TFDConnectionHelper.ReadMessage(Sender: TObject; MessageText: WideString; PhoneNumber, CenterNumber: AnsiString; TimeStamp: TDateTime; TimeZone, Status, Index: Integer);
begin
Self.ExecSQL('INSERT INTO ...');
end;