• Keine Ergebnisse gefunden

Arbeiten mit der Combobox

Im Dokument Win32API-Tutorials für Delphi (Seite 38-44)

1. Fenster und Controls

2.2. Arbeiten mit der Combobox

2.2.1. Die Combobox erzeugen

Die Combobox ist ohne VCL ein bisschen gewöhnungsbedürftig - aber machbar. Dieses Tutorial zeigt, wie man Eintrag hinzufügt, löscht und ausgewählte Einträge ausliest und anzeigt.

Das Element wird mit "CreateWindowEx" erzeugt. Wichtig sind hierbei aber zwei Dinge:

Die angegebene Höhe ist die Höhe des Editfeldes inklusive der ausgeklappten Liste! Soll in der Liste ein Scrollbalken erscheinen, muss zusätzlich der Stil WS_VSCROLL benutzt werden!

Die wichtigsten Combobox-Stile (weitere finden Sie in der Hilfe und im MSDN):

Wert Bedeutung

CBS_AUTOHSCROLL Scrollt Text automatisch nach rechts, wenn der Anwender ein Zeichen am Ende der Zeile eingibt. Ohne diesen Stil kann die Textlänge nur der Breite der Eingabezeile entsprechen.

CBS_DISABLENOSCROLL Enthält die Liste nicht genügend Items zum Scrollen, wird der Scrollbalken deaktiviert dargestellt. Ohne diesen Stil wird der Scrollbalken in diesem Fall versteckt.

CBS_LOWERCASE,

CBS_UPPERCASE Mit diesen Stilattributen lässt sich der Text in Klein-, bzw. Großbuchstaben konvertieren.

Beide Attribute schließen sich aber gegenseitig aus, deshalb bitte nur einen verwenden.

CBS_SORT Sortiert die Strings in der Liste alfabetisch.

Oder als Auszug aus dem Beispielprogramm:

hCB := CreateWindowEx(0, 'COMBOBOX', '', WS_CHILD or WS_VISIBLE or

CBS_AUTOHSCROLL or CBS_DROPDOWN or CBS_SORT or WS_VSCROLL, 10, 10, 150, 150, hWnd, IDC_CB, hInstance, nil);

2.2.2. Der Combobox einen Eintrag hinzufügen

Es gibt zwei Möglichkeiten zum Hinzufügen von Einträgen: "CB_ADDSTRING" fügt einen String alphabetisch in die Liste ein (sofern das entsprechende Stilattribut gesetzt ist) oder hängt den String an die Liste an:

buffer := 'Peter';

SendMessage(hCB, CB_ADDSTRING, 0, Integer(@buffer));

"CB_INSERTSTRING" hingegen ignoriert die Sortierung; hier kann man einen String gezielt an einer bestimmten Position einfügen:

buffer := 'Luckie';

SendMessage(hCB, CB_INSERTSTRING, {Index ->} 3, Integer(@buffer));

Beide Nachrichten haben gemeinsam, dass sie als zweiten Parameter einen Zeiger auf den Textpuffer erwarten. Aber während bei "CB_INSERTSTRING" der erste Parameter der Index ist, an dem der Text eingefügt werden soll, muss dieser Wert bei "CB_ADDSTRING" Null sein.

2.2.3. Einen Eintrag aus der Combobox entfernen

Die Vorgehensweise beim Löschen eines Eintrages entspricht vom Prinzip her der Listbox. Zuerst sollte man mit der Nachricht "CB_GETCURSEL" ermitteln, welchen Index der ausgewählte Eintrag hat bevor man ihn mit

"CB_DELETESTRING" entfernen kann. Der Auszug aus dem Beispielprogramm verdeutlicht es:

IDC_DEL:

begin

{Index holen}

i := SendMessage(hCB, CB_GETCURSEL, i, 0);

if(i = CB_ERR) then exit;

{Item löschen}

Sendmessage(hCB, CB_DELETESTRING, i, 0);

end;

Um den gesamten Inhalt der Combobox zu löschen, verwenden Sie die Nachricht "CB_RESETCONTENT". Beide Parameter müssen hier Null sein:

IDC_DELALL:

SendMessage(hCB, CB_RESETCONTENT, 0, 0);

2.2.4. Einen Eintrag aus der Combobox auslesen

Wenn Sie sich das Beispielprogramm anschauen, dann werden Sie bemerken, dass Ihnen in einem Label oben rechts der jeweils aktuell ausgewählte Eintrag der Combobox angezeigt wird. Dazu wird die Nachricht "CBN_SELCHANGE"

bearbeitet. Sie ist ein Zeichen, dass sich die Auswahl der Combobox geändert hat. Mit der Nachricht "CB_GETLBTEXT"

kann man dann den Text auslesen. Vorher ist natürlich wieder der Index des markierten Eintrags zu erfragen. Der Auszug zeigt Ihnen wie es geht:

WM_COMMAND:

case hiword(wParam) of

{Combobox-Auswahl geändert}

CBN_SELCHANGE:

case loword(wParam) of IDC_CB:

begin

{Index holen}

i := SendMessage(hCB, CB_GETCURSEL, i, 0);

if(i <> CB_ERR) then begin

{Label aktualisieren}

Sendmessage (hCB, CB_GETLBTEXT, i, Integer(@buffer));

SendMessage (hSelItem, WM_SETTEXT, 0, Integer(@buffer));

{Löschen-Button aktivieren}

EnableWindow(hDel,true);

end;

end;

end;

end;

2.2.5. Die Anzahl der Einträge in der Combobox ermitteln

Um die Anzahl der Einträge bei einer Combobox zu ermitteln, benutzen wir die Nachricht "CB_GETCOUNT".

Rückgabeergebnis ist der entsprechende Wert, bzw. CB_ERR im Fehlerfall.

i := SendMessage(hCB, CB_GETCOUNT, 0, 0);

wvsprintf(buffer, '%d', PChar(@i));

lstrcat(buffer, ' Einträge in der Combobox');

2.2.6. Eine ComboBoxEx erzeugen

Eine ComboBoxEx ist eine erweiterte Form der ComboBox, die eine eingebaute Unterstützung für Grafiken besitzt.

Allerdings ist der Stil CBS_OWNERDRAWVARIABLE nicht möglich, weil die Unterstützung in Form von Imagelisten realisiert wurde. Das bedeutet, Sie können mehrere Grafiken in diese Liste laden und müssen sich nicht selbst um das Zeichnen der Bilder kümmern. Allerdings haben diese Grafiken dann immer die selbe Größe. Ansonsten verhält sich die ComboBoxEx wie eine normale ComboBox.

Allerdings handelt es sich hier um ein so genanntes "Common Control". Es ist daher sehr wichtig, dass die ComboBoxEx zwingend mit "InitCommonControlsEx" initialisiert werden muss, sonst sehen Sie sie erst gar nicht

var iccex : TInitCommonControlsEx = (dwSize:sizeof(iccex);

dwICC:ICC_USEREX_CLASSES;);

begin

InitCommonControlsEx(iccex);

{ ... } end.

Sie sehen sie auch nicht, wenn Sie nur "InitCommonControls" aufrufen, wie Sie das evtl. bei einigen anderen

"Common Controls" noch sehen werden.

2.2.6.1. Das Control erzeugen

Wenn Sie die "Common Controls" und damit die ComboBoxEx initialisiert haben, dann können Sie sie wie jedes andere Control erzeugen, wobei als Klassenname WC_COMBOBOXEX zu benutzen ist:

hCBEx := CreateWindowEx(0,WC_COMBOBOXEX,nil,WS_BORDER or WS_CHILD or WS_VISIBLE or CBS_DROPDOWN,10,10,300,150,wnd,IDC_CBEX,hInstance,nil);

Erweiterte Stilattribute

Wert Bedeutung

CBES_EX_CASESENSITIVE Die Suche nach Text in der ComboBoxEx ist abhängig von der Schreibweise der Strings.

CBES_EX_NOEDITIMAGE Das Eingabefeld und die Liste der ComboBoxEx zeigen keine Grafiken an CBES_EX_NOEDITIMAGEINDENT Das Eingabefeld und die Liste der ComboBoxEx zeigen keine Grafiken an (weitere Stile finden Sie im PSDK)

Wenn Sie einen der erweiterten Stile setzen wollen, dann benötigen Sie die Nachricht "CBEM_SETEXTENDEDSTYLE", wobei Sie den wParam auf Null setzen sollten. Das bewirkt, dass alle Flags, die Sie im lParam angeben, berücksichtigt werden. bspw.

SendMessage(hCBEx,CBEM_SETEXTENDEDSTYLE,0,CBES_EX_NOEDITIMAGEINDENT);

Im Gegensatz dazu wäre im folgenden Aufruf das Flag CBES_EX_CASESENSITIVE wirkungslos, weil der wParam lediglich CBES_EX_NOEDITIMAGE enthält und damit das zweite Flag im lParam ignoriert

SendMessage(hCBEx, CBEM_SETEXTENDEDSTYLE, CBES_EX_NOEDITIMAGE, CBES_EX_NOEDITIMAGE or CBES_EX_CASESENSITIVE);

2.2.6.2. Die Imageliste zuweisen

Wie bereits erwähnt enthält die ComboBoxEx eine eingebaute Unterstützung für Grafiken in Form von Imagelisten. Das heißt, wenn Sie die Grafiken nicht gerade zur Laufzeit erzeugen, sondern bspw. Bilder aus den Ressourcen in der ComboBoxEx anzeigen lassen wollen, dann müssen Sie lediglich eine Imageliste erzeugen und die notwendigen Grafiken laden.

Leider muss ich an der Stelle ein bisschen vorgreifen. Zum einen werden uns Imagelisten noch in späteren Beiträgen begegnen (bei der List-View etwa), und zum anderen benutzen wir kurzerhand die Grafik aus dem Toolbar-Beitrag.

Gehen wir also davon aus, dass die besagte Grafik Teil der Programmressourcen ist und die ID 100 hat. Dann laden wir sie zuerst

hbmp := LoadBitmap(hInstance,MAKEINTRESOURCE(100));

Wenn das funktioniert hat, dann ist der Rückgabewert ungleich Null, und wir können die Imageliste mit den Abmessungen von 16x16 Pixel erzeugen

if(hbmp <> 0) then begin

hImgList := ImageList_Create(16,16,ILC_COLOR,0,1);

Nun laden wir die Grafik, indem wir lediglich den Befehl "ImageList_Add" aufrufen. Das Besondere dabei ist, dass unsere Grafik eigentlich mehrere Einzelbilder enthält. Durch die Festlegung der Imageliste auf 16 Pixel Breite wird die Grafik daher automatisch in die Einzelbilder "aufgetrennt". Sie müssen daher nur darauf achten, dass alle Einzelbilder die selbe Breite haben

ImageList_Add(hImgList,hbmp,0);

Da wir die geladene Grafik nicht mehr benötigen, geben wir sie frei

DeleteObject(hbmp);

und übergeben dann die Imageliste mit der Nachricht "CBEM_SETIMAGELIST" an die ComboBoxEx

SendMessage(hCBEx,CBEM_SETIMAGELIST,0,LPARAM(hImgList));

end;

Die Imageliste freigeben

Bevor Sie das Programm beenden, sollten Sie die Imageliste mit dem Befehl "ImageList_Destroy" wieder freigeben, wobei Sie als Parameter das Handle der Liste benutzen:

ImageList_Destroy(hImgList);

2.2.6.3. Items einfügen

Um ein Item einzufügen, benötigen wir das Record TComboBoxExItem. Zuerst legen wir fest, welche Membervariablen des Records gültig sein sollen. Dazu dient die mask-Variable, der wir die notwendigen Flags übergeben. Wir wollen einen Text in der ComboBoxEx sehen, der Text soll u.U. eingerückt sein, und er soll eine Grafik anzeigen. Die Festlegung der Attribute lautet daher also

cbei.mask := CBEIF_TEXT or CBEIF_INDENT or CBEIF_IMAGE or CBEIF_SELECTEDIMAGE;

Dann geben wir den Index des Items an. Im Beispielprogramm wird hier eine Schleife durchlaufen, und der jeweilige Schleifenwert wird als Index übergeben. Wenn Sie stattdessen jedes neue Item generell an das Ende anhängen wollen, dann benutzen Sie den Wert -1

cbei.iItem := -1;

Danach geben wir den gewünschten Text und dessen Länge an. Im Beispielprogramm kommen diese Angaben aus einem Array, dessen Elemente durch die Schleife nacheinander abgearbeitet werden. Hier soll ein Wert aus dem Array das Prinzip verdeutlichen:

cbei.pszText := 'Peter';

cbei.cchTextMax := lstrlen('Peter');

Wenn Sie den Text einrücken wollen, dann benutzen Sie die iIndent-Membervariable und weisen Sie ihr einen Wert zu.

Zu beachten ist, dass der angegebene Wert mit 10 multipliziert wird, d.h. Eins entspricht also einer Einrückung von 10 Pixel, Zwei von 20 Pixel, usw.

cbei.iIndent := 1;

Bleiben noch die Grafiken. In der Auswahlliste soll vor jedem Item ein Bild aus der Imageliste zu sehen sein. Darum müssen wir dessen Index natürlich angeben:

cbei.iImage := ItemInfo[i].iImage;

Aber auch bei der Auswahl eines Items soll im Eingabefeld der ComboBoxEx die Grafik zu sehen sein. Aus dem Grund haben wir das Flag CBEIF_SELECTEDIMAGE benutzt, was bedeutet, das wir den Index des gewünschten Bildes an die iSelectedImage-Variable übergeben müssen:

cbei.iSelectedImage := ItemInfo[i].iImage;

Mit Hilfe der Nachricht "CBEM_INSERTITEM" fügen wir das Item dann ein

SendMessage(hCBEx,CBEM_INSERTITEM,0,LPARAM(@cbei));

und erhalten beispielsweise das folgende Ergebnis:

Und damit sehen Sie, dass Sie sich tatsächlich um nichts weiter kümmern müssen. Die Höhe der ComboBoxEx richtet sich übrigens nach der Höhe der Grafiken. Das Beispielprogramm enthält einen Compilerschalter (THE_BIG_PICTURE), mit dem Sie eine 32x32-Bitmap laden lassen können. Die ComboBoxEx ist dann entsprechend höher.

TcomboBoxExItem-Definition

typedef struct {

UINT mask; // legt die gültigen Membervariablen fest INT_PTR iItem; // Item-Index, bzw. -1

LPTSTR pszText; // Itemtext

int cchTextMax; // Länge des Textes

int iImage; // Index der Grafik für die Auswahlliste int iSelectedImage; // Index der Grafik für das Eingabefeld int iOverlay;

int iIndent; // Einrückung LPARAM lParam;

} COMBOBOXEXITEM

Im Dokument Win32API-Tutorials für Delphi (Seite 38-44)