VCL组件开发实例

上传人:d**** 文档编号:133656502 上传时间:2022-08-10 格式:DOCX 页数:19 大小:139.78KB
收藏 版权申诉 举报 下载
VCL组件开发实例_第1页
第1页 / 共19页
VCL组件开发实例_第2页
第2页 / 共19页
VCL组件开发实例_第3页
第3页 / 共19页
资源描述:

《VCL组件开发实例》由会员分享,可在线阅读,更多相关《VCL组件开发实例(19页珍藏版)》请在装配图网上搜索。

1、通过实例看 VCL 组件开发全过程这篇文章算是对我前段时间学习的一个学习总结,以及对自己学习过程的一个回顾。本 文通过一个简单的例子来尽可能的展示 VCL 组件开发的各个方面,本文针对即将学习组件 开发的初学者,如果你已经熟悉组件开发或认为本文内容过于基础简单,那么本文对你毫无 用处。阅读本文,假设你已经熟悉delphi的普通程序设计以及vcl的结构层次,还有一些重 要的关键字:published、property等。(注:本文内容建立在delphi5.0及以上版本)在这篇文章中我们将建立一个和时间有关的组件,这个组件通过设置它的不同状态有以 下基本功能: 1、显示系统的当前时间(包括设置闹钟

2、)。 2、跑表。 3、倒计时。这是一个简 单的例子,然而我们将在这个例子中尽可能多的用到delphi在组件开发中的多种特性,你可 以通过以下列举出的本文涉及特性有选择的阅读:组件和组件包组件的属性类别组件的属性编辑器组件编辑器一、组件和组件包,以及一些你应该知道的文件类型:组件和组件包的关系就如同普通工程中 unit 和工程文件的关系一样,通常你所安装的 组件都是以组件包的形式发布的,一个组件包中可以有很多个组件,在组件开发中,组件包 就是项目的工程文件为了开始开发我们的组件(我们把他叫做TClock)并将它包括在我们 自己的组件包(ClockPackage)中,我们选择FileTnewoth

3、er在弹出的窗口中的New页选 择Package新建一个组件包,得到一个组件包窗口,查看这个组件包的原文件(.dpk),得 到以下代码:package ClockPackage;$R *.res$ALIGN 8$ASSERTIONS ON$DESCRIPTION Our Clock Pack$IMPLICITBUILD OFFrequiresrtl;end.这个文件其实就是组件开发中的工程文件,requires关键字指示了组件包所需组件包的 列表,随着向组件包中加入组件(类似于单元文件),你还会看到contains关键字,指示了 组件包所包含的组件,你可以通过组件包窗口中的add和remove

4、按纽来添加新的组件和删 除已有的组件。另外这个代码中所包含的大量的编译器开关大多都可以在组件包窗体上的 Options中设置。这里需要补充说明的是组件包的3种重要属性(都在Options中):Designtime Only、Runtime Only、Designtime and runtime (这 3 个词的意思有英语基础的朋友应该都知 道吧),对于大多数的组件包我们只要选择最后一个就可以了,然而有些组件包设计为只运 行时(这样你用这套组件开发的程序不能脱离组件而单独运行,组件包也不能被安装),有 些组件包被设计为只设计时(这将在后文有更详细的说明)。了解了组件和组件包,我们对组件开发中可能

5、出现的一些你没有见过的文件做一些说 明:dpk文件既组件包的原代码;bpl文件,组件包编译后的结果,在没有发布dpk的情况 下可以通过bpl来安装组件包到delphi(Project-OptionsPackagesadd); pas在这里就是 组件包中组件的原代码了; dcu 为 pas 编译后的结果,在你选择将组件包含进组件包时(contains关键字),你可以选择发布原代码或是不发布(dcu文件);dcp如果你将组件作为 运行时组件,连接器将使用该文件。二、开始开发组件:了解了上面的知识后,我们就可以开始开发组件了!在组件窗体中单击 add,选择 NewComponent 页,在第一个组合

6、框中选择我们的组件将要继承自哪个类(通常新的组件是 通过继承已有的组件来开发的),由于这个组件的主要作用是要显示时间、跑表、倒计时种 的文字信息,所以我们选择继承自TCustomLabel (由于我们并不需要Tlabel的全部功能, 我们选择了能够隐藏 Tlabel 属性并有选择的发布它的属性的 TcustomLabel 类)。接下来为我 们的新组件取一个名字Tclock,然后指定我们想把组件安装到哪一个页中,这里我们自己键 入一个 ClockAndTime 页,这将出现在 RegisterComponents 过程中(后面会详细说明),选 择好文件保存的路径后(最好把它和组件dpk包放在同一

7、目录)确认。这是组件包窗体中的 contains 下已经多了我们刚才建立的组件的文件,双击它开始编写代码。在代码中我们需要注意在interface部分的一个新的过程:procedure Register;(注意: delphi 规定 Register 的 R 必须大写,这是一个保留字),这个过程是作为每一个组件所必须 有的,它完成组件的注册,包括组件本身以及如属性编辑器等多种组件特性的注册): procedure Register;beginRegisterComponents(ClockAndTime, TClock);这个过程注册组件本身,注意到前面定义的ClockAndTime页了吗?/

8、这里在后面还会出现一些新的过程,包括注册组件的属性类别等等。end;在下一篇中我们将给出这个组件的全部原代码组件的代码由于假设你已经熟悉delphi开发(它和一般开发没什么不同),我们就直接 贴出来并加上适当的注释:unit Clock;interfaceusesSysUtils, Classes, Controls, StdCtrls,ExtCtrls;typeTState=(StClock,StRunClock,StBackClock);定义枚举类表示控件的3种状态:时钟、 跑表、倒计时钟TClock = class(TCustomLabel)privatefState:TState;fT

9、imer:TTimer;为什么使用这个组件作为我们组件的私有成员就不用说了吧RCD:array1.8 of integer;/跑表中的各个数位。fBeginTime:string;/倒计时时的开始时钟,之所以没用TTime类型是为了在后面演示 属性编辑器fWakeTime:string;/闹钟时间,出于和上面同样的理由fAllowWake:boolean;/是否开启闹钟功能fOnWakeUp:TNotifyEvent;/为了使组件更加完美,我们允许组件用户能够响应闹钟 到来时的时件fOnTimeUp:TNotifyEvent;/同上能够响应倒计时种完成时的事件,我们将发布这两 个事件funct

10、ion GetActive:boolean;/控制Timer是否工作以控制3种状态的钟是否工作 procedure SetActive(Value:boolean);procedure SetState(Value:TState);procedure SetBeginTime(Value:string);procedure SetWakeTime(Value:string);protectedprocedure WalkClock(sender:TObject);作为时钟时走种的事件procedure RunClock(sender:TObject); /跑表procedure BackClo

11、ck(sender:TObject); 倒计时publicconstructor Create(AOwner:TComponent);override;/ 完成一些初始化工作procedure ReSetRunClock; /跑表和倒计时都需要一个复位方法给组件使用者调用 procedure ReSetBackClock;publishedproperty State:TState read fState write SetState default StClock;/默 认为时钟状态property Active:boolean read GetActive write SetActive;

12、/控制 3 种状态的钟是否工作property BeginTime:string read fBeginTime write SetBeginTime;property WakeTime:string read fWakeTime write SetWakeTime; property AllowWake:boolean read fAllowWake write fAllowWake; property OnWakeUp:TNotifyEvent read fOnWakeUp write fOnWakeUp; property OnTimeUp:TNotifyEvent read fOnTi

13、meUp write fOnTimeUp; /最后我们再发布一些被 TCustomLabel 所隐藏而我们又需要的属性 property Align;property Alignment;property Color;property Font;property ParentColor;property ParentFont;property ParentShowHint;property PopupMenu;property ShowHint;property Visible;property Transparent;property OnClick;end;procedure Regist

14、er;implementationprocedure Register;beginRegisterComponents(ClockAndTime, TClock);end; TClock constructor TClock.Create(AOwner: TComponent);begininherited Create(AOwner);/设置默认值fTimer:=TTimer.Create(self);/将它属于我们的组件,这样便不用编写析构函数,而可以自动在释放本组件时释放 TimerActive:=false;AllowWake:=false;State:=StClock;BeginTi

15、me:=00:00:00;WakeTime:=00:00:00;end;function TClock.GetActive: boolean;beginresult:=fTimer.Enabled;end;procedure TClock.SetActive(Value: boolean);beginfTimer.Enabled:=Value;end;procedure TClock.SetState(Value: TState);vari:integer;begincase Value ofStClock:beginActive:=false;fTimer.Interval:=1000;fT

16、imer.OnTimer:=WalkClock;Active:=true;end;StRunClock:/由于Time类型不好处理微秒操作,我们只有手工模仿这个操作,代码会稍微烦琐beginActive:=false;for i:=1 to 8 do RCDi:=0;Caption:=IntToStr(RCD8)+IntToStr(RCD7)+:+IntToStr(RCD6)+IntToStr(RCD5)+:+IntT oStr(RCD4);Caption:=Caption+IntToStr(RCD3)+:+IntToStr(RCD2)+IntToStr(RCD1);fTimer.Interv

17、al:=10;/经过测试,这个秒表的效果很好,然而这只是一个技术上的演示,实际上这么频繁(1/100秒)的不断执行RunClock会使CPU的占用一直达到100%/这并不是一个好注意。事实上要想在跑表中显示微秒级别并做到合理的占用 CPU/这需要更加灵活和复杂的编程fTimer.OnTimer:=RunClock;end;StBackClock:beginActive:=false;Caption:=BeginTime;fTimer.Interval:=1000;fTimer.OnTimer:=BackClock;end;end;fState:=Value;procedure TClock.S

18、etBeginTime(Value: string); begintryStrToTime(Value);fBeginTime:=Value;if State=StBackClock thenbeginActive:=false;Caption:=Value;end;excepton Exception dobeginfBeginTime:=00:00:00;if State=StBackClock then Caption:=00:00:00; end;end;end;procedure TClock.SetWakeTime(Value: string); begintryStrToTime

19、(Value);fWakeTime:=Value;excepton Exception dobeginfWakeTime:=00:00:00;end;end;procedure TClock.WalkClock(sender: TObject);beginCaption:=TimeToStr(Time);if AllowWake and (StrToTime(Caption)=StrToTime(WakeTime) thenbeginBeep;/蜂鸣器if Assigned(fOnWakeUp) then fOnWakeUp(self);end;end;procedure TClock.Run

20、Clock(sender: TObject);beginRCD1:=RCD1+1;if RCD1=10 then begin RCD2:=RCD2+1;RCD1:=0; end;if RCD2=10 then begin RCD3:=RCD3+1;RCD2:=0; end;if RCD3=10 then begin RCD4:=RCD4+1;RCD3:=0; end;if RCD4=6 then begin RCD5:=RCD5+1;RCD4:=0; end;if RCD5=10 then begin RCD6:=RCD6+1;RCD5:=0; end;if RCD6=6 then begin

21、 RCD7:=RCD7+1;RCD6:=0; end;if RCD7=10 then begin RCD8:=RCD8+1;RCD7:=0; end;if RCD8=10 then RCD8:=0; /我们的跑表最多可计 99 个小时;Caption:=IntToStr(RCD8)+IntToStr(RCD7)+:+IntToStr(RCD6)+IntToStr(RCD5)+:+IntT oStr(RCD4);Caption:=Caption+IntToStr(RCD3)+:+IntToStr(RCD2)+IntToStr(RCD1);天之类的时间倒计时procedure TClock.Bac

22、kClock(sender: TObject);/ 可以在beginif StrToTime(Caption)StrToTime(00:00:00) thenCaption:=TimeToStr(StrToTime(Caption)-0.00001) elsebeginActive:=false;Beep;if Assigned(fOnTimeUp) thenfOnTimeUp(self);end;end;procedure TClock.ReSetBackClock;vari:integer;beginif State=StRunClock thenbeginActive:=false;fo

23、r i:=1 to 8 do RCDi:=0;Caption:=00:00:00:00;end;end;procedure TClock.ReSetRunClock;beginif State=StBackClock thenbeginActive:=false;Caption:=BeginTime;end;end;end.为了测试我们的组件,现在你就可以安装这个组件包并建立一个应用测试它了,点击 组件包窗体中的 install 即可(注意:一但你安装了组件包,当你想对组件修改时,在修改了 原代码以后只用点击组件窗体的 compile 就可以了更新组件了),这时 delphi 的组件页的最 后

24、多出了我们定义的页,其中有了我们的组件!然而这个组件到目前为止仍然不够完善,还不能正式发布给用户,在下一篇中我们将 解决两个重要的问题:1、给我们的组件添加一个默认的图标。2、将这个组件杂乱的属性归 类。三、添加组件图标、注册组件的属性类别: 在前面的文章中我们已经完成了组件的基本功能的开发。但是遗憾的是一但你安装了 组件包,你会发现组件显示在 delphi 组件页中的图标并不能清楚的说明我们组件的功能(由 于我们的组件继承自TcustomLabel,图标是一个默认的delphiVCL的图标,如果组件继承自 其它已经出现在组件面板中的组件,图标还会和已有组件一样!)。显然一个好的组件特别是 一

25、个要发布的商业化组件需要一个有自己特色的目标,下面我们便来完成这一工作:打开 delphi 自带的 Image Editor ( ToolsImage Editor ),新建一个组件资源(filenewComponent Resource File (.dcr),在弹出的窗 口中右键单击 new 新建一个 bitmap位图资源调整好位图的大小(我们用24*24)和色深后确定,双击建立好的位图名字 还是做图(做图工具的使用基本和windows自带的画图程序差不多,这里略过),完成后我 们需要为位图文件另取一个名字(右键点击bitmap),因为delphi强制要求这个位图的名字 要和组件的名字一样

26、,并且要全部大写,这里我们就取为:TCLOCK。最后保存这个资源文 件到我们的组件包(dpk文件)目录,命名为ClockDcr.dcr。最后在Clock的代码中的interface 部分加入一个编译器开关:$R ClockDcr.dcr然后重新编译更新组件(还记得怎么更新 吗?),这时的组件图标已经变成我们刚才做的位图了!接下来我们将为我们开发的组件的属性进行分类并介绍一个组件开发中重要的特性: 属性类别。为了让我们组件的一些和时钟有关的属性注册成一个新的类别把它们和 label 的属性 分开开来,让组件用户能够更容易的发现组件的新特性,我们继承了属性类别的基类 TpropertyCatego

27、ry (在delphi5中这需要引用单元DsgnIntf,不过应该特别注意在delphi7中 已经没有了这个基类, 也没有这个单元文件,注册新的属性类别可以通过直接使用 RegisterPropertyInCategory 这种简单的办法完成,在下面的代码中会在相应的地方同时给出 两种方法并说明他们的不同。并覆盖它的两个类方法,最后在Regis ter过程中用 RegisterPropertyInCategory (在 delphi5 中在 DsgnIntf 单元,在 delphi7 中在 DesignIntf 单元, 注意:delphi的一些单元并没有被安装,包括我们这里指出的这两个单元和将

28、要在后文中指 出的单元,这些单元属于delphi的open tools api是用来方便我们,特别是组件开发者用来 扩展delphi。如果你的delphi没有这些单元,请将delphi安装目录下的source文件夹里 ToolsAPI文件夹中的pas文件拷贝到lib目录下,在你第一个需要用到这些单元的程序编译 时delphi会自动编译这些单元)方法注册属性类别。我们把以下的部分代码补充进我们开发 的组件的原代码中:usesDesignIntf;/delphi7/delphi5 用 DsgnIntf/这部分代码如果是delphi7就不需要了/typeTClockGategory=class(Tp

29、ropertyCategory) 建立一个新的属性类别Class function Name:string;override;属性类别的名称Class function Description:string;override;/属 性类别的描述End;Class function TClockGategory .Name:string;BeginResult:=ClockProEnd;Class function TClockGategory . Description:string;BeginResult:=Our Component Clock Description;End;/接下来我们

30、要做的就是修改registe过程:procedure Register;beginRegisterComponents(ClockAndTime, TClock);/这是 delphi7 的代码/RegisterPropertyInCategory(ClockPro,TClock,State);RegisterPropertyInCategory(ClockPro,TClock,Active);RegisterPropertyInCategory(ClockPro,TClock,BeginTime);RegisterPropertyInCategory(ClockPro,TClock,Wake

31、Time);RegisterPropertyInCategory(ClockPro,TClock,AllowWake);RegisterPropertyInCategory(ClockPro,TClock,OnWakeUp);RegisterPropertyInCategory(ClockPro,TClock,OnTimeUp);/这是 delphi5 的代码/RegisterPropertyInCategory(TClockGategory,TClock,State);RegisterPropertyInCategory(TClockGategory,TClock,Active);Regis

32、terPropertyInCategory(TClockGategory,TClock,BeginTime);RegisterPropertyInCategory(TClockGategory,TClock,WakeTime);RegisterPropertyInCategory(TClockGategory,TClock,AllowWake);RegisterPropertyInCategory(TClockGategory,TClock,OnWakeUp);RegisterPropertyInCategory(TClockGategory,TClock,OnTimeUp);/end;重新编

33、译后,做一个测试程序,这时只要组件使用者右键单击 Object Inspector 选择Arrange By Category 就可以看到属性已经被清楚的分类了,如下图:然而,应该清楚的是属性类别绝对不能被滥用,因为过多的使用该技术会使组件使用者为了找到某一个属性变的更加麻烦和摸不着头脑。在接下来的文章里,我们将继续研究两个很有用的组件特性四、组件属性编辑器和组件编辑器:通过上面的努力我们的组件似乎已经比较完美了,可我们也忽略了一些重要的细节和一些有趣的事情,这 一篇我们将研究两个很有用的组件特性:在之前开发组件核心功能时我们曾设置了两个属性BeginTime和WakeTime他们都是字符串型

34、的属性,然而他们所要表示的却是时间类型,这样就很有可能使组件使用者错误 的编辑属性并导致转化字符串到时间时出错(当然这里只是为了文章的讲解,我们故意把它 设置为了字符串类型),虽然通过浏览原代码你知道我们也做了一些代码级别的防出错处理, 使当输入错误时属性自动变成00:00:00,然而这对组件使用者来讲仍然显的很不友好, 所以我们需要为这两个属性定制编辑器,我们的编辑器将弹出一个窗口里面有一个TdateTimePicker用来选择时间。在delphi中有许多这样的例子,例如大家都知道的lines属 性,当你单击它右放的省略号时为自动弹出一个文本编辑器来编辑lines,这大大降低了组 件使用者范

35、错误的可能性。在定制完属性编辑器以后,我们将为组件本身加入一写有趣的元素组件编辑器,这也是在delphi中经常出现的,例如有些组件当你双击它时,它并不会进入代码编写状态, 而是弹出它自己的编辑器。虽然我们的组件似乎并不需要这种特性,但为了演示它,我们也 将它考虑近来,我们给我们的组件编写了一个版权信息和一个关于对话框,当组件使用者双 击它时弹出关于信息(当然,这仅仅是种演示)。上面提到的两种特性由于它们只是会在设 计时起作用,所以你完全可以在新的组件包中编写并注册它们,并将这个组件包设置为 Designtime Only,为了方便起见我们就直接把它们和组件的单元编写在一起。注意:以下出 现的一

36、些类和方法都需要引用单元DesignEditors (delphi7)或DsgnIntf (delphi5),与前面 说的一样,它们都属于delphi的open tools api所以,如果你没有这写单元请按照前文的方 法安装它们。首先来编写属性编辑器,由于BeginTime和WakeTime是字符串类型,所以我们必须 从默认的字符串属性编辑器类 TstringProperty 继承并覆盖它的一写方法(这里只介绍几个重 要的方法,事实上所有的属性编辑器都从TpropertyEditor继承而来,然而我们不用直接继承 这个基类)。其中一个重要的方法是GetAttributes,他将返回一些代表编

37、辑器功能的值,这 些值将会在代码的注释中说明(如果你的属性编辑器还需要一个下拉列表,你还需要另外一 个重要的方法GetVilues具体请查看delphi帮助)另外为了使属性编辑器为弹出的对话框我 们需要覆盖Edit方法。为了可以以可视化的方式设计对话框,我们可以建立一个普通工程, 在设计好后将窗体的类声明复制到我们的组件单元,并将窗体的 dfm 文件拷贝到我们的组 件包目录,并在代码中加入编译器开关$R *.dfm。以下是窗体的类声明,这个窗体没有任 何的代码需要编写:TTimeEditFrm = class(TForm)DateTimePicker1: TDateTimePicker;But

38、ton1: TButton;Button2: TButton;private Private declarations public Public declarations end;以下是属性编辑器的代码:TClockProperty=class(TStringProperty)publicfunction GetAttributes:TPropertyAttributes;override;procedure Edit;override;end;实现部分:procedure TClockProperty.Edit;varTimeEditFrm:TTimeEditFrm;beginTimeEd

39、itFrm:=TTimeEditFrm.Create(Application);tryTimeEditFrm.DateTimePicker1.Time:=StrToTime(GetValue);if TimeEditFrm.ShowModal=mrOK then SetValue(TimeToStr(TimeEditFrm.DateTimePicker1.Time);/GetValue 和 SetValue 是 TStringProperty 的基类方法,他直接读取和设置字符串的 值finallyTimeEditFrm.Free;end;end;function TClockProperty.

40、GetAttributes: TPropertyAttributes;beginresult:=paDialog,paMultiselect;/paDialog表示属性编辑器将显示一个对话框,paMulitiselect允许多个组件选择属性 /除此之外如果你想让属性编辑器显示下拉列表,你还需要 paValueList 具体请查看 帮助end;最后我们用 RegisterPropertyEditor 方法注册属性编辑器:procedure Register;beginRegisterPropertyEditor(TypeInfo(string),TClock,BeginTime,TClockPr

41、operty);RegisterPropertyEditor(TypeInfo(string),TClock,WakeTime,TClockProperty); end; 重新编译更新组件后我们就可以测试了,可以看到组件编辑器工作的很好:接下来我们来实现组件编辑器:组件编辑器需要继承TcomponentEditor并覆盖一些重要的方法,GetVbrbCount返回设计 时组件右键自定义菜单的数目,GetVerb为每一个自定义菜单添加文字,ExecuteVerb为每一 个菜单项添加事件, Edit 为组件的缺省操作指定事件(即在设计时双击组件),以下是代码:TClockEditor=class(

42、TComponentEditor)publicfunction GetVerbCount:integer;override;function GetVerb(index:integer):string;override;procedure ExecuteVerb(index:integer);override;procedure Edit;override;end;实现部分:procedure TClockEditor.Edit;beginExecuteVerb(1); / 默认显示关于end;procedure TClockEditor.ExecuteVerb(index: integer)

43、;begincase index of/第一个显示名字的菜单什么都不做显示 1:showmessage(hk.barton2003);end;end;function TClockEditor.GetVerb(index: integer): string; begincase index of0:result:=hk.barton;1:result:=About Clock;end;end;function TClockEditor.GetVerbCount: integer;beginresult:=2;/我们显示两条菜单,一个我的名字,一个关于 end;同样最后我们注册组件编辑器:procedure Register;beginRegisterComponentEditor(TClock,TClockEditor); end;同样可以看到组件编辑器的测试情况:文章写到这里也该结束了,虽然写了那么多,然而在组件开发中这仍是一小部分内容 本文只是抛砖引玉的作用,希望对正要进入组件开发的朋友一些启示。为了方便你阅读本文 如果你想要本文所开发的这个组件的全部原文件,请和我联系:E-mail:hk.barton hekphiQQ:6813489(全文完)

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!