Kontrolki niestandardowe
Ta sekcja zawiera informacje o kontrolkach zdefiniowanych przez aplikację lub niestandardowych.
Omówiono następujące tematy.
- Tworzenie elementów sterujących Owner-Drawn
- podklasowanie klasy okna istniejącej kontrolki
- implementowanie klasy okien Application-Defined
- wysyłanie powiadomień z elementu sterującego
- ułatwień dostępu
- Tematy pokrewne
Tworzenie kontrolek Owner-Drawn
Przyciski, menu, kontrolki tekstu statycznego, pola listy i pola kombi można tworzyć z flagą stylu rysowaną przez właściciela. Gdy kontrolka ma styl narysowany przez właściciela, system obsługuje interakcję użytkownika z kontrolką w zwykły sposób, wykonując takie zadania jak wykrywanie, gdy użytkownik wybrał przycisk i powiadamia właściciela przycisku o zdarzeniu. Ponieważ kontrolka jest rysowana przez właściciela, okno nadrzędne kontrolki jest odpowiedzialne za jej wygląd graficzny. Okno nadrzędne odbiera komunikat za każdym razem, gdy kontrolka musi zostać narysowana.
W przypadku przycisków i kontrolek tekstu statycznego styl narysowany przez właściciela wpływa na sposób, w jaki system rysuje całą kontrolkę. W przypadku pól listy i pól kombi okno nadrzędne rysuje elementy wewnątrz kontrolki, a kontrolka rysuje swój własny kontur. Na przykład aplikacja może dostosować pole listy, aby wyświetlić małą mapę bitową obok każdego elementu na liście.
Poniższy przykładowy kod pokazuje, jak utworzyć kontrolkę statycznego tekstu rysowanego przez właściciela. Załóżmy, że kod Unicode jest zdefiniowany.
// g_myStatic is a global HWND variable.
g_myStatic = CreateWindowEx(0, L"STATIC", L"Some static text",
WS_CHILD | WS_VISIBLE | SS_OWNERDRAW,
25, 125, 150, 20, hDlg, 0, 0, 0);
W poniższym przykładzie w procedurze okna, które zawiera kontrolkę stworzoną w poprzednim przykładzie, komunikat WM_DRAWITEM jest obsługiwany poprzez wyświetlenie tekstu w kolorze niestandardowym przy użyciu czcionki domyślnej. Pamiętaj, że nie trzeba wywoływać BeginPaint i EndPaint, kiedy obsługujesz WM_DRAWITEM.
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT pDIS = (LPDRAWITEMSTRUCT)lParam;
if (pDIS->hwndItem == g_myStatic)
{
SetTextColor(pDIS->hDC, RGB(100, 0, 100));
WCHAR staticText[99];
int len = SendMessage(myStatic, WM_GETTEXT,
ARRAYSIZE(staticText), (LPARAM)staticText);
TextOut(pDIS->hDC, pDIS->rcItem.left, pDIS->rcItem.top, staticText, len);
}
return TRUE;
}
Aby uzyskać więcej informacji na temat kontrolek rysowanych przez właściciela, zobacz Tworzenie listy rysowanej przez właściciela oraz Pola kombinacji rysowanego przez właściciela.
Podklasowanie klasy okna istniejącej kontrolki
Podklasowanie istniejącej kontrolki to inny sposób tworzenia niestandardowej kontrolki. Procedura podklasy może zmieniać wybrane zachowania kontrolki, przetwarzając te komunikaty, które mają wpływ na wybrane zachowania. Wszystkie inne komunikaty są przekazywane do oryginalnej procedury okna dla kontrolki. Na przykład aplikacja może wyświetlić małą mapę bitową obok tekstu w kontrolce edycji tylko do odczytu, jednowierszowej, klasyfikując kontrolkę i przetwarzając komunikat WM_PAINT. Aby uzyskać więcej informacji, zobacz O Procedurach Okna oraz Podklasowanie Kontrolek.
Implementowanie klasy okna Application-Defined
Aby utworzyć kontrolkę, która nie jest jawnie oparta na istniejącej kontrolce, aplikacja musi utworzyć i zarejestrować klasę okien. Proces rejestrowania klasy okien zdefiniowanej przez aplikację dla kontrolki niestandardowej jest taki sam jak rejestrowanie klasy dla zwykłego okna. Aby utworzyć kontrolkę niestandardową, określ nazwę klasy okna w funkcji CreateWindowEx lub w szablonie okna dialogowego. Każda klasa musi mieć unikatową nazwę, odpowiednią procedurę okna i inne informacje.
Co najmniej procedura okna renderuje kontrolkę. Jeśli aplikacja używa kontrolki, aby umożliwić użytkownikowi wprowadzanie informacji, procedura okna przetwarza również komunikaty wejściowe z klawiatury i myszy oraz wysyła komunikaty powiadomień do okna nadrzędnego. Ponadto jeśli kontrolka obsługuje komunikaty sterujące, procedura okna przetwarza komunikaty wysyłane do niego przez okno nadrzędne lub inne okna. Na przykład kontrolki często przetwarzają komunikat WM_GETDLGCODE wysyłany przez okna dialogowe w celu przekierowania okna dialogowego w celu przetworzenia danych wejściowych klawiatury w określony sposób.
Procedura okna dla kontrolki zdefiniowanej przez aplikację powinna przetwarzać wszelkie wstępnie zdefiniowane komunikaty sterujące w poniższej tabeli, jeśli komunikat ma wpływ na działanie kontrolki.
Komunikat | Zalecenie |
---|---|
WM_GETDLGCODE | Przetwarzaj, jeśli kontrolka używa klawiszy ENTER, ESC, TAB lub klawiszy strzałek. Funkcja IsDialogMessage wysyła ten komunikat do kontrolek w oknie dialogowym, aby określić, czy należy przetworzyć klucze, czy przekazać je do kontrolki. |
WM_GETFONT | Jeśli komunikat WM_SETFONT jest również przetwarzany, należy go przetworzyć. |
WM_GETTEXT | Przetwarzanie, gdy tekst kontrolny nie jest taki sam jak tytuł określony przez funkcję CreateWindowEx. |
WM_GETTEXTLENGTH | Przetwarzanie, jeśli tekst kontrolki nie jest taki sam jak tytuł określony przez funkcję CreateWindowEx. |
WM_KILLFOCUS | Przetwarzanie, jeśli kontrolka wyświetla karetkę, prostokąt fokusu lub inny element, aby wskazać, że ma fokus na wejściu. |
WM_SETFOCUS | Przetwarzanie, jeśli kontrolka wyświetla kursor, prostokąt fokusu lub inny element, aby wskazać, że ma fokus dla danych wejściowych. |
WM_SETTEXT | Przetwarzanie, jeśli tekst kontrolki nie jest taki sam jak tytuł określony przez funkcję CreateWindowEx. |
WM_SETFONT | Proces, jeśli pole kontrolne wyświetla tekst. System wysyła ten komunikat podczas tworzenia okna dialogowego, które ma styl DS_SETFONT. |
Komunikaty sterujące zdefiniowane przez aplikację są specyficzne dla danej kontrolki i muszą być jawnie wysyłane do kontrolki przy użyciu funkcji SendMessage lub SendDlgItemMessage. Wartość liczbowa dla każdego komunikatu musi być unikatowa i nie może powodować konfliktu z wartościami innych komunikatów okna. Aby upewnić się, że wartości komunikatów zdefiniowanych przez aplikację nie powodują konfliktu, aplikacja powinna utworzyć każdą wartość, dodając unikatową liczbę do wartości WM_USER.
Wysyłanie powiadomień z kontrolki
Kontrolki niestandardowe mogą być wymagane do wysyłania powiadomień o zdarzeniach do okna nadrzędnego, aby aplikacja hosta mogła reagować na te zdarzenia. Na przykład niestandardowy widok listy może wysłać powiadomienie, gdy użytkownik wybierze element, a inne powiadomienie po dwukrotnym kliknięciu elementu.
Powiadomienia są wysyłane jako komunikaty WM_COMMAND lub WM_NOTIFY. WM_NOTIFY wiadomości zawierają więcej informacji niż komunikaty WM_COMMAND.
Identyfikator kontrolki to unikatowy numer używany przez aplikację do identyfikowania kontrolki wysyłającej komunikat. Aplikacja ustawia identyfikator kontrolki podczas tworzenia kontrolki. Aplikacja określa identyfikator albo w parametrze hMenu funkcji CreateWindowEx, albo w członku id struktury DLGITEMTEMPLATEEX.
Ponieważ sama kontrolka nie ustawia identyfikatora kontrolki, kontrolka musi pobrać identyfikator, zanim będzie mogła wysyłać komunikaty powiadomień. Aby pobrać własny identyfikator kontrolki, należy użyć funkcji GetDlgCtrlID. Mimo że identyfikator kontrolki jest określony jako uchwyt menu podczas tworzenia kontrolki, nie można użyć funkcji GetMenu do pobrania identyfikatora. Alternatywnie, kontrolka może pobrać identyfikator z członka hMenu w strukturze CREATESTRUCT podczas przetwarzania komunikatu WM_CREATE.
Poniższe przykłady, w których hwndControl jest uchwytem okna kontrolki, a CN_VALUECHANGED jest niestandardową definicją powiadomienia, pokazują dwa sposoby wysyłania powiadomienia specyficznego dla kontrolki.
// Send as WM_COMMAND.
SendMessage(GetParent(hwndControl),
WM_COMMAND,
MAKEWPARAM(GetDlgCtrlID(hwndControl), CN_VALUECHANGED),
(LPARAM)hwndControl);
// Send as WM_NOTIFY.
NMHDR nmh;
nmh.code = CN_VALUECHANGED;
nmh.idFrom = GetDlgCtrlID(hwndControl);
nmh.hwndFrom = hwndControl;
SendMessage(GetParent(hwndControl),
WM_NOTIFY,
(WPARAM)hwndControl,
(LPARAM)&nmh);
Należy pamiętać, że struktura NMHDR może być częścią większej struktury zdefiniowanej przez kontrolkę, która zawiera dodatkowe informacje. W tym przykładzie w tej strukturze mogą znajdować się stare i nowe wartości kontrolki. (Takie struktury rozszerzone są używane z wieloma standardowymi powiadomieniami, na przykład zobacz LVN_INSERTITEM, która używa struktury NMLISTVIEW).
Dostępność
Wszystkie typowe kontrolki obsługują funkcję Microsoft Active Accessibility (MSAA), która umożliwia dostęp programowy przez aplikacje z ułatwieniami dostępu, takie jak czytniki zawartości ekranu. Usługa MSAA umożliwia również automatyzację interfejsu użytkownika, nowszą technologię, interakcję z kontrolkami.
Kontrolki niestandardowe powinny implementować interfejs IAccessible (do obsługi MSAA) lub interfejsy automatyzacji interfejsu użytkownika, lub oba. W przeciwnym razie produkty z ułatwieniami dostępu będą mogły uzyskać tylko bardzo ograniczone informacje o oknie sterowania, nie będą miały dostępu do właściwości kontrolki i nie będą mogły wyzwalać zdarzeń w kontrolce.
Aby uzyskać więcej informacji na temat zapewniania dostępności kontrolki, zobacz Windows Automation API.
Tematy pokrewne