Hogyan lehet egy kombinált listát leszármaztatni?
Ez a témakör bemutatja, hogyan alosztályozza a kombinált listákat. A C++ példaalkalmazás létrehoz egy eszköztárablakot, amely két kombinált listát tartalmaz. A kombinált listák szerkesztési vezérlőinek alosztályozásával az eszköztárablak elfogja a TAB, ENTER és ESC billentyűket, amelyeket egyébként figyelmen kívül hagyna.
Amit tudnia kell
Technológiák
Előfeltételek
- C/C++
- Windows felhasználói felület programozása
Előírás
A WM_CREATE üzenet feldolgozása
Az alkalmazás feldolgozza a WM_CREATE üzenetet, hogy gyermekablakként két kombinált listavezérlőt hozzon létre.
// 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);
Az alkalmazás ezután alosztályozza a szerkesztési vezérlőket (kijelölési mezőket) az egyes kombinált listákban, mert az egyszerű és legördülő kombinált lista karakterbemenetét kapják. Végül meghívja a ChildWindowFromPoint függvényt, hogy lekérje a leírót az egyes szerkesztési vezérlőkhöz.
A szerkesztési vezérlők alosztályához az alkalmazás meghívja a SetWindowLong függvényt, a mutatót az osztályablak-eljárásra cserélve egy mutatót az alkalmazás által definiált SubClassProc függvényre. Az eredeti ablak eljárására mutató mutató az lpfnEditWndProc globális változóban lesz mentve.
SubClassProc elfogja a TAB, ENTER és ESC billentyűket, és alkalmazás által definiált üzenetek (WM_TAB, WM_ESC és WM_ENTER) küldésével értesíti az eszköztárablakot. SubClassProc a CallWindowProc függvénnyel továbbítja a legtöbb üzenetet az eredeti ablak eljárásnak, lpfnEditWndProc.
// 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);
A WM_SETFOCUS üzenet feldolgozása
Amikor az eszköztárablak megkapja a bemeneti fókuszt, azonnal az eszköztár első kombinált mezőjére állítja a fókuszt. Ehhez a példa meghívja a SetFocus függvényt a WM_SETFOCUS üzenetre válaszul.
case WM_SETFOCUS:
SetFocus(hwndCombo1);
break;
Üzenetek feldolgozása Application-Defined
A SubClassProc függvény alkalmazás által definiált üzeneteket küld az eszköztár ablakába, amikor a felhasználó lenyomja a TAB, ENTER vagy ESC billentyűt egy kombinált listában. A WM_TAB üzenet a TAB billentyűhöz, az ESC-kulcs WM_ESC üzenetéhez és az ENTER-kulcs WM_ENTER üzenetéhez lesz elküldve.
A példa úgy dolgozza fel a WM_TAB üzenetet, hogy a fókuszt az eszköztár következő kombinált mezőjére állítja. A WM_ESC üzenetet úgy dolgozza fel, hogy a fókuszt a fő alkalmazásablakra állítja.
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;
A WM_ENTER üzenetre válaszul a példa biztosítja, hogy a kombinált lista aktuális kijelölése érvényes legyen, majd a fókuszt a fő alkalmazásablakra állítsa. Ha a kombinált lista nem tartalmaz aktuális kijelölést, a példa a CB_FINDSTRINGEXACT üzenetben keres egy olyan listaelemet, amely megfelel a kijelölési mező tartalmának. Ha van egyezés, a példa beállítja az aktuális kijelölést; ellenkező esetben új listaelemet ad hozzá.
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);
Teljes példa
Az alábbiakban az eszköztár ablakeljárását és a két kombinált lista alosztályának eljárását követjük.
#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);
}
Kapcsolódó témakörök