Programmierung von Kontrollelementen
Willemers Informatik-Ecke
Die Kontrollelemente besitzen einige Gemeinsamkeiten. Es sind aus Sicht von Windows lediglich spezialisierte Fenster und gehorchen gleichen Gesetzen.

Zu allererst sollte der Header CommCtrl.h eingebunden werden.

#include <CommCtrl.h>
Soll ein Kontrollelement in einem Fenster erstellt werden, erfolgt dies normalerweise unter WM_CREATE der Fensterfunktion
case WM_CREATE:
    {
        int x = 0;
        int y = 32 * 7;
        int w = 200;
        int h = 24;
        HWND hwndWahl = CreateWindow(WC_BUTTON, L"Neues Spiel",
            WS_VISIBLE | WS_CHILD | WS_BORDER, x, y, w, h, 
            hWnd, (HMENU)NEUESSPIEL, 0, 0);

    }
    break;

Fensterklassen

ElementFensterklasseStil-Präfix
Staticfeld WC_STATIC SS_
Schaltfläche (Button) WC_BUTTON BS_
Eingabefeld WC_EDIT ES_
Listbox WC_LISTBOX LBS_
Combobox WC_COMBOBOX CBS_
Scrollbar WC_SCROLLBAR SBS_
Baumdiagramm WC_TREEVIEW TVS_
ListView WC_LISTVIEW LVS_

Erzeugung eines Kontrollelements

Kontrollelemente werden oft in Dialogboxen erstellt und werden durch den Dialogstart miterzeugt. Werden diese Elemente aber in Fenstern benötigt werden sie mit CreateWindow erzeugt. Die Parameter von CreateWindow sind:
LPCTSTR: Fensterklasse
Hier wird die vordefinierte Fensterklasse angegeben, die wie bei eigenen Fenstern durch einen String festgelegt ist. Beispiel: "LISTBOX"
LPCTSTR: Fenstertext
Bei STATIC, EDIT und BUTTON ist dies der Text, der im Element zu sehen ist. Bei Standardfenstern steht er im Balken.
DWORD: Fensterstil
Eine Veroderung von WS_-Konstanten. Typischerweise werden die Konstanten WS_VISIBLE|WS_CHILD|WS_BORDER als Ausgangspunkt benötigt. Dazu kommen noch elementspezifische Stile, wie etwa bei Listboxen LBS_SORT.
int, int, int, int: x, y, Breite, Hoehe
Position im Elternfenster
HWND: das Elternfenster
die Fensterfunktion des Elternfensters erhät die Nachrichten des Kontrollelements
HMENU: Ressource-ID
Jedes Element hat eine solche ID, die in ihrem Umfeld eindeutig sein muß Bei Standardfenstern wird an dieser Stelle die Menü-ID angegeben. Normale IDs müssen hier gecastet werden: (HMENU)ID_MYCONTROL.
HANDLE: Instanz
Die Instanz der Anwendung, wie bei WinMain übergeben.
LPVOID: Parameter
Dieser Wert ist bei Kontrollelementen 0. Er wird bei der Erzeugung von Fenstern und Dialogen gebraucht.

Ein Beispiel zur Erzeugung eines Eingabefeldes:

    CreateWindow("EDIT", "", 
                 WS_VISIBLE|WS_CHILD|WS_BORDER,
                 10, 50, 300, 30, // Positionen auf dem Elternfenster
                 hWnd, (HMENU)ID_MYCONTROL, hInst, 0);

Bei den Common Controls sollte noch der Aufruf von InitCommonControls() erfolgen. In der neueren Variante und lautet z. B. für Tree Views:

INITCOMMONCONTROLSEX icc;
  icc.dwSize = sizeof(icc);
  icc.dwICC = ICC_TREEVIEW_CLASSES;
  InitCommonControlsEx(&icc);

Ereignisse bearbeiten

Die Ereignisse gelangen in die Fensterfunktion des Elternfensters. Dies kann ein Dialog oder ein gewöhnliches Fenster sein. Die Kontrollelemente lösen ein WM_COMMAND aus.

LOWORD(wParam) enthält die Ressource-ID
HIWORD(wParam) beschreibt das Ereignis

  case WM_COMMAND:
    switch(LOWORD(wParam)) { // welches Kontrollelement loest die Nachricht aus?
    case ID_MYCONTROL:
      switch (HIWORD(wParam)) {  // welches Ereignis ist genau eingetreten?
      case LBN_DBLCLK:  // ein Doppelklick auf eine Listbox
        break;
      case LBN_SELCHANGE:

Einige der neueren Kontrollelemente verwenden nicht die Nachricht WM_COMMAND, sondern WM_NOTIFY. Bei diesem Ereignis wird im lParam ein Pointer auf eine Struktur NMHDR übergeben, die in den ersten Elementen bei allen Kontrolls gleich sind. Sie enthalten:

HWND hwndFrom Das HWND des Kontrollelements
UINT idFrom Die Ressource-ID des Kontrollelements
UINT code Der Code des Ereignisses

Eine typische Bearbeitung der Ereignisse sieht also so aus:

LPNMHDR hdr;

    case WM_NOTIFY:
        hdr = (LPNMHDR)lParam;
        switch(hdr->code) {
           // unterscheide den Notify-Code

Manipulation

Ein Kontroll kann Befehle erhalten oder man kann Informationen erfragen. Der Kontakt des Programmes mit seinen Kontrollelementen geschieht durch das Senden von Nachrichten.

Im Beispiel werden die Daten, die hinter dem ausgewählten Listboxelement abgelegt sind, angefragt. Dies benötigt zwei Schritte. Erst muß ermittelt werden, welches Element selektiert ist und anschließend erfragt man die Daten. Beide Vorgänge werden durch die Funktion SendMessage ausgelöst. Im ersten Parameter wird das HWND des Kontrollelements benoetigt, im Beispiel hListe. Der zweite Parameter enthält das Kommando. Das ist LB_CURSEL zum Ermitteln des aktuell selektierten Element und LB_GETITEMDATA zur Frage nach den Daten. Die folgenden beiden Parameter entsprechen dem wParam und lParam aus der Fensterfunktion.

    ListIndex = SendMessage(hListe, LB_GETCURSEL, 0, 0);
    Person = (tPerson *)SendMessage(hListe, LB_GETITEMDATA, ListIndex, 0);