Använda tangentbordsacceleratorer
Det här avsnittet beskriver uppgifter som är associerade med tangentbordsacceleratorer.
Använda en acceleratortabellresurs
Det vanligaste sättet att lägga till stöd för acceleratorer i ett program är att inkludera en acceleratortabellresurs med programmets körbara fil och sedan läsa in resursen vid körning.
Det här avsnittet täcker följande ämnen.
- Skapa acceleratortabellresursen
- läser in acceleratortabellresursen
- Anropa funktionen Translate Accelerator
- Bearbeta WM_COMMAND-meddelanden
- Förstör acceleratortabellens resurs
- Skapa acceleratorer för teckensnittsattribut
Skapa acceleratortabellresursen
Du skapar en acceleratortabellresurs med hjälp av ACCELERATORS--instruktionen i programmets resursdefinitionsfil. Du måste tilldela ett namn eller resursidentifierare till acceleratortabellen, helst till skillnad från någon annan resurs. Systemet använder den här identifieraren för att läsa in resursen under körning.
Varje accelerator som du definierar kräver en separat post i acceleratortabellen. I varje post definierar du tangenttryckningen (antingen en ASCII-teckenkod eller virtuell nyckelkod) som genererar acceleratorn och acceleratorns identifierare. Du måste också ange om tangenttryckningen måste användas i någon kombination med ALT-, SKIFT- eller CTRL-tangenterna. Mer information om virtuella nycklar finns i Tangentbordsindata.
En ASCII-tangenttryckning anges antingen genom att ASCII-tecknet omges av dubbla citattecken eller genom att använda heltalsvärdet för tecknet i kombination med ASCII-flaggan. I följande exempel visas hur du definierar ASCII-acceleratorer.
"A", ID_ACCEL1 ; SHIFT+A
65, ID_ACCEL2, ASCII ; SHIFT+A
En tangenttryckning för virtuell nyckel anges på olika sätt beroende på om tangenttryckningen är en alfanumerisk nyckel eller en icke-alfanumerisk nyckel. För en alfanumerisk nyckel kombineras nyckelns bokstav eller nummer, omgivet av dubbla citattecken, med flaggan VIRTKEY. För en icke-alfanumerisk nyckel kombineras den virtuella nyckelkoden för den specifika nyckeln med flaggan VIRTKEY. I följande exempel visas hur du definierar kodacceleratorer med virtuella nycklar.
"a", ID_ACCEL3, VIRTKEY ; A (caps-lock on) or a
VK_INSERT, ID_ACCEL4, VIRTKEY ; INSERT key
I följande exempel visas en resurs för snabbkommandotabell som definierar snabbkommandon för filåtgärder. Namnet på resursen är FileAccel.
FileAccel ACCELERATORS
BEGIN
VK_F12, IDM_OPEN, CONTROL, VIRTKEY ; CTRL+F12
VK_F4, IDM_CLOSE, ALT, VIRTKEY ; ALT+F4
VK_F12, IDM_SAVE, SHIFT, VIRTKEY ; SHIFT+F12
VK_F12, IDM_SAVEAS, VIRTKEY ; F12
END
Om du vill att användaren ska trycka på ALT-, SKIFT- eller CTRL-tangenterna i någon kombination med acceleratorns tangenttryckning anger du ALT-, SKIFT- och CONTROL-flaggorna i acceleratorns definition. Här följer några exempel.
"B", ID_ACCEL5, ALT ; ALT_SHIFT+B
"I", ID_ACCEL6, CONTROL, VIRTKEY ; CTRL+I
VK_F5, ID_ACCEL7, CONTROL, ALT, VIRTKEY ; CTRL+ALT+F5
När en acceleratornyckel som standard motsvarar ett menyalternativ markerar systemet menyalternativet. Du kan använda flaggan NOINVERT för att förhindra markering för en enskild accelerator. I följande exempel visas hur du använder flaggan NOINVERT:
VK_DELETE, ID_ACCEL8, VIRTKEY, SHIFT, NOINVERT ; SHIFT+DELETE
Om du vill definiera acceleratorer som motsvarar menyalternativ i ditt program inkluderar du acceleratorerna i texten i menyalternativen. I följande exempel visas hur du inkluderar acceleratorer i menyobjekttext i en resursdefinitionsfil.
FilePopup MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New..", IDM_NEW
MENUITEM "&Open\tCtrl+F12", IDM_OPEN
MENUITEM "&Close\tAlt+F4" IDM_CLOSE
MENUITEM "&Save\tShift+F12", IDM_SAVE
MENUITEM "Save &As...\tF12", IDM_SAVEAS
END
END
Laddar resurs för acceleratortabell
Ett program läser in en acceleratortabellresurs genom att anropa funktionen LoadAccelerators och ange instanshandtaget för programmet vars körbara fil innehåller resursen och resursens namn eller identifierare. LoadAccelerators läser in den angivna acceleratortabellen i minnet och returnerar handtaget till acceleratortabellen.
Ett program kan när som helst läsa in en acceleratortabellresurs. Vanligtvis läser ett entrådat program in sin acceleratortabell innan det anger huvudmeddelandeloopen. Ett program som använder flera trådar läser vanligtvis in acceleratortabellresursen för en tråd innan den går in i meddelandeloopen för tråden. Ett program eller en tråd kan också använda flera acceleratortabeller, var och en associerad med ett visst fönster i programmet. Ett sådant program skulle läsa in acceleratortabellen för fönstret varje gång användaren aktiverade fönstret. Mer information om trådar finns i Processer och trådar.
Anropa Translate Accelerator-funktionen
För att bearbeta acceleratorer måste ett programs (eller trådens) meddelandeloop innehålla ett anrop till funktionen TranslateAccelerator. TranslateAccelerator jämför tangenttryckningar med en acceleratortabell och, om den hittar en matchning, översätter tangenttryckningarna till ett WM_COMMAND -meddelande (eller WM_SYSCOMMAND). Funktionen skickar sedan meddelandet till en fönsterprocedur. Parametrarna för funktionen TranslateAccelerator inkluderar handtaget till fönstret som ska ta emot de WM_COMMAND meddelanden, handtaget till acceleratortabellen som används för att översätta acceleratorer och en pekare till en MSG struktur som innehåller ett meddelande från kön. I följande exempel visas hur du anropar TranslateAccelerator inifrån en meddelandeloop.
MSG msg;
BOOL bRet;
while ( (bRet = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
// Check for accelerator keystrokes.
if (!TranslateAccelerator(
hwndMain, // handle to receiving window
haccel, // handle to active accelerator table
&msg)) // message data
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Bearbeta WM_COMMAND meddelanden
När en accelerator används får fönstret som anges i funktionen TranslateAccelerator ett WM_COMMAND- eller WM_SYSCOMMAND-meddelande. Lågordningsordet i parametern wParam innehåller acceleratorns identifierare. Fönsterproceduren undersöker identifieraren för att fastställa källan till det WM_COMMAND meddelandet och bearbeta meddelandet därefter.
Om en accelerator vanligtvis motsvarar ett menyalternativ i programmet tilldelas acceleratorn och menyalternativet samma identifierare. Om du behöver veta om ett WM_COMMAND meddelande har genererats av en accelerator eller av ett menyalternativ, kan du granska den högre ordningen av ordet i wParam parametern. Om en accelerator genererade meddelandet är högordningsordet 1. Om ett menyalternativ genererade meddelandet är det högordade ordet 0.
Förstöra acceleratorns tabellresurs
Systemet förstör automatiskt acceleratortabellresurser som läses in av funktionen LoadAccelerators och tar bort resursen från minnet när programmet har stängts.
Skapa acceleratorer för teckensnittsattribut
Exemplet i det här avsnittet visar hur du utför följande uppgifter:
- Skapa en resurs för acceleratortabell.
- Läs in acceleratortabellen vid körning.
- Översätt acceleratorer i en meddelandeloop.
- Bearbeta WM_COMMAND meddelanden som genereras av acceleratorerna.
Dessa uppgifter demonstreras i kontexten av en applikation som innehåller en Tecken--meny och tillhörande snabbkommandon som tillåter användaren att välja attribut för det aktuella teckensnittet.
Följande del av en resursdefinitionsfil definierar menyn Tecken och den associerade acceleratortabellen. Observera att menyalternativen visar tangenttryckningar för acceleratorn och att varje accelerator har samma identifierare som dess associerade menyalternativ.
#include <windows.h>
#include "acc.h"
MainMenu MENU
{
POPUP "&Character"
{
MENUITEM "&Regular\tF5", IDM_REGULAR
MENUITEM "&Bold\tCtrl+B", IDM_BOLD
MENUITEM "&Italic\tCtrl+I", IDM_ITALIC
MENUITEM "&Underline\tCtrl+U", IDM_ULINE
}
}
FontAccel ACCELERATORS
{
VK_F5, IDM_REGULAR, VIRTKEY
"B", IDM_BOLD, CONTROL, VIRTKEY
"I", IDM_ITALIC, CONTROL, VIRTKEY
"U", IDM_ULINE, CONTROL, VIRTKEY
}
Följande avsnitt i programmets källfil visar hur du implementerar acceleratorerna.
HWND hwndMain; // handle to main window
HANDLE hinstAcc; // handle to application instance
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // application messages
BOOL bRet; // for return value of GetMessage
HACCEL haccel; // handle to accelerator table
// Perform the initialization procedure.
// Create a main window for this application instance.
hwndMain = CreateWindowEx(0L, "MainWindowClass",
"Sample Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hinst, NULL );
// If a window cannot be created, return "failure."
if (!hwndMain)
return FALSE;
// Make the window visible and update its client area.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Load the accelerator table.
haccel = LoadAccelerators(hinstAcc, "FontAccel");
if (haccel == NULL)
HandleAccelErr(ERR_LOADING); // application defined
// Get and dispatch messages until a WM_QUIT message is
// received.
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
// Check for accelerator keystrokes.
if (!TranslateAccelerator(
hwndMain, // handle to receiving window
haccel, // handle to active accelerator table
&msg)) // message data
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return msg.wParam;
}
LRESULT APIENTRY MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BYTE fbFontAttrib; // array of font-attribute flags
static HMENU hmenu; // handle to main menu
switch (uMsg)
{
case WM_CREATE:
// Add a check mark to the Regular menu item to
// indicate that it is the default.
hmenu = GetMenu(hwndMain);
CheckMenuItem(hmenu, IDM_REGULAR, MF_BYCOMMAND |
MF_CHECKED);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
// Process the accelerator and menu commands.
case IDM_REGULAR:
case IDM_BOLD:
case IDM_ITALIC:
case IDM_ULINE:
// GetFontAttributes is an application-defined
// function that sets the menu-item check marks
// and returns the user-selected font attributes.
fbFontAttrib = GetFontAttributes(
(BYTE) LOWORD(wParam), hmenu);
// SetFontAttributes is an application-defined
// function that creates a font with the
// user-specified attributes the font with
// the main window's device context.
SetFontAttributes(fbFontAttrib);
break;
default:
break;
}
break;
// Process other messages.
default:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
}
Använda en acceleratortabell som skapats vid körningstid
I det här avsnittet beskrivs hur du använder acceleratortabeller som skapats vid körning.
- Skapa en Run-Time acceleratortabell
- Acceleratorer för bearbetning
- Förstöra en Run-Time acceleratortabell
- Skapa användarredigerbara acceleratorer
Skapa en Run-Time-acceleratortabell
Det första steget när du skapar en acceleratortabell vid körningstid är att fylla i en matris med ACCEL- strukturer. Varje struktur i matrisen definierar en accelerator i tabellen. En acceleratordefinition innehåller dess flaggor, dess nyckel och dess identifierare. Den ACCEL- strukturen har följande formulär.
typedef struct tagACCEL { // accl
BYTE fVirt;
WORD key;
WORD cmd;
} ACCEL;
Du definierar en accelerators tangenttryckning genom att ange en ASCII-teckenkod eller en virtuell nyckelkod i nyckel medlem i ACCEL- struktur. Om du anger en kod för virtuell nyckel måste du först inkludera flaggan FVIRTKEY i fVirt medlem. annars tolkar systemet koden som en ASCII-teckenkod. Du kan inkludera flaggan FCONTROL, FALTeller FSHIFT eller alla tre för att kombinera CTRL-, ALT- eller SKIFT-tangenten med tangenttryckningen.
Om du vill skapa acceleratortabellen skickar du en pekare till matrisen med ACCEL- strukturer till funktionen CreateAcceleratorTable. CreateAcceleratorTable skapar acceleratortabellen och returnerar handtaget till tabellen.
Bearbetningsacceleratorer
Processen med att ladda och anropa acceleratorer som tillhandahålls av en acceleratortabell som skapas i körningstid är densamma som att bearbeta de som tillhandahålls av en acceleratortabellresurs. Mer information finns i Läsa in acceleratortabellresursen fram till Bearbeta WM_COMMAND-meddelanden.
Förstöra en Run-Time accelerator-tabell
Systemet förstör automatiskt acceleratortabeller som skapas vid körning, vilket tar bort resurserna från minnet när programmet har stängts. Du kan förstöra en acceleratortabell och ta bort den från minnet tidigare genom att skicka tabellens handtag till funktionen DestroyAcceleratorTable.
Skapa acceleratorer som kan redigeras av användare
Det här exemplet visar hur du skapar en dialogruta som gör att användaren kan ändra acceleratorn som är associerad med ett menyalternativ. Dialogrutan består av en kombinationsruta som innehåller menyalternativ, en kombinationsruta som innehåller namnen på nycklar och kryssrutor för att markera TANGENTERNA CTRL, ALT och SKIFT. Följande bild visar dialogrutan.
I följande exempel visas hur dialogrutan definieras i resursdefinitionsfilen.
EdAccelBox DIALOG 5, 17, 193, 114
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Edit Accelerators"
BEGIN
COMBOBOX IDD_MENUITEMS, 10, 22, 52, 53,
CBS_SIMPLE | CBS_SORT | WS_VSCROLL |
WS_TABSTOP
CONTROL "Control", IDD_CNTRL, "Button",
BS_AUTOCHECKBOX | WS_TABSTOP,
76, 35, 40, 10
CONTROL "Alt", IDD_ALT, "Button",
BS_AUTOCHECKBOX | WS_TABSTOP,
76, 48, 40, 10
CONTROL "Shift", 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 "Cancel", IDCANCEL, 103, 92, 40, 14
LTEXT "Select Item:", 101, 10, 12, 43, 8
LTEXT "Select Keystroke:", 102, 123, 12, 60, 8
END
Programmets menyrad innehåller en Tecken undermeny vars objekt har acceleratorer associerade med dem.
MainMenu MENU
{
POPUP "&Character"
{
MENUITEM "&Regular\tF5", IDM_REGULAR
MENUITEM "&Bold\tCtrl+B", IDM_BOLD
MENUITEM "&Italic\tCtrl+I", IDM_ITALIC
MENUITEM "&Underline\tCtrl+U", IDM_ULINE
}
}
FontAccel ACCELERATORS
{
VK_F5, IDM_REGULAR, VIRTKEY
"B", IDM_BOLD, CONTROL, VIRTKEY
"I", IDM_ITALIC, CONTROL, VIRTKEY
"U", IDM_ULINE, CONTROL, VIRTKEY
}
Menyalternativets värden för menymallen är konstanter som definieras enligt följande i programmets huvudfil.
#define IDM_REGULAR 1100
#define IDM_BOLD 1200
#define IDM_ITALIC 1300
#define IDM_ULINE 1400
I dialogrutan används en matris med programdefinierade VKEY-strukturer som var och en innehåller en tangenttryckningstextsträng och en acceleratortextsträng. När dialogrutan skapas parsar den matrisen och lägger till varje tangenttryckningstextsträng i kombinationsrutan Välj tangenttryckning. När användaren klickar på knappen OK letar dialogrutan upp den markerade tangenttryckningstextsträngen och hämtar motsvarande acceleratortextsträng. Dialogrutan lägger till acceleratortextsträngen till texten i menyalternativet som användaren har valt. I följande exempel visas matrisen med VKEY-strukturer:
// VKey Lookup Support
#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", "Home",
"Lft", "Left",
"Up", "Up",
"Rgt", "Right",
"Dn", "Down",
"Ins", "Insert",
"Del", "Delete",
"Mult", "Multiply",
"Add", "Add",
"Sub", "Subtract",
"DecPt", "Decimal Point",
"Div", "Divide",
"F2", "F2",
"F3", "F3",
"F5", "F5",
"F6", "F6",
"F7", "F7",
"F8", "F8",
"F9", "F9",
"F11", "F11",
"F12", "F12"
};
Dialogrutans initieringsprocedur fyller kombinationsrutorna Välj objekt och Välj tangenttryckning. När användaren har valt ett menyalternativ och tillhörande accelerator undersöker dialogrutan kontrollerna i dialogrutan för att hämta användarens val, uppdaterar texten i menyalternativet och skapar sedan en ny acceleratortabell som innehåller den användardefinierade nya acceleratorn. I följande exempel visas dialogrutans procedur. Observera att du måste initiera i fönsterproceduren.
// 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; // pointer to 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
HRESULT hr;
INT numTCHAR; // TCHARs in listbox text
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)/sizeof(TCHAR), 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)
{
hr = StringCchCat(szAccelText, 32, "Ctl+");
if (FAILED(hr))
{
// TODO: write error handler
}
fAccelFlags |= FCONTROL;
}
hwndCtl = GetDlgItem(hwndDlg, IDD_ALT);
if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0) == 1)
{
hr = StringCchCat(szAccelText, 32, "Alt+");
if (FAILED(hr))
{
// TODO: write error handler
}
fAccelFlags |= FALT;
}
hwndCtl = GetDlgItem(hwndDlg, IDD_SHIFT);
if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0) == 1)
{
hr = StringCchCat(szAccelText, 32, "Shft+");
if (FAILED(hr))
{
// TODO: write error handler
}
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);
numTCHAR = SendMessage(hwndCtl, CB_GETLBTEXTLEN,
nCursel, 0);
if (numTCHAR <= 15)
{
SendMessage(hwndCtl, CB_GETLBTEXT,
nCurSel, (LONG) (LPSTR) szKeyStroke);
}
else
{
// TODO: writer error handler
}
for (i = 0; i < MAXKEYS; i++)
{
//
// lstrcmp requires that both parameters are
// null-terminated.
//
if(lstrcmp(vkeys[i].pKeyString, szKeyStroke)
== 0)
{
hr = StringCchCopy(szKeyStroke, 16, vkeys[i].pKeyName);
if (FAILED(hr))
{
// TODO: write error handler
}
break;
}
}
// Concatenate the keystroke text to the
// "Ctl+","Alt+", or "Shft+" string.
hr = StringCchCat(szAccelText, 32, szKeyStroke);
if (FAILED(hr))
{
// TODO: write error handler
}
// Determine the position in the menu of the
// selected menu item. Menu items in the
// "Character" menu have positions 0,2,3, and 4.
// Note: the lstrcmp parameters must be
// null-terminated.
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)/sizeof(TCHAR), 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; i < (UINT) cAccelerators; i++)
{
if (lpaccelNew[i].cmd == (WORD) idItem)
{
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;
}