W tym przykładzie przedstawiono sposób skonstruowania okno dialogowe, które pozwala użytkownikowi zmieniać akceleratora skojarzony element menu. Okno dialogowe składa się z pola kombi, zawierające elementy menu, pole kombi, zawierające nazwy kluczy i pola wyboru zaznaczenie ctrl, alt i klawisze shift. Na poniższej ilustracji przedstawiono okno dialogowe.
W poniższym przykładzie pokazano, w jaki sposób okno dialogowe jest zdefiniowany w pliku definicji zasobów.
EdAccelBox okno DIALOGOWE 5, 17, 193, 114 styl DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION CAPTION "Edytuj akceleratorów" Rozpocznij COMBOBOX IDD_MENUITEMS, 10, 22, 52, 53, CBS_SIMPLE | CBS_SORT | WS_VSCROLL |
WS_TABSTOP kontroli "Kontrolowanie", IDD_CNTRL, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 76, 35, 40, 10 kontroli "Alt", IDD_ALT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 76, 48, 40, 10 kontroli "Zmiana" IDD_SHIFT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 76, 61, 40, 10 COMBOBOX IDD_KEYSTROKES, 124, 22, 58, 58, CBS_SIMPLE | CBS_SORT | WS_VSCROLL |
WS_TABSTOP PUSHBUTTON "Ok", IDOK, 43, 92, 40, 14 PUSHBUTTON "Anuluj", IDCANCEL, 103, 92, 40, 14 LTEXT "wybierz pozycję:", 101 jak, 10, 12, 43, 8 LTEXT "Wybierz klawiszy:", 102, 123, 12, 60, koniec 8
Pasek menu aplikacji zawiera podmenu znak , którego elementy zostały akceleratorów z nimi związanych.
MainMenu MENU {POPUP "amp;Znak"{MENUITEM" & Regular\tF5 ", IDM_REGULAR MENUITEM" & Bold\tCtrl + B ", IDM_BOLD MENUITEM" & Italic\tCtrl + I ", IDM_ITALIC MENUITEM" & Underline\tCtrl + U ", IDM_ULINE}
} Akceleratory FontAccel {VK_F5, IDM_REGULAR, VIRTKEY IDM_BOLD, kontroli, "B", VIRTKEY "I", IDM_ITALIC, CONTROL, VIRTKEY "U", IDM_ULINE, kontroli, VIRTKEY}
Wartości elementu menu dla szablonu menu są stałe zdefiniowane następująco w pliku nagłówka aplikacji.
# define IDM_REGULAR 1100
# define IDM_BOLD 1200
# define IDM_ITALIC 1300
# define IDM_ULINE 1400
Okno dialogowe użyto tablicy zdefiniowanych przez aplikację VKEY struktur, każda zawierająca ciąg tekstowy naciśnięcia klawiszy i ciąg tekstowy akceleratora. Gdy tworzony jest okno dialogowe, analizuje tablicy i dodaje każdy ciąg klawiszy tekst do pola kombinaciśnięcie klawisza Wybierz. Gdy użytkownik kliknie przycisk OK , okno dialogowe wyszukuje ciąg zaznaczony tekst naciśnięcia klawiszy i pobiera odpowiednie akceleratora napisu. Okno dialogowe dołącza ciąg tekstowy pedału przyspieszenia do tekstu elementu menu, wybranego przez użytkownika. W poniższym przykładzie pokazano Tablica struktur VKEY :
/ / Obsługuje wyszukiwania VKey # define MAXKEYS 25 typedef struct _VKEYS {char * pKeyName;
char * pKeyString;
} VKEYS;
VKEYS vkeys [MAXKEYS] = {"BkSp", "Back Space", "PgUp" "Page Up", "PgDn" "Page Down", "End", "End", "Home", "Strona główna", "Lft", "Left", "Up", "Up", "Rgt", "Right", "Dn", "Down", "Dodatki", "Wstaw", "Del", "Usuwanie", "Mult", "Multiply", "Dodaj", "Dodaj", "Sub", "Odejmij", "DecPt", "Przecinka dziesiętnego", "Div", "Divide", "F2", "F2", "F3", "F3", "F5", "F5", "F6", "F6", "F7", "F7", "F8", "F8", "F9", "F9", "F11", "F11", "F12", "F12"}
Okno dialogowe inicjowania wypełnia pola kombi Wybierz element i Wybierz naciśnięć klawiszy . Po użytkownik wybierze element menu i skojarzonych akceleratora, okno dialogowe analizuje formantów w oknie dialogowym, aby uzyskać wybór użytkownika, aktualizacji tekstu elementu menu, a następnie tworzy nową tabelę akceleratora, która zawiera zdefiniowane przez użytkownika akceleratora nowych. W poniższym przykładzie przedstawiono procedurę okno dialogowe. Należy zauważyć, że należy zainicjować hwndMain
w procedurze okna.
// Global variables
HWND hwndMain; // handle to main window
HACCEL haccel; // handle to accelerator table
// Dialog-box procedure
BOOL CALLBACK EdAccelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int nCurSel; // index of list box item
UINT idItem; // menu-item identifier
UINT uItemPos; // menu-item position
UINT i, j = 0; // loop counters
static UINT cItems; // count of items in menu
char szTemp[32]; // temporary buffer
char szAccelText[32]; // buffer for accelerator text
char szKeyStroke[16]; // buffer for keystroke text
static char szItem[32]; // buffer for menu-item text
HWND hwndCtl; // handle to control window
static HMENU hmenu; // handle to "Character" menu
PCHAR pch, pch2; // pointers for string copying
WORD wVKCode; // accelerator virtual-key code
BYTE fAccelFlags; // fVirt flags for ACCEL structure
LPACCEL lpaccelNew; // address of new accelerator table
HACCEL haccelOld; // handle to old accelerator table
int cAccelerators; // number of accelerators in table
static BOOL fItemSelected = FALSE; // item selection flag
static BOOL fKeySelected = FALSE; // key selection flag
switch (uMsg)
{
case WM_INITDIALOG:
// Get the handle to the menu-item combo box.
hwndCtl = GetDlgItem(hwndDlg, IDD_MENUITEMS);
// Get the handle to the Character submenu and
// count the number of items it has. In this example,
// the menu has position 0. You must alter this value
// if you add additional menus.
hmenu = GetSubMenu(GetMenu(hwndMain), 0);
cItems = GetMenuItemCount(hmenu);
// Get the text of each item, strip out the '&' and
// the accelerator text, and add the text to the
// menu-item combo box.
for (i = 0; i < cItems; i++)
{
if (!(GetMenuString(hmenu, i, szTemp,
sizeof(szTemp), MF_BYPOSITION)))
continue;
for (pch = szTemp, pch2 = szItem; *pch != '\0'; )
{
if (*pch != '&')
{
if (*pch == '\t')
{
*pch = '\0';
*pch2 = '\0';
}
else *pch2++ = *pch++;
}
else pch++;
}
SendMessage(hwndCtl, CB_ADDSTRING, 0,
(LONG) (LPSTR) szItem);
}
// Now fill the keystroke combo box with the list of
// keystrokes that will be allowed for accelerators.
// The list of keystrokes is in the application-defined
// structure called "vkeys".
hwndCtl = GetDlgItem(hwndDlg, IDD_KEYSTROKES);
for (i = 0; i < MAXKEYS; i++)
{
SendMessage(hwndCtl, CB_ADDSTRING, 0,
(LONG) (LPSTR) vkeys[i].pKeyString);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDD_MENUITEMS:
// The user must select an item from the combo
// box. This flag is checked during IDOK
// processing to be sure a selection was made.
fItemSelected = TRUE;
return 0;
case IDD_KEYSTROKES:
// The user must select an item from the combo
// box. This flag is checked during IDOK
// processing to be sure a selection was made.
fKeySelected = TRUE;
return 0;
case IDOK:
// If the user has not selected a menu item
// and a keystroke, display a reminder in a
// message box.
if (!fItemSelected || !fKeySelected)
{
MessageBox(hwndDlg,
"Item or key not selected.", NULL,
MB_OK);
return 0;
}
// Determine whether the CTRL, ALT, and SHIFT
// keys are selected. Concatenate the
// appropriate strings to the accelerator-
// text buffer, and set the appropriate
// accelerator flags.
szAccelText[0] = '\0';
hwndCtl = GetDlgItem(hwndDlg, IDD_CNTRL);
if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0) == 1)
{
lstrcat(szAccelText, "Ctl+");
fAccelFlags |= FCONTROL;
}
hwndCtl = GetDlgItem(hwndDlg, IDD_ALT);
if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0) == 1)
{
lstrcat(szAccelText, "Alt+");
fAccelFlags |= FALT;
}
hwndCtl = GetDlgItem(hwndDlg, IDD_SHIFT);
if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0) == 1)
{
lstrcat(szAccelText, "Shft+");
fAccelFlags |= FSHIFT;
}
// Get the selected keystroke, and look up the
// accelerator text and the virtual-key code
// for the keystroke in the vkeys structure.
hwndCtl = GetDlgItem(hwndDlg, IDD_KEYSTROKES);
nCurSel = (int) SendMessage(hwndCtl,
CB_GETCURSEL, 0, 0);
SendMessage(hwndCtl, CB_GETLBTEXT,
nCurSel, (LONG) (LPSTR) szKeyStroke);
for (i = 0; i < MAXKEYS; i++)
{
if(lstrcmp(vkeys[i].pKeyString, szKeyStroke)
== 0)
{
lstrcpy(szKeyStroke, vkeys[i].pKeyName);
break;
}
}
// Concatenate the keystroke text to the
// "Ctl+","Alt+", or "Shft+" string.
lstrcat(szAccelText, szKeyStroke);
// Determine the position in the menu of the
// selected menu item. Menu items in the
// "Character" menu have positions 0,2,3, and 4.
if (lstrcmp(szItem, "Regular") == 0)
uItemPos = 0;
else if (lstrcmp(szItem, "Bold") == 0)
uItemPos = 2;
else if (lstrcmp(szItem, "Italic") == 0)
uItemPos = 3;
else if (lstrcmp(szItem, "Underline") == 0)
uItemPos = 4;
// Get the string that corresponds to the
// selected item.
GetMenuString(hmenu, uItemPos, szItem,
sizeof(szItem), MF_BYPOSITION);
// Append the new accelerator text to the
// menu-item text.
for (pch = szItem; *pch != '\t'; pch++);
++pch;
for (pch2 = szAccelText; *pch2 != '\0'; pch2++)
*pch++ = *pch2;
*pch = '\0';
// Modify the menu item to reflect the new
// accelerator text.
idItem = GetMenuItemID(hmenu, uItemPos);
ModifyMenu(hmenu, idItem, MF_BYCOMMAND |
MF_STRING, idItem, szItem);
// Reset the selection flags.
fItemSelected = FALSE;
fKeySelected = FALSE;
// Save the current accelerator table.
haccelOld = haccel;
// Count the number of entries in the current
// table, allocate a buffer for the table, and
// then copy the table into the buffer.
cAccelerators = CopyAcceleratorTable(
haccelOld, NULL, 0);
lpaccelNew = (LPACCEL) LocalAlloc(LPTR,
cAccelerators * sizeof(ACCEL));
if (lpaccelNew != NULL)
{
CopyAcceleratorTable(haccel, lpaccelNew,
cAccelerators);
}
// Find the accelerator that the user modified
// and change its flags and virtual-key code
// as appropriate.
for (i = 0; (lpaccelNew[i].cmd ==
(WORD) idItem)
&& (i < (UINT) cAccelerators); i++)
{
lpaccelNew[i].fVirt = fAccelFlags;
lpaccelNew[i].key = wVKCode;
}
// Create the new accelerator table, and
// destroy the old one.
DestroyAcceleratorTable(haccelOld);
haccel = CreateAcceleratorTable(lpaccelNew,
cAccelerators);
// Destroy the dialog box.
EndDialog(hwndDlg, TRUE);
return 0;
case IDCANCEL:
EndDialog(hwndDlg, TRUE);
return TRUE;
default:
break;
}
default:
break;
}
return FALSE;
}