我有连接到DBComboboxCsOwnerDrawFixed样式。
有时在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/

10-09 06:17