Проблема в том, что DialogBox
API не имеет ускорителей для перевода, и это должно быть сделано в цикле сообщений перед отправкой сообщений.
Эту проблему можно решить следующим образом:
- используйте
SetWindowsHookEx
API для установки ловушки потока типа WH_GETMESSAGE
- это позволяет вам видеть сообщения до того, как они будут возвращены в цикл сообщений DialogBox
- на подключаемой процедуре, отфильтруйте интересующие сообщения (
PM_REMOVE
, затем сообщение WM_KEYFIRST
.. WM_LAST
, затем окно также представляет интерес)
- перенаправить сообщение на
TranslateAccelerator
и в случае успеха аннулировать его, обновив MSG.mesasge
с помощью WM_NULL
, чтобы «удалить» его из цикла сообщений API
24 мая 2014 г. Обновление
Пользователь Мик П. добавил фрагмент кода, который следует инструкциям выше (по какой-то причине это было отклонено при рецензировании здесь, но это стоит опубликовать), и они хорошо сработали для него. Вот код (некоторые вещи сомнительны, но это лучше, чем ничего для тех, кому требуется быстрый старт):
static HWND g_hDialog = NULL;
static HHOOK g_hHook = NULL;
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LRESULT nResult = 1;
if(nCode == HC_ACTION && wParam == PM_REMOVE)
{
MSG *p = (MSG*) lParam;
if(p->message >= WM_KEYFIRST && p->message <= WM_KEYLAST)
if(g_hDialog == GetForegroundWindow())
{
HWND gf = GetFocus(); // ignore if edit-able control
if(DLGC_HASSETSEL & ~SendMessage(gf, WM_GETDLGCODE, 0, 0)
|| ES_READONLY & GetWindowLong(gf, GWL_STYLE))
{
static HACCEL ha = // leaky
LoadAccelerators(..., MAKEINTRESOURCEW(IDR_MYACCEL));
if(TranslateAcceleratorW(g_hDialog, ha, p))
{
p->message = WM_NULL;
nResult = 0;
}
}
}
}
if(nCode < 0 || nResult)
return CallNextHookEx(g_hHook,nCode,wParam,lParam);
return nResult;
}
static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_INITDIALOG:
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, HookProc, ..., GetCurrentThreadId());
g_hDialog = hWnd;
return 1;
case WM_NCDESTROY:
UnhookWindowsHookEx(g_hHook);
break;
}
return 0;
}