我有连接到DBCombobox
的CsOwnerDrawFixed
样式。
有时在Tstringfield
中不存在数据库Strufield内容(因为用户在单独进程中出错),dbcombobox.Items
控件没有显示任何内容。如何在dbcombobox
上将此数据显示为文本?
procedure TForm1.DBComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
with DBComboBox1.Canvas do
begin
if odselected in State then
Brush.Color:= $00D68759
else
Brush.Color:= $00FEECDD;
FillRect(rect);
TextOut(30, Rect.Top, DBComboBox1.Items[Index]);
Pen.Color := clwhite;
Brush.Style:= bsClear;
TextOut(Rect.Left + 4, Rect.Top, UpCase(DBComboBox1.Items[Index][1]));
Rectangle(Rect.Left + 1, Rect.Top + 1, Rect.Left +20, Rect.Top + DBComboBox1.ItemHeight-2);
end;
end;
最佳答案
我分两步来做。使用此功能创建Combobox
后,我从操纵组合框继承了DBCombobox
。
这是一个简单的组合框测试。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DBCtrls;
type
TManipulatecombobox= class(stdctrls.TCombobox)
private
Ftext: string;
FOnDrawItem: TDrawItemEvent;
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure Settext(Avalue: string);
protected
procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); reintroduce; virtual;
property OnDrawItem: TDrawItemEvent read FOnDrawItem write FOnDrawItem;
public
property text: string read Ftext write Settext;
end;
TForm1 = class(TForm)
Edit1: TEdit;
DBComboBox1: TDBComboBox;
procedure FormCreate(Sender: TObject);
procedure Edit1Change(Sender: TObject);
private
Combo: TManipulatecombobox;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TManipulatecombobox.CNDrawItem(var Message: TWMDrawItem);
var
State: TOwnerDrawState;
begin
with Message.DrawItemStruct^ do
begin
State := TOwnerDrawState(LongRec(itemState).Lo);
if itemState and ODS_COMBOBOXEDIT <> 0 then
Include(State, odComboBoxEdit);
if itemState and ODS_DEFAULT <> 0 then
Include(State, odDefault);
Canvas.Handle := hDC;
Canvas.Font := Font;
Canvas.Brush := Brush;
if (Integer(itemID) >= 0) and (odSelected in State) then
begin
Canvas.Brush.Color := clHighlight;
Canvas.Font.Color := clHighlightText
end;
if Integer(itemID) >= 0 then
DrawItem(itemID, rcItem, State) else
if (Integer(itemID) = -1) and (odComboBoxEdit in State) then
DrawItem(itemID, rcItem, State)
else
Canvas.FillRect(rcItem);
if odFocused in State then DrawFocusRect(hDC, rcItem);
Canvas.Handle := 0;
end;
end;
procedure TManipulatecombobox.DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState);
begin
TControlCanvas(Canvas).UpdateTextFlags;
if Assigned(FOnDrawItem) then FOnDrawItem(Self, Index, Rect, State)
else
begin
Canvas.FillRect(Rect);
if Index = -1 then
Canvas.TextOut(Rect.Left + 2, Rect.Top, text);
if Index >= 0 then
Canvas.TextOut(Rect.Left + 2, Rect.Top, Items[Index]);
end;
end;
procedure TManipulatecombobox.Settext(Avalue: string);
begin
if Avalue <> Ftext then
begin
Ftext:= Avalue;
//I'm not sure this is a good way.
Invalidate;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
combo:= TManipulatecombobox.Create(self);
with combo do
begin
parent:= self;
SetBounds(20, 50, 120, 30);
Items.Add('item1');
items.Add('item2');
Style:= csOwnerDrawVariable;
end;
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
Combo.ItemIndex:= -1;
Combo.Settext(TEdit(sender).Text);
end;
end.
最后,我从
DBCombobox
代码复制所有VCL
类并更改两个函数。TManipulateDBcombobox= class(TManipulatecombobox)
private
FDataLink: TFieldDataLink;
FPaintControl: TPaintControl;
procedure DataChange(Sender: TObject);
procedure EditingChange(Sender: TObject);
function GetComboText: string;
function GetDataField: string;
function GetDataSource: TDataSource;
function GetField: TField;
function GetReadOnly: Boolean;
procedure SetComboText(const Value: string);
.
.
end;
implementation
.
.
procedure TManipulateDBcombobox.SetComboText(const Value: string);
var
I: Integer;
Redraw: Boolean;
begin
if Value <> GetComboText then
begin
if Style <> csDropDown then
begin
Redraw := (Style <> csSimple) and HandleAllocated;
if Redraw then SendMessage(Handle, WM_SETREDRAW, 0, 0);
try
if Value = '' then I := -1 else I := Items.IndexOf(Value);
ItemIndex := I;
finally
if Redraw then
begin
SendMessage(Handle, WM_SETREDRAW, 1, 0);
Invalidate;
end;
end;
if I >= 0 then Exit;
end;
// if Style in [csownerdrawfixed, csownerdrawvariable] then //?
text:= value;
end;
end;
function TManipulateDBcombobox.GetComboText: string;
begin
if Style in [csDropDown, csSimple] then Result := Text else
if ItemIndex < 0 then Result := text else Result := Items[ItemIndex];
end;
关于database - 具有CSOwnerDraw样式的Delphi DBCombobox,仅显示自己的项目,不显示数据字段字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22013864/