Unterstufen eines Kombinationsfelds
In diesem Thema wird veranschaulicht, wie Kombinationsfelder untergliedert werden. Die C++-Beispielanwendung erstellt ein Symbolleistenfenster, das zwei Kombinationsfelder enthält. Durch Unterklassen der Bearbeitungssteuerelemente in den Kombinationsfeldern fängt das Symbolleistenfenster TAB-, EINGABE- und ESC-Schlüssel ab, die andernfalls ignoriert würden.
Wichtige Informationen
Technologien
Voraussetzungen
- C/C++
- Windows Benutzeroberfläche-Programmierung
Instructions
Verarbeiten der WM _ CREATE-Nachricht
Die Anwendung verarbeitet die WM _ CREATE-Nachricht, um zwei Kombinationsfeld-Steuerelemente als untergeordnete Fenster zu erstellen.
// Create two combo box child windows.
dwBaseUnits = GetDialogBaseUnits();
hwndCombo1 = CreateWindow(L"COMBOBOX", L"",
CBS_DROPDOWN | WS_CHILD | WS_VISIBLE,
(6 * LOWORD(dwBaseUnits)) / 4,
(2 * HIWORD(dwBaseUnits)) / 8,
(100 * LOWORD(dwBaseUnits)) / 4,
(50 * HIWORD(dwBaseUnits)) / 8,
hwnd, NULL, NULL, NULL);
hwndCombo2 = CreateWindow(L"COMBOBOX", L"",
CBS_DROPDOWN | WS_CHILD | WS_VISIBLE,
(112 * LOWORD(dwBaseUnits)) / 4,
(2 * HIWORD(dwBaseUnits)) / 8,
(100 * LOWORD(dwBaseUnits)) / 4,
(50 * HIWORD(dwBaseUnits)) / 8,
hwnd, NULL, hInst, NULL);
Die Anwendung untergliedert dann die Bearbeitungssteuerelemente (Auswahlfelder) in jedem Kombinationsfeld, da sie die Zeicheneingabe für einfache und Dropdown-Kombinationsfelder erhalten. Schließlich wird die ChildWindowFromPoint-Funktion aufgerufen, um das Handle für jedes Bearbeitungssteuerelement abzurufen.
Um die Bearbeitungssteuerelemente zu untergliedern, ruft die Anwendung die SetWindowLong-Funktion auf und ersetzt den Zeiger auf die Klassenfensterprozedur durch einen Zeiger auf die anwendungsdefinierte SubClassProc-Funktion. Der Zeiger auf die ursprüngliche Fensterprozedur wird in der globalen Variablen lpfnEditWndProc gespeichert.
SubClassProc fängt TAB-, EINGABE- und ESC-Schlüssel ab und benachrichtigt das Symbolleistenfenster durch Senden von anwendungsdefinierten Nachrichten (WM _ TAB, WM _ ESC und WM _ ENTER). SubClassProc verwendet die CallWindowProc-Funktion, um die meisten Nachrichten an die ursprüngliche Fensterprozedur lpfnEditWndProc zu übergeben.
// Get the edit window handle to each combo box.
pt.x = 1;
pt.y = 1;
hwndEdit1 = ChildWindowFromPoint(hwndCombo1, pt);
hwndEdit2 = ChildWindowFromPoint(hwndCombo2, pt);
// Change the window procedure for both edit windows
// to the subclass procedure.
lpfnEditWndProc = (WNDPROC) SetWindowLongPtr(hwndEdit1,
GWLP_WNDPROC, (LONG_PTR) SubClassProc);
SetWindowLongPtr(hwndEdit2, GWLP_WNDPROC, (LONG_PTR) SubClassProc);
Verarbeiten der WM _ SETFOCUS-Nachricht
Wenn das Symbolleistenfenster den Eingabefokus erhält, wird der Fokus sofort auf das erste Kombinationsfeld in der Symbolleiste festgelegt. Zu diesem Zweck ruft das Beispiel die SetFocus-Funktion als Reaktion auf die WM _ SETFOCUS-Nachricht auf.
case WM_SETFOCUS:
SetFocus(hwndCombo1);
break;
Verarbeiten Application-Defined Nachrichten
Die SubClassProc-Funktion sendet anwendungsdefinierte Nachrichten an das Symbolleistenfenster, wenn der Benutzer die TAB-, EINGABE- oder ESC-Taste in einem Kombinationsfeld drückt. Die _ WM-TAB-Nachricht wird für die TAB-TASTE, die WM _ ESC-Nachricht für die ESC-Taste und die _ WM-EINGABE-Meldung für die EINGABETASTE gesendet.
Im Beispiel wird die _ WM-TAB-Meldung verarbeitet, indem der Fokus auf das nächste Kombinationsfeld in der Symbolleiste festgelegt wird. Die WM _ ESC-Nachricht wird verarbeitet, indem der Fokus auf das Hauptanwendungsfenster festgelegt wird.
case WM_TAB:
if (GetFocus() == hwndEdit1)
SetFocus(hwndCombo2);
else
SetFocus(hwndCombo1);
break;
case WM_ESC:
hwndCombo = GetFocus() == hwndEdit1 ? hwndCombo1 : hwndCombo2;
// Clear the current selection.
SendMessage(hwndCombo, CB_SETCURSEL,
(WPARAM) (-1), 0);
// Set the focus to the main window.
SetFocus(hwndMain);
break;
Als Reaktion auf die _ WM-EINGABEMELDUNG stellt das Beispiel sicher, dass die aktuelle Auswahl für das Kombinationsfeld gültig ist, und legt dann den Fokus auf das Hauptanwendungsfenster fest. Wenn das Kombinationsfeld keine aktuelle Auswahl enthält, wird im Beispiel die CB _ FINDSTRINGEXACT-Meldung verwendet, um nach einem Listenelement zu suchen, das dem Inhalt des Auswahlfelds entspricht. Wenn eine Übereinstimmung vorhanden ist, legt das Beispiel die aktuelle Auswahl fest. Andernfalls wird ein neues Listenelement hinzugefügt.
case WM_ENTER:
hwndCombo = GetFocus() == hwndEdit1 ? hwndCombo1 : hwndCombo2;
SetFocus(hwndMain);
// If there is no current selection, set one.
if (SendMessage(hwndCombo, CB_GETCURSEL, 0, 0)
== CB_ERR)
{
if (SendMessage(hwndCombo, WM_GETTEXT,
sizeof(achTemp), (LPARAM) achTemp) == 0)
break; // Empty selection field
dwIndex = SendMessage(hwndCombo,
CB_FINDSTRINGEXACT, (WPARAM) (-1),
(LPARAM) achTemp);
// Add the string, if necessary, and select it.
if (dwIndex == CB_ERR)
dwIndex = SendMessage(hwndCombo, CB_ADDSTRING,
0, (LPARAM) achTemp);
if (dwIndex != CB_ERR)
SendMessage(hwndCombo, CB_SETCURSEL,
dwIndex, 0);
}
break;
// .
// . Process additional messages.
// .
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
Vollständiges Beispiel
Im Folgenden sind die Fensterprozedur für die Symbolleiste und die Unterklassenprozedur für die beiden Kombinationsfelder aufgeführt.
#define WM_TAB (WM_USER)
#define WM_ESC (WM_USER + 1)
#define WM_ENTER (WM_USER + 2)
// Global variables
HWND hwndMain;
WNDPROC lpfnEditWndProc; // Original wndproc for the combo box
// Prototypes
LRESULT CALLBACK SubClassProc( HWND, UINT, WPARAM, LPARAM );
/********************************************************
FUNCTION: ToolbarWindowProc
PURPOSE: Window procedure for the toolbar window
*********************************************************/
LRESULT CALLBACK ToolbarWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndEdit1;
static HWND hwndEdit2;
static HWND hwndCombo1;
static HWND hwndCombo2;
POINT pt;
DWORD dwBaseUnits;
HWND hwndCombo;
DWORD dwIndex;
char achTemp[256]; // Temporary buffer
switch (msg)
{
case WM_CREATE:
// Create two combo box child windows.
dwBaseUnits = GetDialogBaseUnits();
hwndCombo1 = CreateWindow(L"COMBOBOX", L"",
CBS_DROPDOWN | WS_CHILD | WS_VISIBLE,
(6 * LOWORD(dwBaseUnits)) / 4,
(2 * HIWORD(dwBaseUnits)) / 8,
(100 * LOWORD(dwBaseUnits)) / 4,
(50 * HIWORD(dwBaseUnits)) / 8,
hwnd, NULL, NULL, NULL);
hwndCombo2 = CreateWindow(L"COMBOBOX", L"",
CBS_DROPDOWN | WS_CHILD | WS_VISIBLE,
(112 * LOWORD(dwBaseUnits)) / 4,
(2 * HIWORD(dwBaseUnits)) / 8,
(100 * LOWORD(dwBaseUnits)) / 4,
(50 * HIWORD(dwBaseUnits)) / 8,
hwnd, NULL, hInst, NULL);
// Get the edit window handle to each combo box.
pt.x = 1;
pt.y = 1;
hwndEdit1 = ChildWindowFromPoint(hwndCombo1, pt);
hwndEdit2 = ChildWindowFromPoint(hwndCombo2, pt);
// Change the window procedure for both edit windows
// to the subclass procedure.
lpfnEditWndProc = (WNDPROC) SetWindowLongPtr(hwndEdit1,
GWLP_WNDPROC, (LONG_PTR) SubClassProc);
SetWindowLongPtr(hwndEdit2, GWLP_WNDPROC, (LONG_PTR) SubClassProc);
break;
case WM_SETFOCUS:
SetFocus(hwndCombo1);
break;
case WM_TAB:
if (GetFocus() == hwndEdit1)
SetFocus(hwndCombo2);
else
SetFocus(hwndCombo1);
break;
case WM_ESC:
hwndCombo = GetFocus() == hwndEdit1 ? hwndCombo1 : hwndCombo2;
// Clear the current selection.
SendMessage(hwndCombo, CB_SETCURSEL,
(WPARAM) (-1), 0);
// Set the focus to the main window.
SetFocus(hwndMain);
break;
case WM_ENTER:
hwndCombo = GetFocus() == hwndEdit1 ? hwndCombo1 : hwndCombo2;
SetFocus(hwndMain);
// If there is no current selection, set one.
if (SendMessage(hwndCombo, CB_GETCURSEL, 0, 0)
== CB_ERR)
{
if (SendMessage(hwndCombo, WM_GETTEXT,
sizeof(achTemp), (LPARAM) achTemp) == 0)
break; // Empty selection field
dwIndex = SendMessage(hwndCombo,
CB_FINDSTRINGEXACT, (WPARAM) (-1),
(LPARAM) achTemp);
// Add the string, if necessary, and select it.
if (dwIndex == CB_ERR)
dwIndex = SendMessage(hwndCombo, CB_ADDSTRING,
0, (LPARAM) achTemp);
if (dwIndex != CB_ERR)
SendMessage(hwndCombo, CB_SETCURSEL,
dwIndex, 0);
}
break;
// .
// . Process additional messages.
// .
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
/********************************************************
FUNCTION: SubClassProc
PURPOSE: Process TAB and ESCAPE keys, and pass all
other messages to the class window
procedure.
*********************************************************/
LRESULT CALLBACK SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_TAB:
SendMessage(hwndMain, WM_TAB, 0, 0);
return 0;
case VK_ESCAPE:
SendMessage(hwndMain, WM_ESC, 0, 0);
return 0;
case VK_RETURN:
SendMessage(hwndMain, WM_ENTER, 0, 0);
return 0;
}
break;
case WM_KEYUP:
case WM_CHAR:
switch (wParam)
{
case VK_TAB:
case VK_ESCAPE:
case VK_RETURN:
return 0;
}
}
// Call the original window procedure for default processing.
return CallWindowProc(lpfnEditWndProc, hwnd, msg, wParam, lParam);
}