TGridDrawState名字空间冲突问题及解决方法

2008-02-23 05:34:19来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

 相信大家碰到过很多类似这样的问题,用了某些第三方组件后,编译时提示:
E2015 Ambiguity between 'TGridDrawState' and 'Gridseh::TGridDrawState'

E2015 Ambiguity between 'TGridDrawState' and 'Grids::TGridDrawState'
之类的,这是典型的名字空间冲突,ccrun(老妖)在CSDN也帮助解决过多次类似的问题,所以写这篇文档旨在于总结一下,希望能对后来者有帮助。文章是以TGridDrawState来说事,但是道理是相同的,适合VCL中其他的类型是。为了增加文章的字数并且为了显的本文章有力度,多加了一些废话在里面(ccrun是不是很有公务员的潜质呢? - -#)。

TGridDrawState是VCL中Grids单元定义的一个集合(Set)类型,常用在表格(Grid)的单元格(Cell)绘制中,原型如下:
enum Grids__3 { gdSelected, gdFocused, gdFixed };
typedef Set<Grids_3, gdSelected, gdFixed> TGridDrawState;

其中
gdSelected 表示单元格处于被选择状态
gdFocused 表示单元格正获得焦点
gdFixed 表示单元格是固定的(行或列头)

VCL中常用的Grid控件有: TStringGrid, TDrawGrid, TDBGrid,三者都继承自TCustomGrid,类关系如下:
TCustomGrid
/ \
TDrawGrid TCustomDBGrid
| |
TStringGrid TDBGrid

TCustomGrid提供了OnDrawCell的方法,使得我们能够自画单元格,原型如下:
virtual void __fastcall DrawCell(int ACol, int ARow, const TRect &ARect, Grids::TGridDrawState AState) = 0;

TDrawGrid和TStringGrid一直沿用了OnDrawCell这个方法,而TCustomDBGrid却走上另一条路,增加了OnDrawColumnCell和OnDrawDataCell方法,原型如下:
DYNAMIC void __fastcall DrawColumnCell(const Types::TRect &Rect, int DataCol, TColumn* Column, Grids::TGridDrawState State);

DYNAMIC void __fastcall DrawDataCell(const Types::TRect &Rect, Db::TField* Field,
Grids::TGridDrawState State);
分别对应绘制某列的单元格和单个的单元格。到了TDBGrid这一代的时候,干脆把OnDrawCell方法也隐藏了,嘿嘿,所以TCustomGrid的这两个孙子(TStringGrid和TDBGrid)的自画单元格事件是不太相同,就象表兄弟似的,看着有点相似,却又有很多不同。这三个自画函数的最后一个参数都是TGridDrawState,用来指示当前绘制单元格的状态。前面加Grids::是因为VCL中的TGridDrawState的名字空间(namespace)是Grids。
// 本文转自 C Builder 研究 - http://www.ccrun.com/article.asp?i=1003&d=15f173
这本来这是个和谐的局面,可是大家都知道C Builder和Delphi都支持在VCL基础上派生出来的第三方组件,这实在是个好功能,相当的好啊。您能够扩展已有的组件,写一个新的功能更强的或利用第三方现成的组件,加快工程的研发进度,美化界面,增强程式功能等等。但是,在方便的同时,也带来一些负作用:兼容性问题。先不说针对不同的IDE版本分别需要不同的组件包(bpl),就组件内部来讲,由于新组件的不断扩充,类,对象,方法,数据类型,名字空间也在不断的增多,所以有冲突是难免的。有了问题我们就着手解决,下面做个试验:
  首先安装Ehlib v4.14 Full Source版本,本站有下载(广告来的真及时哦):
  http://www.ccrun.com/view.asp?id=149
  新建一个工程,放置一个Ehlib组件中的DBGridEh和一个标准的组件DBGrid在窗体上
  分别双击DBGridEh和DBGrid的OnDrawDataCell事件,在IDE产生的两个函数体中分别加一行注释://,这是为了在测试编译时不至于因为函数体空着而被编译器自动消除了函数声明及定义部分。
  在工程属性中添加一下Ehlib的头文档路径:Project-->Options-->Directories/Conditionals-->Include path中,找到Ehlib的BCB6目录并添加进来。
  然后试着编译,弹出一个对话框,说很难找到组件的头文档:GridsEh,您会说,日,不是添加了Include path了吗?表着急的说,IDE在安装Ehlib组件时(源码版),生成的头文档是.hpp的,而在单元文档.h中声明的#include <xxx>却是.h的,所以会说很难找到头文档了。但是没有关系,点击查找头文档窗口的Broswer按钮,找到Ehlib\BCB6目录下的GridsEh.hpp,点击OK,恩,这一关算是过了,不关马上就又产生Error信息了,大名鼎鼎的E2015错误,也就是文章开头说的那个提示信息:两个类型不明确,因为编译器找到分别属于两个名字空间的相同类型的声明,但是在这里却不知道该用具体的哪一个。晕了吧。
  喝口茶,广告时间:欢迎光临 C Builder研究 - http://www.ccrun.com/
  这个时候很多朋友就该上网发帖子问或搜索解决方案了。有的朋友把三方组件的头文档中的有冲突的数据类型前全手工加上了名字空间,有的是把VCL自带的组件头文档中相关的数据类型前加了名字空间。但是ccrun不太建议用这样的方法。我的原则是尽量不修改IDE生成的头文档内容,注意是尽量而不是从来不,有的人喜欢抠字眼。除非是迫不得已。比如您用Pascal写了一个组件,组件响应MouseUp事件,于是添加一行 property OnMouseUp; 但是在书写时却写成了onMouseUp(小写的o),因为在Pascal中不区分大小写,在BCB中能够成功的编译和安装,但是在使用这个组件时就问题来了:编译器编译Pas文档,同时生成相应的.hpp文档,刚才的property OnMouseUp在.hpp中的声明就变成了:__property onMouseUp; 汗!Pascal文档的不区分大小写变成.cpp或.hpp以后就成了灾难了。这是一件很郁闷的事,因为C Builder不认识.hpp中的onMouseUp,只认识OnMouseUp。这时才不得不手工修改.hpp文档。扯远了扯远了。继续名字空间冲突的解决方案。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C 实例教学-基础知识(1)

下一篇: 函数指针(全局函数/类成员函数)和函数对象