{定义Field为一个String属性}type TFieldsProperty = class(TStringProperty) public procedure GetValues(Proc: TGetStrProc); override; function GetAttributes: TPropertyAttributes; override; end;...{ TFieldsProperty }procedure TFieldsProperty.GetValues(Proc: TGetStrProc); var Values: TStrings; begin Values := TStringList.Create; FYourDataSet.GetFieldNames(Values); for I := 0 to Values.Count - 1 do begin Proc(Values[I]); end; Values.Free; end;function TFieldsProperty.GetAttributes: TPropertyAttributes; begin Result := [paValueList,paSortList,paMultiSelect]; end;{注册} procedure Register; begin ... RegisterPropertyEditor(TypeInfo(String), TYourComponentClass, 'Field', TFieldsProperty); end;
//前提这两个类必须在一个pascal单元,因为你的DataSet为私有属性。//如果是c++builder,则必须publish你的DataSet。procedure TFieldsProperty.GetValues(Proc: TGetStrProc); var Values: TStrings; ADataSet: TDataSet; begin ADataSet := TYourComponent(GetComponent(0)).YourDataSet; Values := TStringList.Create; ADataSet.GetFieldNames(Values); for I := 0 to Values.Count - 1 do begin Proc(Values[I]); end; Values.Free; end;
第二个问题基本解决了。 关于第一个问题: To Borlandor: 但凡是从TStringProperty继承下来的属性编辑器好像都没有下拉列表框,你可以试试。
而且要实现GetAttributes,返回集合应包括paValueList。function TFieldsProperty.GetAttributes: TPropertyAttributes; begin Result := [paValueList,paSortList,paMultiSelect]; end;
}; //The following PropertyEditor is used by control to generate a listbox--Property:DataField class TDataFieldProperty:public TStringProperty { public: TPropertyAttributes __fastcall GetAttributes() { return TPropertyAttributes()<<paValueList<<paSortList; } void __fastcall GetValues(TGetStrProc Proc) { TDataSet *pDataSet; TDataComBox *pDCBX=dynamic_cast<TDataComBox*>(GetComponent(0)); if(pDCBX) { pDataSet=pDCBX->DataSource->DataSet; if(pDataSet) { for(int i=0;i<pDataSet->FieldCount;i++) { Proc(pDataSet->Fields->Fields[i]->FieldName); } } } } }; //The following PropertyEditor is used by control to generate a listbox------Property:BaudRate class TBaudRateProperty:public TIntegerProperty { public: TPropertyAttributes __fastcall GetAttributes() { return TPropertyAttributes()<<paValueList; } void __fastcall GetValues(TGetStrProc Proc) { Proc("9600"); Proc("14400"); Proc("28800"); Proc("32400"); Proc("57600"); } }; //The following PropertyEditor is used by control to generate a listbox-----Property:FileName class TFileNameProperty:public TStringProperty { public: TPropertyAttributes __fastcall GetAttributes() { return TPropertyAttributes()<<paDialog; } void __fastcall Edit() { TOpenDialog *O=new TOpenDialog(Application); O->Title="Kingcaiyao http://www.csdn.net"; O->InitialDir="c:\\"; O->FileName=GetValue(); if(O->Execute()) { Value=O->FileName; } delete O; } };//--------------------------------------------------------------------------- #endif .cpp File //---------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop#include "DataComBox.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // ValidCtrCheck is used to assure that the components created do not have // any pure virtual functions. //static inline void ValidCtrCheck(TDataComBox *) { new TDataComBox(NULL); } //--------------------------------------------------------------------------- __fastcall TDataComBox::TDataComBox(TComponent* Owner) : TComboBox(Owner) { } //--------------------------------------------------------------------------- TTypeInfo *AnsiStringInfo() //You know,the macro __typeinfo is only used to obtain typeinfo of vcl not common datatype,so we should use a function to achieve { TTypeInfo *pTypeInfo=new TTypeInfo; pTypeInfo->Name="AnsiString"; pTypeInfo->Kind=tkString; return pTypeInfo; } //--------------------------------------------------------------------------- TTypeInfo *IntInfo() { TTypeInfo *pTypeInfo=new TTypeInfo; pTypeInfo->Kind=tkInteger; pTypeInfo->Name="int"; return pTypeInfo; } //----------------------------The namespace is used by compiler to recoganize control with their name--------------- namespace Datacombox { void __fastcall PACKAGE Register() { TComponentClass classes[1] = {__classid(TDataComBox)}; RegisterComponents("AKing", classes, 0); RegisterPropertyEditor(IntInfo(),__classid(TDataComBox),"BaudRate",__classid(TBaudRateProperty)); RegisterPropertyEditor(AnsiStringInfo(),__classid(TDataComBox),"FileName",__classid(TFileNameProperty)); RegisterPropertyEditor(AnsiStringInfo(),__classid(TDataComBox),"DataField",__classid(TDataFieldProperty)); } } //--------------------------------------------------------------------------- void __fastcall TDataComBox::SetDataSource(TDataSource* DataSource) { FDataSource=DataSource; } //------------------------------------------------------- void __fastcall TDataComBox::SetDataField(AnsiString Field) { FDataField=Field; } //----------------------------------------------------- void __fastcall TDataComBox::SetBaudRate(int BaudRate) { FBaudRate=BaudRate; } //---------------------------------------------------- void __fastcall TDataComBox::SetFileName(AnsiString FileName) { FFileName=FileName; }
To borlandor: 看到我发给你的短消息了吗? 我反复检查了我的代码,但问题依然得不到解决,在object inspector中始终没有DataField属性的下拉列表框。
刚才查了一下:AnsiString的类型类别应该为tkLString//--------------------------------------------------------------------------- TTypeInfo *AnsiStringInfo() //You know,the macro __typeinfo is only used to obtain typeinfo of vcl not common datatype,so we should use a function to achieve { TTypeInfo *pTypeInfo=new TTypeInfo; pTypeInfo->Name="AnsiString"; pTypeInfo->Kind=tkLString;//tkString; return pTypeInfo; }这样也许就对了,不不过没有试过。
TFieldsProperty = class(TStringProperty)
public
procedure GetValues(Proc: TGetStrProc); override;
function GetAttributes: TPropertyAttributes; override;
end;...{ TFieldsProperty }procedure TFieldsProperty.GetValues(Proc: TGetStrProc);
var Values: TStrings;
begin
Values := TStringList.Create;
FYourDataSet.GetFieldNames(Values);
for I := 0 to Values.Count - 1 do
begin
Proc(Values[I]);
end;
Values.Free;
end;function TFieldsProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paValueList,paSortList,paMultiSelect];
end;{注册}
procedure Register;
begin
...
RegisterPropertyEditor(TypeInfo(String), TYourComponentClass, 'Field', TFieldsProperty);
end;
我写的是C++ BUILDER的代码,它们是两个不同的类,即是说控件类和属性编辑器类,而FYOURDATASET正好是关键之所在,它在控件类的private域中。说到底关键是我要知道如何在属性编辑器的类中得到当前的数据源?
我写的是C++ BUILDER的代码,它们是两个不同的类,即是说控件类和属性编辑器类,而FYOURDATASET正好是关键之所在,它在控件类的private域中。说到底关键是我要知道如何在属性编辑器的类中得到当前的数据源?
var Values: TStrings;
ADataSet: TDataSet;
begin
ADataSet := TYourComponent(GetComponent(0)).YourDataSet;
Values := TStringList.Create;
ADataSet.GetFieldNames(Values);
for I := 0 to Values.Count - 1 do
begin
Proc(Values[I]);
end;
Values.Free;
end;
关于第一个问题:
To Borlandor:
但凡是从TStringProperty继承下来的属性编辑器好像都没有下拉列表框,你可以试试。
property Field: String read FField write FField;注册时PropertyName必须为'Field':
RegisterPropertyEditor(TypeInfo(String), TYourComponentClass, 'Field', TFieldsProperty);
begin
Result := [paValueList,paSortList,paMultiSelect];
end;
//---------------------------------------------------------------------------#ifndef DataComBoxH
#define DataComBoxH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
#include <dsgnintf.hpp>
#include <db.hpp>
#include <forms.hpp>
#include <dialogs.hpp>//---------------------------------------------------------------------------class PACKAGE TDataComBox : public TComboBox
{
private:
TDataSource* FDataSource;
AnsiString FDataField;
int FBaudRate;
AnsiString FFileName;
protected:
public:
void __fastcall SetDataSource(TDataSource* DataSource);
void __fastcall SetDataField(AnsiString Field);
void __fastcall SetBaudRate(int BaudRate);
void __fastcall SetFileName(AnsiString FileName);
__fastcall TDataComBox(TComponent* Owner);
__published:
__property TDataSource* DataSource={read=FDataSource,write=SetDataSource};
__property AnsiString DataField={read=FDataField,write=SetDataField};
__property int BaudRate={read=FBaudRate,write=SetBaudRate,default=9600};
__property AnsiString FileName={read=FFileName,write=SetFileName};
};
//The following PropertyEditor is used by control to generate a listbox--Property:DataField
class TDataFieldProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList<<paSortList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
TDataSet *pDataSet;
TDataComBox *pDCBX=dynamic_cast<TDataComBox*>(GetComponent(0));
if(pDCBX)
{ pDataSet=pDCBX->DataSource->DataSet;
if(pDataSet)
{
for(int i=0;i<pDataSet->FieldCount;i++)
{
Proc(pDataSet->Fields->Fields[i]->FieldName);
}
}
}
}
};
//The following PropertyEditor is used by control to generate a listbox------Property:BaudRate
class TBaudRateProperty:public TIntegerProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
Proc("9600");
Proc("14400");
Proc("28800");
Proc("32400");
Proc("57600");
}
};
//The following PropertyEditor is used by control to generate a listbox-----Property:FileName
class TFileNameProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paDialog;
}
void __fastcall Edit()
{
TOpenDialog *O=new TOpenDialog(Application);
O->Title="Kingcaiyao http://www.csdn.net";
O->InitialDir="c:\\";
O->FileName=GetValue();
if(O->Execute())
{
Value=O->FileName;
}
delete O;
}
};//---------------------------------------------------------------------------
#endif
.cpp File
//---------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop#include "DataComBox.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//static inline void ValidCtrCheck(TDataComBox *)
{
new TDataComBox(NULL);
}
//---------------------------------------------------------------------------
__fastcall TDataComBox::TDataComBox(TComponent* Owner)
: TComboBox(Owner)
{
}
//---------------------------------------------------------------------------
TTypeInfo *AnsiStringInfo() //You know,the macro __typeinfo is only used to obtain typeinfo of vcl not common datatype,so we should use a function to achieve
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Name="AnsiString";
pTypeInfo->Kind=tkString;
return pTypeInfo;
}
//---------------------------------------------------------------------------
TTypeInfo *IntInfo()
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Kind=tkInteger;
pTypeInfo->Name="int";
return pTypeInfo;
}
//----------------------------The namespace is used by compiler to recoganize control with their name---------------
namespace Datacombox
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TDataComBox)};
RegisterComponents("AKing", classes, 0);
RegisterPropertyEditor(IntInfo(),__classid(TDataComBox),"BaudRate",__classid(TBaudRateProperty));
RegisterPropertyEditor(AnsiStringInfo(),__classid(TDataComBox),"FileName",__classid(TFileNameProperty));
RegisterPropertyEditor(AnsiStringInfo(),__classid(TDataComBox),"DataField",__classid(TDataFieldProperty)); }
}
//---------------------------------------------------------------------------
void __fastcall TDataComBox::SetDataSource(TDataSource* DataSource)
{
FDataSource=DataSource;
}
//-------------------------------------------------------
void __fastcall TDataComBox::SetDataField(AnsiString Field)
{
FDataField=Field;
}
//-----------------------------------------------------
void __fastcall TDataComBox::SetBaudRate(int BaudRate)
{
FBaudRate=BaudRate;
}
//----------------------------------------------------
void __fastcall TDataComBox::SetFileName(AnsiString FileName)
{
FFileName=FileName;
}
看到我发给你的短消息了吗?
我反复检查了我的代码,但问题依然得不到解决,在object inspector中始终没有DataField属性的下拉列表框。
TTypeInfo *GetTypeInfo(AnsiString s)
{
PPTypeInfo Temp; Temp = GetPropInfo(__typeinfo(TDataComBox), s)->PropType; return *Temp;}namespace Datacombox
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TDataComBox)};
RegisterComponents("AKing", classes, 0);
RegisterPropertyEditor(GetTypeInfo("BaudRate") ,__classid(TDataComBox),"BaudRate",__classid(TBaudRateProperty));
RegisterPropertyEditor(GetTypeInfo("FileName"),__classid(TDataComBox),"FileName",__classid(TFileNameProperty));
RegisterPropertyEditor(GetTypeInfo("DataField") ,__classid(TDataComBox),"DataField",__classid(TDataFieldProperty)); }
}
class TDataFieldProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList<<paSortList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
TStrings *Value;
TDataSet *pDataSet;
TDataComBox *pDCBX=dynamic_cast<TDataComBox*>(GetComponent(0));
if(pDCBX)
{
if(pDCBX->DataSource)
{
pDataSet=pDCBX->DataSource->DataSet;
if(pDataSet)
{
Value = new TStringList;
pDataSet->GetFieldNames(Value);
for(int i=0;i<Value->Count;i++)
{
Proc(Value->Strings[i]);
}
delete Value;
}
}
}
}
};
你调试通过了吗?
TTypeInfo *AnsiStringInfo()
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Kind=tkString;
pTypeInfo->Name="AnsiString";
}
我的整型编辑器是可以的----BaudRate属性是有下拉列表框的,莫非字符串必须是你所写的那样。
C++Builder作组件有点别扭,为什么不用Delphi呢?Delphi只要如此注册即可:
RegisterPropertyEditor(TypeInfo(String), TYourComponent, 'Field', TFieldsProperty);
TTypeInfo *AnsiStringInfo() //You know,the macro __typeinfo is only used to obtain typeinfo of vcl not common datatype,so we should use a function to achieve
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Name="AnsiString";
pTypeInfo->Kind=tkLString;//tkString;
return pTypeInfo;
}这样也许就对了,不不过没有试过。
马上给分.