Привязка CALLBACK функции к оконному классу.
class CMyWnd : public CWnd
{
...
}
Для некоторых экземпляров класса мне нужно привязать CALLBACK функцию, например hook функцию обработки мыши:
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode < 0)
return CallNextHookEx(CTerminalView::hHookMouse, nCode, wParam, lParam);
// моя обработка...
return CallNextHookEx(CTerminalView::hHookMouse, nCode, wParam, lParam);
}
Сначала я разместил эту ф-цию внутри класса CMyWnd. Но при установке хука
void CMyWnd::DoDataExchange(CDataExchange* pDX)
{
//...
hHookMouse = SetWindowsHookEx(WH_MOUSE, this->MouseProc, NULL, ::GetCurrentThreadId());
}
возникает error C2664: 'SetWindowsHookEx': cannot convert parameter 2 from 'long (int,unsigned int,long)' to 'long (__stdcall *)(int,unsigned int,long)'
Т.е., насколько я понимаю, макрос CALLBACK (когда ф-ция определена внутри класса) игнорируется.
Поэтому мне пришлось вынести CALLBACK функцию из описания класса.
И здесь возникает другая проблема - экземпляров класса много, а CALLBACK функция одна. Т.е. я не могу определить из CALLBACK функции к какому экземпляру класса она привязана.
Вопрос:
1. Можно ли как то определить CALLBACK ф-цию внутри класса, и вызывать её без ошибки?
2. Ели первое нельзя, то как можно определить из CALLBACK функции c каким экземпляром класса она связана?
Есть класс наследуемый от CWnd:
class CMyWnd : public CWnd
{
...
}
Для некоторых экземпляров класса мне нужно привязать CALLBACK функцию, например hook функцию обработки мыши:
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode < 0)
return CallNextHookEx(CTerminalView::hHookMouse, nCode, wParam, lParam);
// моя обработка...
return CallNextHookEx(CTerminalView::hHookMouse, nCode, wParam, lParam);
}
Сначала я разместил эту ф-цию внутри класса CMyWnd. Но при установке хука
void CMyWnd::DoDataExchange(CDataExchange* pDX)
{
//...
hHookMouse = SetWindowsHookEx(WH_MOUSE, this->MouseProc, NULL, ::GetCurrentThreadId());
}
возникает error C2664: 'SetWindowsHookEx': cannot convert parameter 2 from 'long (int,unsigned int,long)' to 'long (__stdcall *)(int,unsigned int,long)'
Т.е., насколько я понимаю, макрос CALLBACK (когда ф-ция определена внутри класса) игнорируется.
Поэтому мне пришлось вынести CALLBACK функцию из описания класса.
И здесь возникает другая проблема - экземпляров класса много, а CALLBACK функция одна. Т.е. я не могу определить из CALLBACK функции к какому экземпляру класса она привязана.
Вопрос:
1. Можно ли как то определить CALLBACK ф-цию внутри класса, и вызывать её без ошибки?
2. Ели первое нельзя, то как можно определить из CALLBACK функции c каким экземпляром класса она связана?
1. Только, как static.
2. ОС ничего о твоих классах и экземплярах не знает, ОС оперирует (в данном случае) HWND. Его можно получить из lParam:
((MOUSEHOOKSTRUCT*)lParam)->hwnd
Далее, используя HWND можно связаться с твоим экземпляром несколькими способами, один из них - положить указатель на экземпляр в GWL_USERDATA (См. SetWindowLong) при инициализации окна (WM_CREATE или SubclassWindow).
1. Только, как static.
2. ОС ничего о твоих классах и экземплярах не знает, ОС оперирует (в данном случае) HWND. Его можно получить из lParam:
((MOUSEHOOKSTRUCT*)lParam)->hwnd
Далее, используя HWND можно связаться с твоим экземпляром несколькими способами, один из них - положить указатель на экземпляр в GWL_USERDATA (См. SetWindowLong) при инициализации окна (WM_CREATE или SubclassWindow).
Спасибо за ответ. Сохранение указателя на экземпляр в GWL_USERDATA я уже выполнял. И с этим пробле нет. Но как быть, если CALLBACK функция является, например, не hook функцией обработки мыши (где можно выбрать HWND), а hook функцией обработки клавиатуры (где нельзя выбрать HWND)?
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
);
Спасибо за ответ. Сохранение указателя на экземпляр в GWL_USERDATA я уже выполнял. И с этим пробле нет. Но как быть, если CALLBACK функция является, например, не hook функцией обработки мыши (где можно выбрать HWND), а hook функцией обработки клавиатуры (где нельзя выбрать HWND)?
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
);
В разных случиях по-разному. В данном случае, наверное, надо определить в каком окне находиться фокус GetFocus().
В разных случиях по-разному. В данном случае, наверное, надо определить в каком окне находиться фокус GetFocus().
Да, согласен, - это уникальное решение для ф-ции LRESULT CALLBACK KeyboardProc(...)
Скорее всего оно мне сейчас и поможет. Спасибо.
Но хотелось бы, на будущее, получить универсальное решение для всех CALLBACK ф-ций.
Кстати, для ф-ции обработки хука мыши, приходящий хендл окна не всегда яляется хендлом окна моего экземпляра класса. Так что нужно ещё анализировать результат вызова GetWindowLong(hwnd, GWL_USERDATA) :(.