Nikt nie podawał przykładu, więc pokażę jak takie coś wykonać;
Skoro problemu z odczytem danych z bazy nie ma, to nie będę pokazywał jak łączyć łańcuchy - to raczej sensu nie ma; W każdym razie wygodnie będzie oddzielać składowe znakiem spacji (0x20
), bo będzie można wyświetlić całość w głównym polu komponentu; Dla przykładu dodajemy do komponentu poniższe itemy:
xxxxx xxxxxxxxxxxx
xxxxxxx xxxxxxx
xxxx xxxxxxxxxxxxxxx
xxxxxxxxx xxxxxxxx
xxxxxxxxx xxxx
xxxxx xxxxxxxxx
Wartość po lewej to imię, a po prawej to nazwisko - jak widać mają różne długości (i składowe, i całość); Teraz trzeba napisać algorytm rozdzielający łańcuch na składowe - najprościej jest to wykonać za pomocą klasy TStringList
:
type
TItemTextParts = record
Name: AnsiString;
Surname: AnsiString;
end;
procedure TMainForm.SplitItemText(AText: AnsiString; out AResult: TItemTextParts);
const
COMBO_ITEM_PARTS_SEPARATOR = AnsiChar(' ');
begin
with TStringList.Create() do
try
Delimiter := COMBO_ITEM_PARTS_SEPARATOR;
DelimitedText := AText;
AResult.Name := Strings[0];
AResult.Surname := Strings[1];
finally
Free();
end;
end;
Metoda ta rozdziela łańcuch itema na składowe, po czym wrzuca je do pól rekordu z parametru AResult
; Oczywiście zabezpieczenia można sobie dodać, jeśli któryś z łańcuchów może zaiwerać tylko imię/nazwisko; To nam wystarczy, teraz czas na malowanie itemów; Samo malowanie jest banalne - wystarczy tylko ustalić kolor tekstu i tła na podstawie zawartości zbioru z parametru State
i pomalować item:
procedure TMainForm.bcPreviewDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
const
COMBO_SURNAME_OFFSET = 100;
var
Combo: TComboBox;
itpItem: TItemTextParts;
begin
Combo := TComboBox(Control);
with Combo.Canvas do
begin
{ set colors for background and text }
if odSelected in State then
begin
Brush.Color := clMenuHighlight;
Font.Color := clHighlightText;
end
else
begin
Brush.Color := clWindow;
Font.Color := clWindowText;
end;
{ fill background rectangle }
FillRect(Rect);
if odComboBoxEdit in State then
{ draw name and surname }
TextOut(Rect.Left + 2, Rect.Top + 2, Combo.Items[Index])
else
begin
{ split item text }
SplitItemText(Combo.Items[Index], itpItem);
{ draw name }
TextOut(Rect.Left + 2, Rect.Top + 2, itpItem.Name);
{ draw surname }
TextOut(Rect.Left + COMBO_SURNAME_OFFSET, Rect.Top + 2, itpItem.Surname);
end;
{ remove focus rectangle }
if odFocused in State then
begin
Pen.Color := Pen.Color xor $FFFFFF;
DrawFocusRect(Rect);
end;
end;
end;
Jak widać rysowanie tekstu jest w warunku; Istnienie enuma odComboBoxEdit
istnieje w zbiorze State
oznacza, że malowany jest item w edytorze komponentu, a nie na jego rozwijanej liście; Sprawdzenie to ma na celu narysowanie tekstu razem, aby przy zwiniętej liście nie było dużego odstępu pomiędzy imieniem a nazwiskiem; W przeciwnym razie imię i nazwisko rysowane są w odpowiednim odstępie od lewej krawędzi obszaru roboczego itema; Offset nazwiska można sobie wyregulować według własnych upodobań - ustalenie odpowiedniego odstępu od lewej krawędzi jest konieczne, aby imię nie nachodziło na nazwisko;
Efekt działania powyższego kodu:
Item widoczny w edytorze to ten sam co item podświetlony na liście; Źródła programu bez pliku wykonywalnego wrzucam do załączników posta.