Unterklassifizierung eines Kombinationsfelds
In diesem Thema wird veranschaulicht, wie Kombinationsfelder untergeordnet werden. Die C++-Beispielanwendung erstellt ein Symbolleistenfenster, das zwei Kombinationsfelde enthält. Durch Unterklassen der Bearbeitungssteuerelemente in den Kombinationsfelden fängt das Symbolleistenfenster TAB-, EINGABETASTE- und ESC-Schlüssel ab, die andernfalls ignoriert würden.
Wichtige Informationen
Technologien
Voraussetzungen
- C/C++
- Programmierung der Windows-Benutzeroberfläche
Anweisungen
Verarbeiten der WM_CREATE-Nachricht
Die Anwendung verarbeitet die WM_CREATE-Nachricht , um zwei Kombinationsfeldsteuerelemente 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 unterklassiert dann die Bearbeitungssteuerelemente (Auswahlfelder) in jedem Kombinationsfeld, da sie die Zeicheneingabe für das einfache Kombinationsfeld und das Dropdown-Kombinationsfeld erhalten. Schließlich wird die ChildWindowFromPoint-Funktion aufgerufen, um das Handle für jedes Bearbeitungssteuerelement abzurufen.
Zum Unterklassen der Bearbeitungssteuerelemente 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-, ENTER- und ESC-Schlüssel ab und benachrichtigt das Symbolleistenfenster durch Senden von anwendungsdefinierte 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 empfängt, wird der Fokus sofort auf das erste Kombinationsfeld in der Symbolleiste festgelegt. Dazu ruft das Beispiel die SetFocus-Funktion als Antwort 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-, EINGABETASTE- oder ESC-TASTE in einem Kombinationsfeld drückt. Die WM_TAB Nachricht wird für die TAB-Taste, die WM_ESC Nachricht für den ESC-Schlüssel und die WM_ENTER Nachricht für die EINGABETASTE gesendet.
Im Beispiel wird die WM_TAB-Nachricht verarbeitet, indem der Fokus auf das nächste Kombinationsfeld auf der Symbolleiste festgelegt wird. Es verarbeitet die WM_ESC-Nachricht, indem der Fokus auf das Standard Anwendungsfenster 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_ENTER Meldung stellt das Beispiel sicher, dass die aktuelle Auswahl für das Kombinationsfeld gültig ist, und legt dann den Fokus auf das Standard Anwendungsfensters fest. Wenn das Kombinationsfeld keine aktuelle Auswahl enthält, wird im Beispiel die CB_FINDSTRINGEXACT Nachricht 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 Fensterprozeduren für die Symbolleiste und die Unterklassenprozedur für die beiden Kombinationsfelde 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);
}
Zugehörige Themen