如何讓DBLookupComboBox能夠輸入,我的辦法是做一個組合的控件,在它的下方(當然也可以是上方)加一個小編輯框,我已經完成了代碼的80%,我是從TCustomControl繼承下來,在我的代碼後會有解釋我爲什麼要從這個類繼承,而不是從TWinControl繼承,請大家先看代碼:
.h File
//---------------------------------------------------------------------------
#ifndef KingKingH
#define KingKingH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <dsgnintf.hpp>
#include <db.hpp>
//---------------------------------------------------------------------------
class PACKAGE TKingKing : public TCustomControl
{
private:
TDBLookupComboBox *FLookup;
TEdit *FEdit;
TDataSource *FDataSource;
TDataSource *FListSource;
AnsiString FListField;
AnsiString FKeyField;
AnsiString FDataField;
int FBaudRate;
protected:
virtual void __fastcall Paint();
virtual __fastcall ~TKingKing();
virtual void __fastcall CreateWnd();
public:
__fastcall TKingKing(TComponent* Owner);
void __fastcall SetDataSource(TDataSource *DataSource);
void __fastcall SetListSource(TDataSource *DataSource);
void __fastcall SetKeyField(AnsiString Field);
void __fastcall SetDataField(AnsiString Field);
void __fastcall SetListField(AnsiString Field);
void __fastcall SetBaudRate(int BaudRate);
void __fastcall DoMyJob(TObject *Sender,WORD &Key,TShiftState Shift);
__published:
__property TDataSource* DataSource={read=FDataSource,write=SetDataSource};
__property TDataSource *ListSource={read=FListSource,write=SetListSource};
__property AnsiString KeyField={read=FKeyField,write=SetKeyField};
__property AnsiString ListField={read=FListField,write=SetListField};
__property AnsiString DataField={read=FDataField,write=SetDataField};
__property int BaudRate={read=FBaudRate,write=SetBaudRate};
};
class TDataOfFieldProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
Proc("None");
TStrings *pList=new TStringList();;
TKingKing *pDCBX=dynamic_cast<TKingKing*>(GetComponent(0));
if(pDCBX)
{
if(pDCBX->DataSource)
{
TDataSet *pDataSet=pDCBX->DataSource->DataSet;
if(pDataSet)
{
pDataSet->GetFieldNames(pList);
for(int i=0;i<pList->Count;i++)
{
Proc(pList->Strings[i]);
}
}
}
}
delete pList;
}
};
//List Field
class TListOfFieldProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
Proc("None");
TStrings *pList=new TStringList();
TKingKing *pDCBX=dynamic_cast<TKingKing*>(GetComponent(0));
if(pDCBX)
{
if(pDCBX->ListSource)
{
TDataSet *pDataSet=pDCBX->ListSource->DataSet;
if(pDataSet)
{
pDataSet->GetFieldNames(pList);
for(int i=0;i<pList->Count;i++)
{
Proc(pList->Strings[i]);
}
}
}
}
delete pList;
}
};
//KeyField
class TKeyOfFieldProperty:public TStringProperty
{
public:
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
Proc("None");
TStrings *pList=new TStringList();
TKingKing *pDCBX=dynamic_cast<TKingKing*>(GetComponent(0));
if(pDCBX)
{
if(pDCBX->ListSource)
{
TDataSet *pDataSet=pDCBX->ListSource->DataSet;
if(pDataSet)
{
pDataSet->GetFieldNames(pList);
for(int i=0;i<pList->Count;i++)
{
Proc(pList->Strings[i]);
}
}
}
}
delete pList;
}
};
class TBaudRateProperty:public TIntegerProperty //Announcement:The property is only used to test.
{
TPropertyAttributes __fastcall GetAttributes()
{
return TPropertyAttributes()<<paValueList;
}
void __fastcall GetValues(TGetStrProc Proc)
{
Proc("9600");
Proc("14400");
Proc("28800");
Proc("57600");
}
};
//---------------------------------------------------------------------------
#endif
.cpp File
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "KingKing.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(TKingKing *)
{
new TKingKing(NULL);
}
//---------------------------------------------------------------------------
TTypeInfo *AnsiStringInfo()
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Kind=tkLString;
pTypeInfo->Name="AnsiString";
return pTypeInfo;
}
TTypeInfo *IntInfo()
{
TTypeInfo *pTypeInfo=new TTypeInfo;
pTypeInfo->Kind=tkInteger;
pTypeInfo->Name="Integer";
return pTypeInfo;
}
__fastcall TKingKing::TKingKing(TComponent* Owner)
: TCustomControl(Owner)
{
FLookup=new TDBLookupComboBox(this);
FEdit=new TEdit(this);
FEdit->OnKeyDown=DoMyJob;
Width = 150;
Height=46;
}
//---------------------------------------------------------------------------
void __fastcall TKingKing::CreateWnd()
{
TCustomControl::CreateWnd();
FLookup->DataSource=DataSource;
FLookup->ListSource=ListSource;
FLookup->DataField=DataField;
FLookup->ListField=ListField;
FLookup->KeyField=KeyField;
}
//----------------------------------------------------------------------------
void __fastcall TKingKing::DoMyJob(TObject *Sender,WORD &Key,TShiftState Shift)
{
if(Key==13)
{
FLookup->KeyField=FEdit->Text;
}
}
//-------------------------------------------------------------------------
void __fastcall TKingKing::Paint()
{
Width = 150;
Height=46;
FLookup->Parent=this;
FLookup->Left=0;
FLookup->Top=0;
FLookup->Width=145;
FLookup->Height=21;
FEdit->Parent=this;
FEdit->Left=0;
FEdit->Top=FLookup->Height;
FEdit->Width=80;
FEdit->Height=21;
}
void __fastcall TKingKing::SetDataSource(TDataSource *DataSource)
{
FDataSource=DataSource;
}
//--------------------------------------------------------------------------
void __fastcall TKingKing::SetListSource(TDataSource *DataSource)
{
FListSource=DataSource;
}
//--------------------------------------------------------------------------
void __fastcall TKingKing::SetKeyField(AnsiString Field)
{
FKeyField=Field;
}
void __fastcall TKingKing::SetListField(AnsiString Field)
{
FListField=Field;
}
void __fastcall TKingKing::SetDataField(AnsiString Field)
{
FDataField=Field;
}
void __fastcall TKingKing::SetBaudRate(int BaudRate)
{
FBaudRate=BaudRate;
}
__fastcall TKingKing::~TKingKing()
{
if(FLookup)
{
delete FLookup;
}
if(FEdit)
{
delete FEdit;
}
}
namespace Kingking
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TKingKing)};
RegisterPropertyEditor(AnsiStringInfo(),__classid(TKingKing),"DataField",__classid(TDataOfFieldProperty));
RegisterPropertyEditor(AnsiStringInfo(),__classid(TKingKing),"ListField",__classid(TListOfFieldProperty));
RegisterPropertyEditor(AnsiStringInfo(),__classid(TKingKing),"KeyField",__classid(TKeyOfFieldProperty));
RegisterPropertyEditor(IntInfo(),__classid(TKingKing),"BaudRate",__classid(TBaudRateProperty));
RegisterComponents("AKing", classes, 0);
}
}
//---------------------------------------------------------------------------
那爲什麼我不從TWinControl繼承,而從TCustomControl繼承,我從類的層次來看這個問題:
我對兩個組件進行比較發現:TDBLookupComboBox和TDBComboBox發現,首先它們的繼承的類層次不同,其中TDBComboBox的繼承層次有TCustomComboBox(而這個類是TComboBox的父類),而TDBLookupComboBox的最直接父類就是TCustomControl,這恰恰證明TDBLookupComboBox是放在Paint函數中被畫出來的。而我的錯誤代碼是從TWinControl繼承下來的,而父類爲TWinControl控件的最大特點就是自已能夠畫出自已,而TCustomControl則需要自已畫自已(用Paint方法),據此可以判斷TDBLookupComboBox爲什麼在設計期間就已經有了句柄的理由就是在從TCustomControl繼承的過程序,TDBLookupComboBox不僅重載了Paint方法,還重載了CreateWnd方法。而如果你從TWinControl繼承,再動態生成一個TDBLookupComboBox就會出現錯誤提示”該控件沒有父窗口“。
我的代碼基本上已經完成,唯一的一部分就是編輯框的OnKeyDown中的代碼,你可自已根據需要來完成。