求助网络大神这是啥歌各位大神 nierinterface.dll丢失

时间:(星期五) 15:00(下午三点)
主题:浅谈怎样利用EXE + BPL + DLL + Interface实现插件式客户端解决方案
地点:群号:5726882(煮茶待英雄会议室)
主讲:A1.烟灰缸、D10.天地弦
技术支持:A3.武稀松(王锐)
14:55:52 /:&D10.天地弦()
先来一点对象的基础知识润润
14:56:38 /:&D10.天地弦()
这个是献给初学者的。
14:57:28 /:&D10.天地弦()
14:59:03 /:&D10.天地弦()
上图中A.Free,是将实例内存释放。A实际上是一指针。指向实例内存块。A.Free后A并不是为A仍然记录,
实例内存块的地址(虽然内存已经释放),就像锁被砸碎了,钥匙依然还在(还是指向那把锁)一样。
所以在使用if Form1 = nil来判断Form1对象实例已经建立时要注意。
对象间的赋值(B:=A)只是将对象地址就是指针的赋值,将A实例地址赋值给B,B也是指向那块地址。
14:59:29 /:&D10.天地弦()
我讲得可能不对,请高手帮忙指正
14:59:41 /:&D10.天地弦()
结合图,看
15:00:00 A3.武稀松()
Delphi中的类类型变量实际上都是指针,是对象的引用
15:00:27 /:&D10.天地弦()
我们经常判断窗体有没有建立,一般用
if Form1 = nil then
  没有建立
15:00:46 D3天之痕若虹()
if not assigned() then 
15:01:14 /:&D10.天地弦()
assigned也是判断对象是不是为nil
15:01:16 Max.Free/mg()
内存释放不等于指针也清空
15:01:21 /:&D10.天地弦()
15:01:34 D3天之痕若虹()
freeandnil()时, a才为nil
15:01:43 C01.枫长舞()
D3天之痕若虹(:00:46
if not assigned() then 
---有时这样判断也会出错。
15:01:44 /:&D10.天地弦()
上图中A.Free,是将实例内存释放。A实际上是一指针。指向实例内存块。A.Free后A并不是为A仍然记录,
实例内存块的地址(虽然内存已经释放),就像锁被砸碎了,钥匙依然还在(还是指向那把锁)一样。
所以在使用if Form1 = nil来判断Form1对象实例已经建立时要注意。
对象间的赋值(B:=A)只是将对象地址就是指针的赋值,将A实例地址赋值给B,B也是指向那块地址。
--------------------------
上面的图懂了这几句就参不多了
15:01:49 A3.武稀松()
A3.武稀松(:02:53
Delphi中的类类型变量实际上都是指针,是对象的引用
,其实讲了这么久说是面向对象知识.其实都是指针的知识而已.D10命题不准
15:02:14 /:&D10.天地弦()
好了,开始正题吧
15:02:23 B1.斜阳()
建议大家以后释放对象的时候多使用FreeAndNil这个函数
15:02:25 /:&D10.天地弦()
回家慢慢品味一下就行了
15:03:45 A3.武稀松()
如果是组件的派生类注意在Notifiction方法就行了
15:04:00 /:&D10.天地弦()
刚刚是送的
15:04:02 /:&D10.天地弦()
15:04:39 /:&D10.天地弦()
BPL + DLL + EXE
15:05:11 /:&D10.天地弦()
一个大的项目一般要分成几个模块
15:05:44 /:&D10.天地弦()
15:06:09 /:&D10.天地弦()
有谁用DLL来开发模块
15:06:17 dirk/:;()
15:06:18 Max.Free/mg()
15:06:19 Chester()
15:06:20 KEN()
15:06:25 凡尘()
15:06:31 /:&D10.天地弦()
15:06:33 Chester()
不过我是带窗体的可能有点不好
15:06:33 清葱岁月()
15:06:38 很深()
一直没试过。快讲
15:06:40 凡尘()
但没开始做呢.所以需要这方面的只是.
15:06:46 /$HansBen/sj(1011185)
15:06:50 古木()
15:06:55 /:&D10.天地弦()
15:07:01 KEN()
我也刚刚用,带窗体的
15:07:09 A3.武稀松()
Chester(:06:33
不过我是带窗体的可能有点不好
---------------
我们讨论的带运行时包就没问题
15:07:24 Max.Free/mg()
偶的都带运行包
15:07:25 A3.武稀松()
所以请大家往下听
15:07:31 /:&D10.天地弦()
做过的,都比较清楚,纯DLL里放子窗体是是比较难搞的,是不是
15:07:48 /:&D10.天地弦()
请大家跟着我思路来
15:07:49 Max.Free/mg()
15:07:50 A1.笑熬糨糊(2282902)
D10,分小题来。
15:08:00 dirk/:;()
我都是代form的
15:08:04 /:&D10.天地弦()
争取一堂课讲完,讲第二次就不好了
15:08:07 Chester()
什么子窗体,是不是MDI窗体
15:08:11 /:&D10.天地弦()
15:08:28 /:&D10.天地弦()
第一小题:为什么不用纯DLL
15:08:29 dirk/:;()
我是用普通form,非mdi
15:08:35 A3.武稀松()
任何都可以
15:08:56 KEN()
什么是运行包 BPL 
15:08:57 dirk/:;()
我就是用纯dll的
15:09:09 A3.武稀松()
建议先给大家普及一下包的知识和原理
15:09:14 /:&D10.天地弦()
做过的都知道纯DLL有很多问题
15:09:45 Max.Free/mg()
纯DLL我也做过,子窗体的.问题都解决了.
15:09:53 凡尘()
那你不用听了.
15:09:54 古木()
单使用DLL,我已经测试成功
15:10:20 dirk/:;()
我插一句,纯dll有些小问题,不过并不影响主要的程序功能
15:11:24 B1.斜阳()
技术是百家争鸣,说不上谁好谁不好,在没有找到更好的途径之前,先听D10讲好不。毕竟多一种思路多一种选
择啊,路多了更好走。
15:11:32 /:&D10.天地弦()
EXE + BPL + DLL 这种模式就是要解决DLL中的种种问题
还有要实现将模块像插件一样
15:12:12 /:&D10.天地弦()
只要遵守规则拿来插件就可以使用了
15:13:00 /:&D10.天地弦()
上面所说的是为什么我们要使用EXE + BPL + DLL这种模式
15:13:58 A3.武稀松()
上面你也没解释为什么啊
15:14:06 /:&D10.天地弦()
前面A3,和A1讨论过BPL最大的好处就是共享数据
15:14:46 A3.武稀松()
最好把那节共享包的博客日记发给大家
15:15:18 /:&D10.天地弦()
所以就有了这种模式了,因为事包BPL最大的好处就是共享数据
看看readme.txt
15:25:20 /:&D10.天地弦()
主要的思路在上面的界面上了
15:25:24 A3.武稀松()
15:26:23 /:&D10.天地弦()
采用的是将mdi类似的窗体。子窗本是放在PageControl的TabSheet上的
15:26:35 /:&D10.天地弦()
PageControl是主窗体
15:27:19 A1.笑熬糨糊(2282902)
算了,D10,我先带大家一阵路,不然,下面的路不好走。
15:27:59 /:&D10.天地弦()
老大,你先讲讲
15:28:19 A1.笑熬糨糊(2282902)
首先,我们要明确一点,为什么要用EXE+BPL+DLL的方式来开发程序。
15:28:31 /:&D10.天地弦()
跟老大走走
15:28:40 A1.笑熬糨糊(2282902)
其它的先放下了,先跟著我走一走。
15:29:08 A1.笑熬糨糊(2282902)
首先,是DLL的问题。
15:30:37 A1.笑熬糨糊(2282902)
很多人都是被DLL整个焦头Lan耳,这大家都有碰过的了。
15:31:14 A1.笑熬糨糊(2282902)
如果DLL中没有FORM,那还好说;如果,有FORM的话,各种各样的问题就来了。
15:31:27 A3.武稀松()
严格来说是类
15:31:35 Max.Free/mg()
主要是 Application 是问题.
15:31:41 A3.武稀松()
还有字符串的问题都可以解决
15:31:42 龙在天()
什么问题呢
15:31:44 很深()
带包是什么意思
15:31:47 D3天之痕若虹()
还有 forms这单元
15:31:53 刚子(9294341)
尤其是要有数据源的话
15:32:01 A1.笑熬糨糊(2282902)
例如,内存的问题阿,Tab键的问题阿,Active的问题阿,等等。。。
15:32:09 A3.武稀松()
只要有类就会有这个问题
15:32:14 /:&D10.天地弦()
正是因为种种的痛苦的经历,所以有了这个打算讲解,希望大家好好珍惜。
15:33:08 A1.笑熬糨糊(2282902)
正是因为这样,所以,好多人都想去弄一个方法来解决这个问题。
15:33:38 A1.笑熬糨糊(2282902)
所以,才有了用EXE-&BPL&-DLL这的方法。
15:33:47 dirk/:;()
其实我一直在用dll,到是没有太大的问题
15:34:12 A1.笑熬糨糊(2282902)
第一小题完毕。
15:34:28 A3.武稀松()
如果你对VCL比较了解,小心翼翼的用DLL不会遇到问题.但是用了包就更方便了
15:35:19 A1.笑熬糨糊(2282902)
第二小题:既然用了EXE+BPL+DLL的方式,那么,还用接口干什么?
15:35:27 刚子(9294341)
用了包是不是所有编译用到的包不允许有重复的
15:35:36 很深()
第一题讲完了?
15:35:41 A3.武稀松()
建议去看D10的博客,里面有我和A1关于包和DLL结合的好处,和包的机制
15:36:48 A1.笑熬糨糊(2282902)
我们约定,把这个方式定义为:三明治方式。
15:36:55 刚子(9294341)
即 A包中用到 vcl.bpl 而B、c中都用到Vcl.bpl 这样是不是要把Vcl.bpl给提出来
15:37:01 A1.笑熬糨糊(2282902)
BPL相当於中间的馅。
15:38:07 A1.笑熬糨糊(2282902)
其实,第二小题中:接口和三明治无关。两者是牛和马的关系。
15:38:08 Max.Free/mg()
主要是用bpl来共享内存吧.
15:39:05 A1.笑熬糨糊(2282902)
也就是说,无论你用不用三明治方式,都可以用接口。
15:39:35 A1.笑熬糨糊(2282902)
第三小题。
15:40:03 A3.武稀松()
平时我们用纯DLL那么VCL的类会在EXE和DLL中各有一份.Application等全局变量也会各有一份.这就是纯DLL的
一切犯罪的源泉---RTL是两份.
而我们这套方案EXE和DLL都是带包运行的,那么EXE和DLL都共享运行时包中的RTL信息和VCL类库.那么就不会出
现地址问题等.也不用麻烦传递Application什么的全局变量了
15:40:22 A1.笑熬糨糊(2282902)
第三小题:BPL在三明治方式中起什么作用。
15:40:23 dirk/:;()
接口的用途和例子可以看看dfw中的wings的笔记。
15:41:15 Max.Free/mg()
是接口在这个主题中起什么作用? 先听A1 说bpl的.
15:41:31 A1.笑熬糨糊(2282902)
BPL的最大作用就是:EXE和DLL共享内存(包含变量,类,实际,接口。。。)
15:42:38 A1.笑熬糨糊(2282902)
其中,共享内存中最好用的就是:共享类注册表了。
15:43:24 A1.笑熬糨糊(2282902)
其它的纯DLL也可以作得到,但不如三明治方便。
15:45:38 A1.笑熬糨糊(2282902)
第四小题,EXE用什么方案来维护BPL和DLL的内容。
05-02-25 15:46:55 A1.笑熬糨糊(2282902)
这一小题中,大家要记得一点,要BPL作用“共享内存”,不要作为其它用途。为什么呢,以下的课会慢慢讲了
15:47:01 dirk/:;()
wings的笔记,不知道接口的可以看这个入门,知道接口是怎么工作的:
15:47:37 A1.笑熬糨糊(2282902)
所有的业务界面和DM放在DLL中,BPL只放基类。
15:47:55 A1.笑熬糨糊(2282902)
这样的话,三明治方式就起作用了。
15:48:06 A3.武稀松()
还有一点请A1解释
15:48:43 A1.笑熬糨糊(2282902)
我的路带完,下面请D10继续带路。。。
15:49:14 A3.武稀松()
D10,你的设计方法是EXE+DLL+BPL,那你说一下既然包有这么多好处,为什么还要用DLL而不用EXE+BPL方式呢?
15:49:51 Yananay()
对啊,那还要dll做什么?
15:50:17 Chester()
D10,你从怎样开始做开始讲吧,教我们怎样做
15:50:21 A3.武稀松()
显然大家了解你为什么采用这样的设计方式
15:50:33 A3.武稀松()
先让大家了解你为什么采用这样的设计方式 
15:51:32 A3.武稀松()
纯DLL方式的问题你也说了,那纯BPL呢
15:51:54 B6.银狼()
我想动态加bpl太麻烦了吧
15:52:03 A3.武稀松()
BPL可以静态加载的
15:52:31 A3.武稀松()
A1来讲一下EXE+DLL+BPL的必要性吧
15:54:08 A1.笑熬糨糊(2282902)
算了,我来解释这个问题。
15:54:18 A1.笑熬糨糊(2282902)
第五小题:
15:54:23 Yananay()
bpl 可以安全传递delphi自己的对象,dll 就不保证了
15:54:44 A1.笑熬糨糊(2282902)
第五小题:为什么不用EXE+BPL的方式(也就是纯BPL的方式)。
15:55:34 A1.笑熬糨糊(2282902)
第一点,大家有没有发觉,动态加载DLL比动太加载BPL方便多了。
15:56:32 凡尘()
动态怎么加载bpl?
15:56:33 吕不为()
loadpackage
15:56:35 B2.TCP INFO()
LoadPackage
15:56:36 A1.笑熬糨糊(2282902)
动态加载BPL的话,一大堆事情要做,往往不如静态加载BPL方便。
15:56:39 A3.武稀松()
静态加载也比较方便,和单一EXE开发差不多
15:56:58 Max.Free/mg()
DLL 与 exe 只是调用方式不同.
15:57:27 A1.笑熬糨糊(2282902)
但DLL动态加载就比较方便了。要做的事情也不多,只有一个入口清扫而已。
15:57:41 Yananay()
静态加载bpl和静态加载dll效果一样的
15:58:00 凡尘()
静态能加载dll?
15:58:19 A3.武稀松()
静态加载BPL类不需要注册就可以使用,单元可以直接引用.而动态加载则要注册类.
15:58:20 A1.笑熬糨糊(2282902)
所以,EXE+BPL+DLL的方式实际上就是一静一动的方式来做三明治了。
15:58:41 Yananay()
“静态加载BPL类不需要注册就可以使用,单元可以直接引用.而动态加载则要注册类”
15:58:58 Yananay()
loadpackage ,不用注册类啊
15:59:01 A3.武稀松()
所以动态加载BPL还是比静态加载要麻烦一点的.这就是A1说的第一点
15:59:13 A1.笑熬糨糊(2282902)
题外话:开发程序不能死脑经。活用就是最好的。
15:59:25 A3.武稀松()
Yananay(:58:58
loadpackage ,不用注册类啊
--------------
那么你怎么用里面的类和引用里面的单元呢
16:00:23 Yananay()
只是调用一下接口,创建出来bpl,然后就是bpl做了
16:00:30 A3.武稀松()
所以你要注册啊
16:01:02 A3.武稀松()
不明白的自己回去看.A1,D10继续吧
16:01:23 A3.武稀松()
每个人都等太罗嗦了
16:01:37 /:&D10.天地弦()
我下次细细的讲解
上面那个demo
抱歉我只会讲解代码,希望大家可以从代码中理解,并可以知道怎么样用这种方式来制作项目
16:04:10 A1.笑熬糨糊(2282902)
别的不说,我刚说的五小点,大家看懂了没?
16:04:35 /:&D10.天地弦()
我想这样讲大方向还是有很多初级者听不明,不如下讲我讲讲代码,再结合这次讲的,也许效果比较好
16:04:59 A1.笑熬糨糊(2282902)
D10可以讲代码了。
16:06:10 A1.笑熬糨糊(2282902)
讲的时候,可以讲讲“这一步为什么这样做”就可以了。
16:06:32 /:&D10.天地弦()
那讲代码吧,代码不是很多。
16:07:30 /:&D10.天地弦()
好,如果有工程的大家打开工程
16:08:04 /:&D10.天地弦()
打开ExeBplDll.bpg
16:08:44 /:&D10.天地弦()
16:08:54 /:&D10.天地弦()
看到图没有
16:09:32 /:&D10.天地弦()
里面有一个EXE(主程序) + BPL(共享数据包) + DLL(两个DLL,两个模块)
16:10:17 /:&D10.天地弦()
打开 DataCentre.bpl这个包
16:10:29 /:&D10.天地弦()
看看里面有什么单元
16:11:10 /:&D10.天地弦()
打开了,你看到里面有几个什么单元
16:11:37 B2.TCP INFO()
DKFBaseForm,uDKSoftDM
16:11:41 /:&D10.天地弦()
请大伙跟我思路走
16:11:42  郭大路/wx:()
  uDKSoftDM in 'uDKSoftDM.pas' {DKSoftDM: TDataModule},
  dkFBaseForm in 'dkFBaseForm.pas' {FBaseForm};
16:12:13 /:&D10.天地弦()
FBaseForm是工程里所有窗体的基类
16:12:26 /:&D10.天地弦()
uDKSoftDM.pas
大家想想为什么要用这个单元包含在DataCentre.bpl里
16:14:23 /:&D10.天地弦()
大家想想为什么要用这个单元包含在DataCentre.bpl里
------------
因为这个包是要带的
16:14:48 /:&D10.天地弦()
所以Exe 和DLL中都只会存在并且使用一个对象
16:15:00 D8。飘尘()
接口的一个好处大家没有说了
16:15:25 /:&D10.天地弦()
也就是说DKSoftDM:TdkSoftDM这个对象在Exe和所有的DLL(模块中)是只有一份的
16:15:30 /:&D10.天地弦()
16:16:05 凡尘()
那样会不会有很多共享出现的问题?
16:16:09 /:&D10.天地弦()
知道怎么样才可以共享这个数据包吗?
16:16:54 KEN()
老大不是说 DM放在DLL中,BPL只放基类
16:16:56 /:&D10.天地弦()
凡尘(:16:05
那样会不会有很多共享出现的问题?
--------------------------
我们都想DLL中共享一个数据链接(ADOConnection)
16:16:59 /:&D10.天地弦()
大家可以看看ProjectEds.exe和两个DLL里面都有
16:17:17 /:&D10.天地弦()
大家可以看看ProjectEds.exe和两个DLL里面的Build with package
16:17:44 /:&D10.天地弦()
16:17:48 /:&D10.天地弦()
这样就是带包了
16:17:51 A3.武稀松()
KEN(:16:54
老大不是说 DM放在DLL中,BPL只放基类
------------
BPL的另一个作用就是共享数据
16:17:58 /:&D10.天地弦()
exe和dll里面都带了三个包
16:18:33 吕不为()
共享对象。
16:18:45 A3.武稀松()
16:19:12 /:&D10.天地弦()
好了,大家继续上路
16:19:26 A1.笑熬糨糊(2282902)
DM放在BPL中也可以,但没有DLL方便。
16:19:29 /:&D10.天地弦()
打开主窗体
16:19:47 清葱岁月()
我下下来的怎么没有exe啊?
16:20:37 /:&D10.天地弦()
打开主窗体吧,我带着大家走一次
16:20:57 凡尘()
所谓的主窗体是不是.FMainForm?
16:21:09 /:&D10.天地弦()
16:22:07 /:&D10.天地弦()
看看第一个菜单上的
16:22:15 /:&D10.天地弦()
16:23:24 凡尘()
16:23:48 /:&D10.天地弦()
装入DLL,这个比较简单,
16:23:56 /:&D10.天地弦()
也是用Loadlibrary
16:24:19 /:&D10.天地弦()
只是我把这些工作都封装在类里面
16:24:49 /:&D10.天地弦()
现在我们来打开B组窗体
16:25:35 /:&D10.天地弦()
procedure TFMainForm.MuiBGroupClick(Sender: TObject);
  TsSheet: TTabS
  if BLoader.ModelServiceInts.ExecuteCmd(CMD_BEFORE_EXECUTE, 0, 0) = S_OK then
  begin
    TsSheet := TTabSheet.Create(self);
    TsSheet.PageControl := pgcM
    BLoader.ModelServiceInts.ExecuteCmd(CMD_CREATE_FORM, TsSheet.Handle, 0);
    AddFormInfo(TsSheet.Handle, 'B组窗体');
16:25:51 凡尘()
怪哉.TLoader是什么类?
16:26:06 /:&D10.天地弦()
TLoader可以看看源码
16:26:15 Chester()
DLLLOADER是什么
16:26:36 /:&D10.天地弦()
TDLLLoader是装入DLL的基类
16:26:52 /:&D10.天地弦()
TLoader是继承TDLLLoader
16:26:55 /:&D10.天地弦()
具体化工作
16:27:12 Chester()
我什么没有找到
16:27:14 /:&D10.天地弦()
好,继续回来看到
16:27:35 /:&D10.天地弦()
procedure TFMainForm.MuiBGroupClick(Sender: TObject);
  TsSheet: TTabS
  if BLoader.ModelServiceInts.ExecuteCmd(CMD_BEFORE_EXECUTE, 0, 0) = S_OK then
  begin
    TsSheet := TTabSheet.Create(self);
    TsSheet.PageControl := pgcM
    BLoader.ModelServiceInts.ExecuteCmd(CMD_CREATE_FORM, TsSheet.Handle, 0);
    AddFormInfo(TsSheet.Handle, 'B组窗体');
16:27:39 /:&D10.天地弦()
16:29:12 /:&D10.天地弦()
这个流程里这样的
16:31:19 /:&D10.天地弦()
告诉模块即将要做的动作
BLoader.ModelServiceInts.ExecuteCmd(CMD_BEFORE_EXECUTE, 0, 0)
主程序建立子窗体容器
TsSheet := TTabSheet.Create(self);
TsSheet.PageControl := pgcM
通知模块建立子窗体将放到主窗体建立的容器上
BLoader.ModelServiceInts.ExecuteCmd(CMD_CREATE_FORM, TsSheet.Handle, 0);
主窗体维护建立的窗体信息
16:32:09 /:&D10.天地弦()
上面说的,就是点击窗体要进行的工作
16:32:58 A3.武稀松()
InvokeFunc是一个函数指针类型
16:33:14 凡尘()
IModelInts
16:33:14 A3.武稀松()
InvokeFunc是一个函数指针类型 ,函数的返回值是IModelInts
16:33:23 凡尘()
哦.知道了.继续...
16:33:30 /:&D10.天地弦()
看看模块里是怎么样收到通知做出响应的
16:34:09 /:&D10.天地弦()
16:34:17 /:&D10.天地弦()
打开BGroupDLL.DLL中的dkIntsImp.pas
16:35:04 凡尘()
16:35:31 /:&D10.天地弦()
刚刚点击菜单第一个步骤
告诉模块即将要做的动作
BLoader.ModelServiceInts.ExecuteCmd(CMD_BEFORE_EXECUTE, 0, 0)
16:36:03 /:&D10.天地弦()
function TModelService.ExecuteCmd(CmdIndex, Param1,
  Param2: Integer): HR
  case CmdIndex of
    CMD_BEFORE_EXECUTE:
      begin
        if FDGroupForm = nil then result := S_OK else result := S_FALSE;
     
    CMD_CREATE_FORM:
      begin
        if FDGroupForm = nil then
        begin
          FDGroupForm := TFDGroupForm.Create(Application, Param1);
          FDGroupForm.S
       
        result := S_OK;
     
    CMD_CLOSE_FORM:
      begin
        if FDGroupForm && nil then
          if FDGroupForm.dkClose then
          begin
            FDGroupForm :=
            result := S_OK;
         
     
16:36:13 /:&D10.天地弦()
就执行到这里来
16:36:34 /:&D10.天地弦()
TModelService
16:36:42 /:&D10.天地弦()
这个类是模块的总部
16:36:50 /:&D10.天地弦()
进行指挥工作的
16:37:12 /:&D10.天地弦()
模块的大脑
16:37:36 A3.武稀松()
16:37:49 /:&D10.天地弦()
这些要做的动作,是通过第一个参数CmdIndex: I来得知的
16:38:27 /:&D10.天地弦()
这个方法,就像Windows的消息处理差不多
16:38:53 /:&D10.天地弦()
明了没有?
16:39:00 D12.阿凯()
16:39:03 /:&D10.天地弦()
没有反应了....
16:39:58 凡尘()
其实我像知道这个工程是怎么一步一步建立起来的.
16:40:10 /:&D10.天地弦()
点击菜单第一个步骤
告诉模块即将要做的动作
BLoader.ModelServiceInts.ExecuteCmd(CMD_BEFORE_EXECUTE, 0, 0) = S_OK
16:40:21 /:&D10.天地弦()
就是判断窗体有没有建立
16:40:37 /:&D10.天地弦()
大家可以看看代码就知道了
16:40:50 /:&D10.天地弦()
凡尘(:39:58
其实我像知道这个工程是怎么一步一步建立起来的
---------------
现在不是在说么
16:41:13 D12.阿凯()
我估计  人家问的你的这个编程思想啊
16:41:45 C9.随风飘()
我明白 凡尘 说的 
16:42:03 C9.随风飘()
他是想知道你是怎么把这些东西一步步建立起来的
16:42:13 Chester()
我也想知道
16:42:19 大羽()
比如你为啥创建窗体都用消息
16:42:21 B2.TCP INFO()
这里 uFDGroup
16:42:24 C9.随风飘()
运行的话  F4加断点就知道了
16:42:27 大羽()
不用别的方法
16:42:30 Chester()
什么BPG是怎样建的
16:42:34 大羽()
细节不说了
16:42:50 Chester()
里面也可以随便拉,是什么意思
16:43:00 D12.阿凯()
D10继续啊,还有没有啊  
16:43:19 KEN()
用其他方法也可以实现同样的功能,不用这么复杂,这样有什么好处
16:43:23 B2.TCP INFO()
你的 BGroupDll ,DGroupDll 是两个 TFDGroupForm
16:43:25 /:&D10.天地弦()
想想为什么都要通过单一一个接口来做所有的事呢
16:43:38 大羽()
16:43:48 /:&D10.天地弦()
16:43:49 /:&D10.天地弦()
16:43:53 大羽()
16:43:58 D12.阿凯()
扩展性好,是不是 ? 
16:44:08 大羽()
你的意思是 消息也是为了管理?
16:44:12 C9.随风飘()
那如果几个人同时用这个接口会咋样?
16:44:14 /:&D10.天地弦()
如果这样创建一个,那样创建一个,不是不好管理
16:44:28 大羽()
16:44:40 /:&D10.天地弦()
中间层也是这样做的
16:45:15 /:&D10.天地弦()
这样提供也主程序也只有一种接口,方便调用,方便统一管理,可以做成插件式的模块
16:45:18 大羽()
16:45:23 /:&D10.天地弦()
16:45:42 大羽()
你的程序都基于接口?
16:45:56 /:&D10.天地弦()
使用接口也比较多
16:46:04 /:&D10.天地弦()
特别是DLL输出
16:46:17 /:&D10.天地弦()
主要的服务都是通过接口来的
16:46:28 C9.随风飘()
我想知道多人同时用这个接口会咋样?会冲突吗?你用了什么处理机制没?
16:46:29 C9.随风飘()
16:46:26 /:&D10.天地弦()
这样便于扩充
16:46:54 /:&D10.天地弦()
客户端没有这种情况吧,C9
16:47:12 C9.随风飘()
是服务器端
16:47:19 凡尘()
HOHO.我知道怎么建立的了.
16:47:23 D12.阿凯()
这和多层开发思想一样啊 
16:47:31 /:&D10.天地弦()
已经讲过了
16:47:37 /:&D10.天地弦()
服务端,不是今天的内容
16:48:05 C9.随风飘()
哎  我都不没听过
16:48:14 C9.随风飘()
16:48:16 大羽()
16:48:22 C9.随风飘()
16:48:32 A3.武稀松()
D12.阿凯() 16:47:23
这和多层开发思想一样啊
-----------------------------
这本来就是啊
16:48:48 /:&D10.天地弦()
这个客户端还证明了,确实带包,可以共享对象
16:49:05 D12.阿凯()
对,就是的,哈哈,我还以为你们只讲包的用法呢 
16:49:11 C9.随风飘()
明白了  知道大概是怎么回事了
16:49:14 /:&D10.天地弦()
大家可以点击按钮得知
16:49:20 C9.随风飘()
不过要我自己做还差得远哈
16:49:40 /:&D10.天地弦()
两个模块里都没有创建dkSoftDM对象却都可以使用。
16:49:42 吕不为()
你把包删除,就会出错,证明了,
16:50:13 D12.阿凯()
包我很少用的,有时间应该试试 
16:50:43 大羽()
d10我今天听了一点,赶紧整理记录阿
16:52:53 大羽()
16:54:29 /:&D10.天地弦()
应该这个代码这样一讲都明白大概我的思路了。希望大家可以从中间学到一点东西
16:54:40 /:&D10.天地弦()
完了,完了,也没有什么了
---------------------------------------------------------------
---------------------------------------------------------------
16:54:41 大羽()
16:54:46 Chester()
下课了没有
16:54:48 凡尘()
不错了.不错了.
16:54:53 D12.阿凯()
哦,现在下课 
16:54:54 A3.武稀松()
不是差,是被我们问的发慌了.要是他镇定一点的话会好的多.
16:54:56 西门吹风㊣()
Dirk:不要这么直接啊
16:54:56 B2.TCP INFO()
D10,你的 TFDGroupForm 在DgroupDll,和BGroupDLL中是不是同一个类?
16:54:59 凡尘()
学到东西了.[:)]
16:55:07 /:&D10.天地弦()
B2.TCP INFO(:54:56
D10,你的 TFDGroupForm 在DgroupDll,和BGroupDLL中是不是同一个类? 
16:55:09 兰铃子()
想各位老师致敬
16:55:13 Chester()
凡尘:你知道怎样建了吗
16:55:16 dirk/:;()
呵呵,下次直接讲重点,不要理其他人的废话
16:55:17 /:&D10.天地弦()
不是同一个类
16:55:21 西门吹风㊣()
D10 讲课还凑合
16:55:24 /:&D10.天地弦()
只是我命名重复了
16:55:32 A3.武稀松()
16:55:39 /:&D10.天地弦()
16:55:43 爱你()
请问:我应如何在我的程序中实现类似Word中的自动化功能,也就是我想在Asp或Jsp中调用我的程序,并通过
我的程序接口和提供的参数实现对我的程序的访问和控制。 
16:55:44 B1.斜阳()
下次讲课一定要“咬定青山不放松”,只要不是方向上的错误,呵呵,老师就只管往下讲
16:55:57 /:&D10.天地弦()
16:55:59 B1.斜阳()
总会有人跟下来的
16:56:05 /:&D10.天地弦()
16:56:08 B2.TCP INFO()
      begin
        if FDGroupForm = nil then
        begin
          FDGroupForm := TFDGroupForm.Create(Application, Param1);
          FDGroupForm.S
       
        result := S_OK;
     
16:56:09 /:&D10.天地弦()
16:56:24 B1.斜阳()
其它跟不下来的,课后补[:D]
16:56:29 /:&D10.天地弦()
两个模块不是用同一个单元
16:56:31 大羽()
16:56:42 /:&D10.天地弦()
窗体可以不同
16:56:54 A3.武稀松()
有时间我给大家开课讲一下VCL构架和BASM的知识.
16:57:00 龙在天()
呵呵,谢谢
16:57:10 兰铃子()
师父~~~~~~~~~~
16:57:15 A3.武稀松()
16:57:16 /:&D10.天地弦()
源程序里创建子窗体在容器上,
16:57:28 吕不为()
其实,每个DLL中,不必引用基类窗体包的。
16:57:28 /:&D10.天地弦()
是个好方法,如果大伙需要那样做可以参考
16:57:29 B6.银狼()
武大,要快顶时间哦
16:57:57 /:&D10.天地弦()
[:D],3哥,你把inside vcl从头讲一片
16:58:00 A3.武稀松()
我最近在找工作.找到了就有时间.
16:58:03 兰铃子()
16:58:26 B6.银狼()
你应该在找前吧,要不工作了还有时间啊
16:58:28 A3.武稀松()
我要避开Inside VCL上的,不然没啥意义了
16:58:54 /:&D10.天地弦()
16:58:57 A3.武稀松()
我找到工作就把现在的工作辞了
16:59:08 A3.武稀松()
16:59:13 兰铃子()
16:59:19 D12.阿凯()
A3,讲讲DIRECTX 
16:59:21 B6.银狼()
呵呵,武大的脾气是最大了
16:59:22 /:&D10.天地弦()
我inside vcl差不多看完了,好像得到的东西不太多
16:59:25 D12.阿凯()
怎么样 ? 
16:59:37 兰铃子()
B6.银狼(:59:21
呵呵,武大的脾气是最大了 [:|]
16:59:45 大羽()
16:59:58 大羽()
a3,是懂得多
17:00:08 大羽()
好像脾气大而已
17:00:15 B6.银狼()
呵呵,他都受不了了,谁给我那么多,我想我还可以受一下了
17:00:27 D12.阿凯()
A3不啊,我怎么没有发现啊 
17:00:31 A3.武稀松()
我赚得不多啊
17:00:33 B1.斜阳()
刚刚跟踪VCL的代码。发现一线关于类和接口的一个问题,大家有兴趣否?
17:00:33 /:&D10.天地弦()
我懂得最少了,知道的都拿出来买了
17:00:43 /:&D10.天地弦()
17:00:47 /:&D10.天地弦()
17:00:55 A3.武稀松()
B1拿出来我们讨论啊,人都在
17:01:04 B6.银狼()
17:01:08 B1.斜阳()
大家都知道 TInterfacedObject 这个类吧
17:01:15 A3.武稀松()
17:01:18 B6.银狼()
EN  
17:01:22 大羽()
大家好像从不说 delphi使用接口的缺陷
17:01:24 /:&D10.天地弦()
17:01:29 /:&D10.天地弦()
17:01:43 B1.斜阳()
谁能告诉我,如果我创建了一个TInterfacedObject类型的实例,那么,Delphi为为这个实例分配了多少内存?
17:01:46 B2.TCP INFO()
17:02:33 /:&D10.天地弦()
17:02:42 A3.武稀松()
B1.斜阳() 17:01:43
谁能告诉我,如果我创建了一个TInterfacedObject类型的实例,那么,Delphi
为为这个实例分配了多少内存?
-------------------
看类函数:InstanceSize
17:03:03 B1.斜阳()
实际上分配的是12个字节
17:03:06 兰铃子()
课上完了?
17:03:58 B1.斜阳()
其中有4个字节是self,另外四个字节是FRefCount成员变量,那么剩下的4个字节干吗呢?
17:04:43 B1.斜阳()
呵呵,我就是突然对这4个字节感兴趣了,结果发现了个小秘密。
17:04:58 兰铃子()
17:05:05 A3.武稀松()
17:05:26 /:&D10.天地弦()
17:05:32 /:&D10.天地弦()
见不得光的?
17:05:33 C01.枫长舞()
卖关子了?
17:06:03 B1.斜阳()
在 TInterfacedObject 类型的实例中的最后四个字节,存放的居然是一个指向IInterface的指针
17:06:33 /:&D10.天地弦()
17:06:57 /:&D10.天地弦()
如果是两个接口,那应该就是16字节了
17:07:11 B1.斜阳()
换句话说,在定义类的时候,
TInterfacedObject = class(TObject, IInterface)
在class()的括号中,每列出一个接口,Delphi就会多分配出来4个字节存放这个接口对应的一个指针
17:07:57 A3.武稀松()
17:08:08 B6.银狼()
17:08:20 /:&D10.天地弦()
17:08:28 /:&D10.天地弦()
inside vcl上好像有说
17:08:32 兰铃子()
D10你笑什么
17:08:33 B1.斜阳()
安道理,通过self完全可以找到这些接口的TInterfaceTable,但是Delphi可能是为了性能的关系,牺牲了空间
,换取了效率
17:08:50 兰铃子()
哦~~~~~~~~~~~~~~~~~~~~~~``
17:08:54 /:&D10.天地弦()
17:08:54 B1.斜阳()
是吗?那本书没看完
17:09:24 /:&D10.天地弦()
我没有研究这么深[:L]
17:09:41 /:&D10.天地弦()
嗯,应该是牺牲了空间,换取了效率
17:09:44 A3.武稀松()
B1说的那些是不是因为vmtIntfTable所占得空间大了
17:10:28 B1.斜阳()
这可vmtIntfTable的空间没有什么关系,至少我还没有发现有直接的关系
17:10:35 A3.武稀松()
B1是说vmtIntfTable所有得接口在实例里面都有一个指针么
17:12:17 B1.斜阳()
因为在类中,是通过一个结构数组来记录类中实现了哪些接口,如果没有多出来的那个指针,那么在类中找到
一个接口的唯一方法就是:每次引用接口的时候都要到这个数组中从头到尾搜索一遍,这样很慢
17:13:06 B1.斜阳()
我的意思是说,凡事被列到class()中的接口,都会在类的实例中保留一个指针
17:13:23 B1.斜阳()
包括在祖先类中列出的接口
17:14:23 A1.笑熬糨糊(2282902)
有可能,一个个试一下。
17:14:34 A3.武稀松()
我刚才写代码试验了一下.好像确实如B1所说得
17:14:39 B1.斜阳()
TInterfacedObject = class(TObject, IInterface)
会在TInterfacedObject实例中多出4个字节
TTest = class(TInterfacedObject, ITest)
会在TTest类型的实例中多出8个字节而不是4个
17:14:45 A3.武稀松()
17:15:09 A1.笑熬糨糊(2282902)
试一试 TTest=class(TInterfacedObject,IIF1,IIF2,IIF3,IIF4)
17:15:11 A3.武稀松()
可能是vmtIntfTable中所有的接口在实例里面都有一个指针
17:15:40 B1.斜阳()
而且,越靠近根类中列出的接口,其在实例中的指针的位置就越靠前
17:15:52 A3.武稀松()
这个是肯定的
17:16:27 B1.斜阳()
并且,这些指针总是在实例所占用的内存的最后面
17:17:10 A3.武稀松()
按照正常思维,绑定的接口开始不能确定,所以这些指针应该在最后面.
17:17:12 B1.斜阳()
呵呵,这就给我们一个机会,让我们能偷偷地从一个实例中快速拿出我们想要的接口,呵呵
17:17:39 A3.武稀松()
17:17:59 A3.武稀松()
就是读取最后面的指针
17:19:06 B1.斜阳()
17:19:44 B1.斜阳()
如果一个类中实现的接口你事先知道,那么,就可以直接取到指针,然后强制类型转换
17:19:44 A3.武稀松()
不保险啊.万一Borland变了方式,我们就死定了[:D]
17:21:07 A3.武稀松()
就像现在Delphi.NET里面Char=WideChar.如果原来直接用长度1表示Char的长度的代码就有问题了.而SizeOf取
的就没问题一样.
17:21:53 B1.斜阳()
我只是偶尔发现Delphi实际分配的内存大小和我原来想的不一样,因此就查查看到底为啥,结果就发现了这个
,至于如何利用,现在还只是个初级阶段[:D]
17:22:32 兰铃子()
17:22:38 A1.笑熬糨糊(2282902)
B1原来是在偷东西。[:D]
17:22:48 /:&D10.天地弦()
17:22:51 A3.武稀松()
现阶段应该是可以利用的
17:23:05 B2.TCP INFO()
17:23:24 /:&D10.天地弦()
最后四个字节是指定接口的地址?
17:23:34 /:&D10.天地弦()
我想没有必要
17:23:53 /:&D10.天地弦()
borland提供的方法也可以取到!
17:24:03 /:&D10.天地弦()
在实际系统中是不要使用的
17:24:34 B1.斜阳()
这个说法其实有点不太严密,不应该说是指向了接口,应该是一个方法表的入口
17:24:40 /:&D10.天地弦()
否则borland改了,就真亏大了[:D]
17:24:56 /:&D10.天地弦()
17:25:41 B1.斜阳()
其实直接利用这个指针倒是次要的,主要是他为我们展示了一种提高效率的方法,呵呵
17:25:48 A3.武稀松()
或者说把方法表加载到了实例的最后面的空间
17:26:43 兰铃子()
老大,可以问你一问题吗?
17:26:46 A3.武稀松()
更正:或者说把接口表加载到了实例的最后面的空间
17:27:01 B1.斜阳()
接口中,列举的都是方法,在接口中不可以包含变量
阅读(...) 评论() &

我要回帖

更多关于 求助大神这是什么歌 的文章

 

随机推荐