Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu bölüm, klavye hızlandırıcılarıyla ilişkili görevleri kapsar.
- Hızlandırıcı Tablo Kaynağı Kullanma
- Çalışma Zamanında Oluşturulan Hızlandırıcı Tablosunun Kullanılması
Hızlandırıcı Tablo Kaynağı Kullanma
Uygulamaya hızlandırıcı desteği eklemenin en yaygın yolu, uygulamanın yürütülebilir dosyasıyla bir hızlandırıcı tablosu kaynağı eklemek ve ardından kaynağı çalışma zamanında yüklemektir.
Bu bölümde aşağıdaki konular ele alınır.
- Hızlandırıcı Tablosu Kaynağını Oluşturma
- Hızlandırıcı Tablosu Kaynak Yükleme
- Translate Accelerator İşlevini Çağırma
- WM_COMMAND İletilerini İşleme
- Hızlandırıcı Tablosu Kaynağını Yok Etme
- Yazı Tipi Öznitelikleri için Hızlandırıcı oluşturma
Hızlandırıcı Tablo Kaynağı Oluşturma
Uygulamanızın kaynak tanımı dosyasındaki ACCELERATORS deyimini kullanarak bir accelerator-table kaynağı oluşturursunuz. Tercihen diğer kaynaklardan farklı olarak hızlandırıcı tablosuna bir ad veya kaynak tanımlayıcısı atamanız gerekir. Sistem, kaynağı çalışma zamanında yüklemek için bu tanımlayıcıyı kullanır.
Tanımladığınız her hızlandırıcı, hızlandırıcı tablosunda ayrı bir giriş gerektirir. Her girişte, hızlandırıcıyı ve hızlandırıcının tanımlayıcısını oluşturan tuş vuruşunu (ASCII karakter kodu veya sanal anahtar kodu) tanımlarsınız. Tuş vuruşunun ALT, SHIFT veya CTRL tuşlarıyla birlikte kullanılması gerekip gerekmediğini de belirtmelisiniz. Sanal tuşlar hakkında daha fazla bilgi için bkz. Klavye Girişi.
ASCII tuş vuruşu, ASCII karakteri çift tırnak içine alınarak veya ASCII bayrağıyla birlikte karakterin tamsayı değeri kullanılarak belirtilir. Aşağıdaki örneklerde ASCII hızlandırıcılarının nasıl tanımlanacağı gösterilmektedir.
"A", ID_ACCEL1 ; SHIFT+A
65, ID_ACCEL2, ASCII ; SHIFT+A
Sanal anahtar kodu tuş vuruşu, tuş vuruşunun alfasayısal anahtar mı yoksa alfasayısal olmayan bir anahtar mı olduğuna bağlı olarak farklı şekilde belirtilir. Alfasayısal anahtar için, anahtarın çift tırnak içine alınmış harfi veya numarası, VIRTKEY bayrağıyla birleştirilir. Alfasayısal olmayan bir anahtar için, belirli bir anahtarın sanal anahtar kodu VIRTKEY bayrağıyla birleştirilir. Aşağıdaki örneklerde sanal anahtar kod hızlandırıcılarının nasıl tanımlanacağı gösterilmektedir.
"a", ID_ACCEL3, VIRTKEY ; A (caps-lock on) or a
VK_INSERT, ID_ACCEL4, VIRTKEY ; INSERT key
Aşağıdaki örnekte, dosya işlemleri için hızlandırıcıları tanımlayan bir accelerator-table kaynağı gösterilmektedir. Kaynağın adı 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
Kullanıcının kısayol tuş vuruşuyla birlikte ALT, SHIFT veya CTRL tuşlarına basmasını istiyorsanız, hızlandırıcının tanımında ALT, SHIFT ve CONTROL bayraklarını belirtin. Aşağıda bazı örnekler verilmiştir.
"B", ID_ACCEL5, ALT ; ALT_SHIFT+B
"I", ID_ACCEL6, CONTROL, VIRTKEY ; CTRL+I
VK_F5, ID_ACCEL7, CONTROL, ALT, VIRTKEY ; CTRL+ALT+F5
Varsayılan olarak, bir hızlandırıcı tuşu bir menü öğesine karşılık geldiğinde sistem menü öğesini vurgular. Tek bir hızlandırıcının vurgulanmasını önlemek için NOINVERT bayrağını kullanabilirsiniz. Aşağıdaki örnekte NOINVERT bayrağının nasıl kullanılacağı gösterilmektedir:
VK_DELETE, ID_ACCEL8, VIRTKEY, SHIFT, NOINVERT ; SHIFT+DELETE
Uygulamanızdaki menü öğelerine karşılık gelen hızlandırıcıları tanımlamak için, hızlandırıcıları menü öğelerinin metnine ekleyin. Aşağıdaki örnekte, kaynak tanımı dosyasındaki menü öğesi metnine hızlandırıcıların nasıl dahil olduğu gösterilmektedir.
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
Hızlandırıcı Tablo Kaynağını Yükleme
Uygulama, LoadAccelerators işlevini çağırarak, kaynağı içeren yürütülebilir dosyayla ilişkili uygulamanın örnek tutamacını ve kaynağın adını veya tanımlayıcısını belirterek hızlandırıcı tablo kaynağını yükler. LoadAccelerators belirtilen hızlandırıcı tablosunu belleğe yükler ve tanıtıcıyı hızlandırıcı tablosuna döndürür.
Bir uygulama herhangi bir zamanda bir hızlandırıcı tablosu kaynağı yükleyebilir. Genellikle tek iş parçacıklı bir uygulama, ana ileti döngüsüne girmeden önce hızlandırıcı tablosunu yükler. Birden çok iş parçacığı kullanan bir uygulama, genellikle her iş parçacığı için ileti döngüsüne girmeden önce hızlandırıcı tablo kaynağını yükler. Bir uygulama veya iş parçacığı, her birinin uygulamadaki belirli bir pencereyle ilişkili birden çok hızlandırıcı tablosu da kullanabilir. Böyle bir uygulama, kullanıcı pencereyi her etkinleştirişinde pencere için hızlandırıcı tablosunu yükler. İş parçacıkları hakkında daha fazla bilgi için bkz. İşlemler ve İş Parçacıkları.
Translate Accelerator İşlevini Çağırma
Hızlandırıcıları işlemek için uygulamanın (veya iş parçacığının) ileti döngüsü, TranslateAccelerator işlevine yönelik bir çağrı içermelidir. TranslateAccelerator tuş vuruşlarını bir hızlandırıcı tablosuyla karşılaştırır ve eşleşme bulursa tuş vuruşlarını bir WM_COMMAND (veya WM_SYSCOMMAND) iletisine çevirir. İşlev daha sonra iletiyi bir pencere yordamına gönderir. TranslateAccelerator işlevinin parametreleri, WM_COMMAND iletilerini alacak pencere tutamacını, hızlandırıcı çevriminde kullanılan hızlandırıcı tablosunun tutamacını ve kuyruktan gelen bir ileti içeren MSG yapısının işaretçisini içerir. Aşağıdaki örnek, bir ileti döngüsü içinden TranslateAccelerator nasıl çağrılmasını gösterir.
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);
}
}
}
WM_COMMAND İletilerini İşleme
Hızlandırıcı kullanıldığında, TranslateAccelerator işlevinde belirtilen pencere bir WM_COMMAND veya WM_SYSCOMMAND iletisi alır. wParam parametresinin düşük sıralı sözcüğü hızlandırıcının tanımlayıcısını içerir. Pencere yordamı, WM_COMMAND iletisinin kaynağını belirlemek ve iletiyi uygun şekilde işlemek için tanımlayıcıyı inceler.
Genellikle, bir hızlandırıcı uygulamadaki bir menü öğesine karşılık geliyorsa, hızlandırıcı ve menü öğesine aynı tanımlayıcı atanır. bir WM_COMMAND iletisinin bir hızlandırıcı tarafından mı yoksa bir menü öğesi tarafından mı oluşturulduğunu bilmeniz gerekiyorsa, wParam parametresinin yüksek sıralı sözcüğünü inceleyebilirsiniz. Bir hızlandırıcı iletiyi oluşturduysa, yüksek sıralı sözcük 1'dir; bir menü öğesi iletiyi oluşturduysa, yüksek sıralı sözcük 0'dır.
Hızlandırıcı Tablosu Kaynağını Yok Etme
Sistem, LoadAccelerators işlevi tarafından yüklenen hızlandırıcı tablosu kaynaklarını otomatik olarak yok eder ve uygulama kapatıldıktan sonra kaynağı bellekten kaldırır.
Yazı Tipi Öznitelikleri için Hızlandırıcı Oluşturma
Bu bölümdeki örnekte aşağıdaki görevlerin nasıl gerçekleştirebileceğiniz gösterilmektedir:
- Hızlandırma tablosu kaynağı oluşturun.
- Hızlandırıcı tablosunu çalışma zamanında yükleyin.
- Bir ileti döngüsünde hızlandırıcıları çevirin.
- Hızlandırıcılar tarafından oluşturulan WM_COMMAND iletilerini işleme.
Bu görevler, Karakter menüsü ve kullanıcının geçerli yazı tipinin özniteliklerini seçmesine izin veren ilgili hızlandırıcılar içeren bir uygulama bağlamında gösterilir.
Kaynak tanımı dosyasının aşağıdaki bölümü, Karakter menüsünü ve ilişkili hızlandırıcı tablosunu tanımlar. Menü öğelerinin hızlandırıcı tuş vuruşlarını gösterdiğini ve her hızlandırıcının ilişkili menü öğesiyle aynı tanımlayıcıya sahip olduğunu unutmayın.
#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
}
Uygulamanın kaynak dosyasındaki aşağıdaki bölümlerde hızlandırıcıların nasıl uygulanacakları gösterilmektedir.
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;
}
Çalışma Zamanında Oluşturulan Hızlandırıcı Tablosunu Kullanma
Bu konuda, çalışma zamanında oluşturulan hızlandırıcı tablolarının nasıl kullanılacağı açıklanmaktadır.
- Run-Time Hızlandırıcı Tablosu Oluşturma
- İşleme Hızlandırıcıları
- Bir Run-Time Hızlandırıcı Tablosunu Yok Etme
- Kullanıcı Tarafından Düzenlenebilir Hızlandırıcılar Oluşturma
Run-Time Hızlandırıcı Tablosu Oluşturma
Çalışma zamanında hızlandırıcı tablosu oluşturmanın ilk adımı ACCEL yapıları dizisini doldurmaktır. Dizideki her yapı tabloda bir hızlandırıcı tanımlar. Hızlandırıcının tanımı bayraklarını, anahtarını ve tanımlayıcısını içerir. ACCEL yapısı aşağıdaki biçimdedir.
typedef struct tagACCEL { // accl
BYTE fVirt;
WORD key;
WORD cmd;
} ACCEL;
ACCEL yapısının üyesi anahtarında bir ASCII karakter kodu veya sanal anahtar kodu belirterek hızlandırıcının tuş vuruşunu tanımlarsınız. Bir sanal anahtar kodu belirtirseniz, önce fVirt üyesine FVIRTKEY bayrağını eklemeniz gerekir; aksi takdirde, sistem kodu ASCII karakter kodu olarak yorumlar. CTRL, ALT veya SHIFT tuşunu tuş vuruşuyla birleştirmek için FCONTROL, FALTveya FSHIFT bayrağını ya da üçünü de ekleyebilirsiniz.
Hızlandırıcı tablosunu oluşturmak için, CreateAcceleratorTable işlevine ACCEL yapıları dizisine bir işaretçi geçirin. CreateAcceleratorTable hızlandırıcı tablosunu oluşturur ve tanıtıcıyı tabloya döndürür.
İşlem Hızlandırıcıları
Çalışma zamanında oluşturulan bir hızlandırıcı tablosu tarafından sağlanan hızlandırıcıları yükleme ve çağırma işlemi, hızlandırıcı tablosu kaynağı tarafından sağlanan işlemlerin işlenmesiyle aynıdır. Daha fazla bilgi için bkz. Hızlandırıcı Tablosu Kaynağını Yükleme aracılığıyla WM_COMMAND İletileri İşleme.
Bir Run-Time Hızlandırıcı Tablosunu Yok Etme
Sistem, çalışma zamanında oluşturulan hızlandırıcı tablolarını otomatik olarak yok eder ve uygulama kapatıldıktan sonra kaynakları bellekten kaldırır. Bir hızlandırıcı tablosunu yok edebilir ve tablonun tutamacını DestroyAcceleratorTable işlevine geçirerek daha önce bellekten kaldırabilirsiniz.
Kullanıcı Tarafından Düzenlenebilir Hızlandırıcılar Oluşturma
Bu örnekte, kullanıcının bir menü öğesiyle ilişkili hızlandırıcıyı değiştirmesine olanak tanıyan bir iletişim kutusunun nasıl derlendiğini gösterilmektedir. İletişim kutusu, menü öğelerini içeren bir birleşik giriş kutusundan, anahtarların adlarını içeren bir birleşik giriş kutusundan ve CTRL, ALT ve SHIFT tuşlarını seçme onay kutularından oluşur. Aşağıdaki çizimde iletişim kutusu gösterilmektedir.
Birleşik giriş kutuları ve onay kutularıiletişim kutusu
Aşağıdaki örnek, iletişim kutusunun kaynak tanımı dosyasında nasıl tanımlandığını gösterir.
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
Uygulamanın menü çubuğunda yer alan, öğeleri hızlandırıcılarla ilişkilendirilmiş olan bir Karakter alt menüsü bulunur.
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
}
Menü şablonunun menü öğesi değerleri, uygulamanın üst bilgi dosyasında aşağıdaki gibi tanımlanan sabitlerdir.
#define IDM_REGULAR 1100
#define IDM_BOLD 1200
#define IDM_ITALIC 1300
#define IDM_ULINE 1400
İletişim kutusu, her biri tuş vuruşu metin dizesi ve hızlandırıcı-metin dizesi içeren, uygulama tanımlı VKEY yapılarından oluşan bir dizi kullanır. İletişim kutusu oluşturulduğunda, dizi ayrıştırılır ve her tuş vuruşu metin ifadesi Tuş Vuruşu Seç açılır kutusuna eklenir. Kullanıcı Tamam düğmesine tıkladığında, iletişim kutusu seçili tuş vuruş metin dizisini arar ve karşılık gelen hızlandırıcı metin dizisini getirir. İletişim kutusu, hızlandırıcı metin dizesini kullanıcının seçtiği menü öğesinin metnine ekler. Aşağıdaki örnekte VKEY yapıları dizisi gösterilmektedir:
// 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"
};
İletişim kutusunun başlatma prosedürü, Öğe Seç ve Tuş Vuruşu Seç açılır kutularını doldurur. Kullanıcı bir menü öğesini ve ilişkili hızlandırıcıyı seçtikten sonra, iletişim kutusu kullanıcının seçimini almak için iletişim kutusundaki denetimleri inceler, menü öğesinin metnini güncelleştirir ve ardından kullanıcı tanımlı yeni hızlandırıcıyı içeren yeni bir hızlandırıcı tablosu oluşturur. Aşağıdaki örnekte iletişim kutusu yordamı gösterilmektedir. Pencere işleminizde başlatmanız gerektiğini unutmayın.
// 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;
}