300分请请高手解惑 问题已结 (300分)

  • 主题发起人 主题发起人 dira
  • 开始时间 开始时间
D

dira

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在对于事件的理解很模湖
1、自定义组件可以通过拦截标准WINDOWS消息来触发;
2、通过定时器来触发,毕竟这种不多
3、通过接口得到
4、其他的我还不知道
现在问题
1、接口中是如何定义消息的(这是我的理解,可能有错),比如我看了一下TTable 追溯到 TDataSet = class(TComponent, IProviderSupport)

IProviderSupport = interface
['{7AF8F684-0660-47B5-A1B3-E168D2ACB908}']
procedure PSEndTransaction(Commit: Boolean);
procedure PSExecute;
function PSExecuteStatement(const ASQL: string; AParams: TParams;
ResultSet: Pointer = nil): Integer;
procedure PSGetAttributes(List: TList);
function PSGetDefaultOrder: TIndexDef;
function PSGetKeyFields: string;
function PSGetParams: TParams;
function PSGetQuoteChar: string;
function PSGetTableName: string;
function PSGetIndexDefs(IndexTypes: TIndexOptions = [ixPrimary..ixNonMaintained]): TIndexDefs;
function PSGetUpdateException(E: Exception; Prev: EUpdateError): EUpdateError;
function PSInTransaction: Boolean;
function PSIsSQLBased: Boolean;
function PSIsSQLSupported: Boolean;
procedure PSReset;
procedure PSSetParams(AParams: TParams);
procedure PSSetCommandText(const CommandText: string);
procedure PSStartTransaction;
function PSUpdateRecord(UpdateKind: TUpdateKind; Delta: TDataSet): Boolean;
end;

根本就没有如
OnAfterCancel, OnAfterClose等事件?如何来此事件
2、有没有其他的事件触发方式

也许无需长篇大作即解偶心中困惑,谢谢!见者有分
 
我帮你解析一下其中一个.
 
谢谢,静候
 
1,首先声明事件类型 On
TDataSetNotifyEvent = procedure(DataSet: TDataSet) of object;
2,声明事件变量
FBeforeCancel: TDataSetNotifyEvent;
3,公布事件
property BeforeCancel: TDataSetNotifyEvent read FBeforeCancel write FBeforeCancel;

触发事件
1,在TDateSet的Cancel方法中调用过程DoBeforeCancel;
2,在DoBeforeCancel过程中触发BeforeCancel事件,
部分代码如下:
procedure TDataSet.Cancel;

procedure CancelNestedDataSets;
var
I: Integer;
begin
if Assigned(FNestedDataSets) then
for I := 0 to FNestedDataSets.Count - 1 do
with TDataSet(FNestedDataSets) do
if Active then Cancel;
end;

var
DoScrollEvents: Boolean;
begin
case State of
dsEdit, dsInsert:
begin
CancelNestedDataSets;
DataEvent(deCheckBrowseMode, 0);
DoBeforeCancel; //在这里触发,请看下面DoBeforeCancel的代码!!!!!!!!!!!!!!!!!!!
DoScrollEvents := (State = dsInsert);
if DoScrollEvents then DoBeforeScroll;
UpdateCursorPos;
InternalCancel;
FreeFieldBuffers;
SetState(dsBrowse);
Resync([]);
DoAfterCancel;
if DoScrollEvents then DoAfterScroll;
end;
end;
end;

虚拟方法(或动态方法dynamic)触发事件
procedure DoBeforeCancel; virtual;
procedure TDataSet.DoBeforeCancel;
begin
if Assigned(FBeforeCancel) then FBeforeCancel(Self);
end;
 
我想你的思路错了,TDataSet的很多事件是在类中触发的,而不是在接口IProviderSupport
中触发的.
 

谢谢你的解答,你的意思是在类的方法中直接调用实现事件的方法对吗?这个我知道我只是举这个例子而已,请见$DELPHI/SOURCE/RTL/WIN/URLMON.PAS中
IBindStatusCallback = interface
['{79eac9c1-baf9-11ce-8c82-00aa004ba90b}']
function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall;
function GetPriority(out nPriority): HResult; stdcall;
function OnLowResource(reserved: DWORD): HResult; stdcall;
function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
szStatusText: LPCWSTR): HResult; stdcall;
function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult; stdcall;
function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult; stdcall;
function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc: PFormatEtc;
stgmed: PStgMedium): HResult; stdcall;
function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult; stdcall;
end;

如这其中的 function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
szStatusText: LPCWSTR): HResult; stdcall;
就是自动触发的,
 
触发消息的另一种方式
如DBGRID的编辑
可能先检测KEYDOWN、KEYUP等消息再分析调用ONCHANGE的消息处理过程
 
提前有分!!!!!
 
我好学,我也想知道
 
我个人认为你举的两个接口类型的例子,在使用中有本质的差别:
第一个:这种接口是系统提供给用户调用的,他没有事件触发。(当然有一种接口,他通过提供事件连接点来提供事件接口,我把他归入第二类)
第二个:这种接口是系统定义出模板规则,由用户编写,被系统调用,他本身事件触发时,调用用户定义的接口事件,来触发用户事件,像事件连接点等都是这种技术。

所有我个人认为,接口调用主体不同,导致接口表现不同。

个人观点,有错务怪。。。。
 
楼上的意思我大致明白了,那第二种接口是如何定义的呢?
 
我的看法有点不同了.
不管什么形式的事件,其本质都是相同的--函数指针.
不管实现如何,既然是事件,那么就需要一个事件触发者,也就是决定事件是在什么时候被触发,什么时候调用你的OnXXXX函数了。
这个OnXXXX其实就是一个函数指针,在不同的系统不同的技术细节上的表现形式不一样,专有名词不一样罢了。
比如WINDOWS API 就是CALLBACK。
DELPHI 就是 OF OBJECT。
在ACTIVEX里面了就是连接点,是接口INTERFACE,一组函数定义。至于连接点的详细使用方法比较复杂,你可以参看关于COM或ActiveX方面的书。
 
待把连接点看完先,请大虾继续指点
 
to xuesijun:
你说得是笼统而言,但就是接口比较特殊,比如一个接口,两个地方使用,他在内存中只有一份而已,如果你在两个地方都设置了事件,他知道调说呢?如果在接口中保存回调函数的指针表,然后轮流调用,好像不大行吧。。。。
不太明白,还请指教[:)]
 
终于让我看到了热烈氛,不负我每天顶呀,继续听课
 
首先需要说明的是COM有其特殊性,考虑到组件存在不同的进程,不同的机器上,所以不是简单的函数指针的调用,楼上可以看一下有关COM的资料。

COM组件其实不需要知道是谁在调用他,如果有两个客户调用了他,那么同一事件在每一个客户端都会被调用。这个实现实际上是由一个组件的影子存在与客户端的进程内存里面,是他在调用这个事件的指针。这个影子吗其实是一个dll,
在跨进程的组件调用时的叫法是“代理”。
 

Similar threads

后退
顶部