创建用户可编辑加速器

【勇芳软件工作室】汉化HomePreviousNext

此示例显示如何构建一个允许用户更改与菜单项相关联的加速器的对话框。对话框由包含菜单项的组合框,包含键名称的组合框以及用于选择CTRL,ALT和SHIFT键的复选框组成。下图显示对话框。

以下示例显示如何在资源定义文件中定义对话框。

EdAccelBox对话框5,17,193,114

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION

CAPTION“编辑加速器”

BEGIN

COMBOBOX IDD_MENUITEMS, 10, 22, 52, 53,

CBS_SIMPLE | CBS_SORT | WS_VSCROLL |

WS_TABSTOP

控制“控制”,IDD_CNTRL,“按钮”,

BS_AUTOCHECKBOX | WS_TABSTOP,

76, 35, 40, 10

CONTROL “Alt” 键IDD_ALT, “按钮”

BS_AUTOCHECKBOX | WS_TABSTOP,

76, 48, 40, 10

控制“Shift”,IDD_SHIFT,“按钮”,

BS_AUTOCHECKBOX | WS_TABSTOP,

76, 61, 40, 10

COMBOBOX IDD_KEYSTROKES, 124, 22, 58, 58,

CBS_SIMPLE | CBS_SORT | WS_VSCROLL |

WS_TABSTOP

按钮 “OK”,IDOK,43,92,40,14

PUSHBUTTON“取消”,IDCANCEL,103,92,40,14

LTEXT“选择项目:”,101,10,12,43,8

LTEXT“选择击键:”,102,123,12,60,8

END

该对话框使用一组应用程序定义的VKEY结构,每个结构包含一个按键文本字符串和一个加速器文本字符串。当创建对话框时,它解析数组,并将每个按键文本字符串添加到“选择键击”组合框中。当用户单击Ok按钮时,对话框将查找所选的按键文本字符串并检索相应的加速器文本字符串。对话框将加速器文本字符串附加到用户选择的菜单项的文本。以下示例显示了VKEY结构的数组:

/ * VKey查询支持* /

#define MAXKEYS 26

typedef struct _VKEYS {en

char *pKeyName;

char *pKeyString;

} VKEYS;

VKEYS vkeys[MAXKEYS] = {

“BkSp”,“Back Space”,

“PgUp”,“Page Up”,

“PgDn”,“Page Down”,

“结束”,“结束”,

“家”,“家”,

“Lft”,“Left”,

“上”,“上”

“Rgt”,“Right”,

“Dn”,“Down”,

“Ins”,“Insert”,

“删除”,“删除”

“好”,“乘法”

“添加”,“添加”,

“子”,“减”

“DecPt”,“小数点”,

“Div”,“Divide”,

"F2", "F2",

"F3", "F3",

"F5", "F5",

"F6", "F6",

"F7", "F7",

"F8", "F8",

"F9", "F9",

"F11", "F11",

"F12", "F12"

};

对话框的初始化过程将填充“选择项目”和“选择击键”组合框。在用户选择菜单项和关联的加速器之后,对话框将检查对话框中的控件以获取用户的选择,更新菜单项的文本,然后创建一个新的加速表,其中包含用户定义的新加速器。以下示例显示对话框过程。

/ *全局变量* /

HWND hwndMain; /* handle of main window */

HANDLE hinstAcc; /* handle of application instance */

HACCEL haccel; /* handle of accelerator table */

.

.

.

/ *对话框程序* /

LRESULT CALLBACK EdAccelProc(hwndDlg,uMsg,wParam,lParam)

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 of control window */

static HMENU hmenu; /* handle of "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 accel. table */

HACCEL haccelOld; /* handle of old accel. table */

int cAccelerators; /* number of accelerators in table */

static BOOL fItemSelected = FALSE; /* item selection flag */

static BOOL fKeySelected = FALSE; /* key selection flag */

开关(uMsg){

case WM_INITDIALOG:

/ *获取菜单项组合框的句柄。*/

hwndCtl = GetDlgItem(hwndDlg, IDD_MENUITEMS);

/*

*应用程序的菜单栏包含“Character”

*子菜单的项目具有加速器相关联

* 跟他们。获取“角色”的句柄

*子菜单(其主菜单中的位置为2),

*并计数其数量。

*/

hmenu = GetSubMenu(GetMenu(hwndMain), 2);

cItems = GetMenuItemCount(hmenu);

/*

*获取每个项目的文本,删除“&”和

*加速器文本,并将文本添加到

*菜单项组合框。

*/

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';

}

其他

*pch2++ = *pch++;

}

其他

pch++;

}

SendMessage(hwndCtl,CB_ADDSTRING,0,

(LONG) (LPSTR) szItem);

}

/*

*现在填写击键组合框中的列表

*加速器允许的按键。

*击键列表在应用程序定义中

*结构称为“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:

开关(LOWORD(wParam)){

case IDD_MENUITEMS:

/*

*用户必须从菜单中选择一个项目 -

*项目组合框。此标志被检查

* IDOK处理以确保进行了选择。

*/

fItemSelected = TRUE;

return 0;

case IDD_KEYSTROKES:

/*

*用户必须从菜单中选择一个项目 -

*项目组合框。此标志被检查

* IDOK处理以确保进行了选择。

*/

fKeySelected = TRUE;

return 0;

case IDOK:

/*

*如果用户没有选择菜单项

*和按键,在a中显示提醒

*消息框。

*/

if(!fItemSelected ||!fKeySelected){

MessageBox(hwndDlg,

“项目或密钥未选择”,NULL,

MB_OK);

return 0;

}

/*

*确定CTRL,ALT和SHIFT

*键被选中。连接

*适当的字符串加速器 -

*文本缓冲区,并设置相应的

*加速器标志。

*/

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;

}

/*

*获取所选的按键,并查找

*加速器文本和虚拟键代码

*用于vkeys结构中的按键。

*/

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;

}

}

/*

*将击键文本连接到

*“Ctl +”,“Alt +”或“Shft +”字符串。

*/

lstrcat(szAccelText, szKeyStroke);

/*

*确定菜单中的位置

*选择菜单项。菜单中的项目

*“角色”菜单有位置0,2,3和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;

/*

*获取对应的字符串

*选定项目。

*/

GetMenuString(HMENU,uItemPos,szItem,

sizeof(szItem), MF_BYPOSITION);

/*

*附加新的加速器文本

*菜单项文本。

*/

for (pch = szItem; *pch != '\t'; pch++);

++pch;

for (pch2 = szAccelText; *pch2 != '\0';

PCH2 ++)

*pch++ = *pch2;

*pch = '\0';

/*

*修改菜单项以反映新的

*加速器文本。

*/

idItem = GetMenuItemID(hmenu, uItemPos);

ModifyMenu(hmenu,idItem,MF_BYCOMMAND |

MF_STRING, idItem, szItem);

/ *复位选择标志。*/

fItemSelected = FALSE;

fKeySelected = FALSE;

/ *保存当前加速表。*/

haccelOld = haccel;

/*

*计算当前的条目数

*表,为表分配一个缓冲区,和

*然后将表复制到缓冲区。

*/

cAccelerators = CopyAcceleratorTable(

haccelOld, NULL, 0);

lpaccelNew = (LPACCEL) LocalAlloc(LPTR,

cAccelerators * sizeof(ACCEL));

if (lpaccelNew != NULL)

CopyAcceleratorTable(HACCEL,lpaccelNew,

cAccelerators);

/*

*查找用户修改的加速器

*并更改其标志和虚拟键代码

* 作为适当的。

*/

for (i = 0; (lpaccelNew[i].cmd ==

(WORD)idItem)

&& (i < (UINT) cAccelerators); i++) {

lpaccelNew[i].fVirt = fAccelFlags;

lpaccelNew[i].key = wVKCode;

}

/*

*创建新的加速器表,和

*摧毁旧的。

*/

DestroyAcceleratorTable(haccelOld);

haccel = CreateAcceleratorTable(lpaccelNew,

cAccelerators);

/ *销毁对话框。*/

EndDialog(hwndDlg, TRUE);

return 0;

case IDCANCEL:

EndDialog(hwndDlg, TRUE);

return TRUE;

默认:

break;

}

默认:

break;

}

return FALSE;

}