Есть класс
class CPageCtrl : public CTabCtrl
{
}
При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?
Здравствуйте User99, Вы писали:
U>Есть класс U>class CPageCtrl : public CTabCtrl U>{ U>} U>При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?
в WTL для этого существует карта сообщений. Всякие там
Только не получаю я сообщений вообще никаких. Наверное нужно добавить когото еще в предки. Вот только кого? Статейку по wtl местную читал — непомогает. Если несложно объясните неучу. Хочется закладки менять, но не из диалога, а из приведенного класса. Проблемма только с получением событий.
Здравствуйте User99, Вы писали:
U>Здравствуйте Алекс, Вы писали:
А>>в WTL для этого существует карта сообщений. Всякие там
[]
U>Только не получаю я сообщений вообще никаких. Наверное нужно добавить когото еще в предки. Вот только кого? Статейку по wtl местную читал — непомогает. Если несложно объясните неучу. Хочется закладки менять, но не из диалога, а из приведенного класса. Проблемма только с получением событий.
я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.
Здравствуйте Алекс, Вы писали:
А>я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.
Если приаттачиваешся — значит просто держишь хэндл окошка, и через него можешь этим окошком уаправлять, но никакие сообщения к тебе не идут, т.к. у окошка своя оконная процедура.
сабклассишь — аттачь + подмена оконной функции следовательно получаешь все события от данного окна.
Верно?
Хотелось конечно второй вариант, но насколько я понимаю у CTabCtrl не оконной функции. Нужно еще наследоваться и от CWindowImpl, НО КАК ЭТО СДЕЛАТЬ? у CTabCtrl CWindowImpl общий предок.
Здравствуйте User99, Вы писали:
U>Здравствуйте Алекс, Вы писали:
А>>я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.
U>Если приаттачиваешся — значит просто держишь хэндл окошка, и через него можешь этим окошком уаправлять, но никакие сообщения к тебе не идут, т.к. у окошка своя оконная процедура.
U>сабклассишь — аттачь + подмена оконной функции следовательно получаешь все события от данного окна. U>Верно?
U>Хотелось конечно второй вариант, но насколько я понимаю у CTabCtrl не оконной функции. Нужно еще наследоваться и от CWindowImpl, НО КАК ЭТО СДЕЛАТЬ? у CTabCtrl CWindowImpl общий предок.
типа такого
class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl>
Здравствуйте User99, Вы писали:
U>Есть класс U>class CPageCtrl : public CTabCtrl U>{ U>} U>При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?
в карте сообщений попробуй сделать так:
class CPageCtrl : public CTabCtrl
{
BEGIN_MSG_MAP(CPageCtrl)
REFLECT_NOTIFICATIONS()
MESSAGE_HANDLER(TCN_SELCHANGE,OnChangePage)
//COMMAND_HANDLER(IDC_TAB,TCN_SELCHANGE, f1)
//COMMAND_RANGE_HANDLER(0,100000,f1)CHAIN_MSG_MAP(CTabCtrl)
END_MSG_MAP()
};
Здравствуйте Al-Ko, Вы писали:
AK> AK>[ccode] AK>class CPageCtrl : public CTabCtrl AK>{ AK>BEGIN_MSG_MAP(CPageCtrl) AK> REFLECT_NOTIFICATIONS() AK> MESSAGE_HANDLER(TCN_SELCHANGE,OnChangePage) AK> //COMMAND_HANDLER(IDC_TAB,TCN_SELCHANGE, f1) AK> //COMMAND_RANGE_HANDLER(0,100000,f1) AK> CHAIN_MSG_MAP(CTabCtrl) AK>END_MSG_MAP()
Вот так делать как раз таки не нельзя т.к. в CTabCtrlT нет ProcessWindowMessage. См. предидущую ветку. В общем-то я уже ответ на свой вопрос получил.
Здравствуйте Алекс.
Не пойму какое сообщение ловить в классе class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl>
для реакции о смене закладки.
Вроде бы должно точно приходить отраженное TCN_SELCHANGING + OCM__BASE (REFLECT_NOTIFICATIONS в карте есть), но не приходит. Нотификационное тоже не приходит ( мне кажется, что и недолжно), приходит только нажатие левой кнопки мыши, но ведь это не-то. Может есть какие мысли?
Здравствуйте User99, Вы писали:
U>Здравствуйте Алекс. U>Не пойму какое сообщение ловить в классе class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl> U>для реакции о смене закладки. U>Вроде бы должно точно приходить отраженное TCN_SELCHANGING + OCM__BASE (REFLECT_NOTIFICATIONS в карте есть), но не приходит. Нотификационное тоже не приходит ( мне кажется, что и недолжно), приходит только нажатие левой кнопки мыши, но ведь это не-то. Может есть какие мысли?
есть. Нафига тебе REFLECT_NOTIFICATIONS?
Убери его и просто лови TCN_SELCHANGE.
Здравствуйте User99, Вы писали:
U>Здравствуйте Алекс, Вы писали:
А>>есть. Нафига тебе REFLECT_NOTIFICATIONS? А>>Убери его и просто лови TCN_SELCHANGE.
U>NOTIFY_ID_HANDLER(TCN_SELCHANGE,f1) U>MESSAGE_HANDLER(TCN_SELCHANGE,f2)
U>Не приходит ни в первую ни во вторую функцию
Здравствуйте User99, Вы писали:
U>Здравствуйте Алекс, Вы писали: А>>NOTIFY_CODE_HANDLER() не пробовал? U>И это тоже. WM_NOTIFY вообще не приходит на это действие.
Если воспользоваться refletion, то получается следующий неожиданный поворот, по крайней мередля меня:
приходит событие WM_NOTIFY + OCM__BASE, которое нужно обрабатывать так же как и нотификационное. Вот собственно и все.
Вот кусок из wtl
LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HWND hWndChild = NULL;
switch(uMsg)
{
case WM_COMMAND:
if(lParam != NULL) // not from a menu
hWndChild = (HWND)lParam;
break;
case WM_NOTIFY:
hWndChild = ((LPNMHDR)lParam)->hwndFrom;
break;
}
if(hWndChild == NULL)
{
bHandled = FALSE;
return 1;
}
ATLASSERT(::IsWindow(hWndChild));
return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
}
Здравствуйте, User99, Вы писали:
U>Есть класс U>class CPageCtrl : public CTabCtrl U>{ U>} U>При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?
нотификационные собщения от контрола идут родительскому окну, следовательно макрос REFLECT_NOTIFICATIONS должен быть вставлен в карту обработчиков сообщений родителя (т.е. диалога в данном случае)
Можете вставить его в самый конец карты, а перед REFLECT_NOTIFICATIONS спокойно обрабатывать оповещения от других эл-тов управления.
В карте самого контрола (CPageCtrl) обрабатывайте отраженные сообщения
второй подход заключается в следующем:
В контроле CPageCtrl делаете мембер типа CContainedWindow m_wndParent;
#define PARENT_MSG_MAP_ID 1
в конструкторе:
CPageCtrl():m_wndParent(this, PARENT_MSG_MAP_ID)
{
// бла-бла-бла
}
мапа:
BEGIN_MSG_MAP_EX(CPageCtrl)
// бла-бла-бла
ALT_MASG_MAP(PARENT_MSG_MAP_ID)
// набор обработчиков (не отраженных) сообщений от CPageCtrl
END_MSG_MAP
вот и все
так как время жизни объекта CPageCtrl вложено во время жизни диалога, то Unsubclass для m_wndParent вызывать не нужно, вроде бы
а если очень хочется, то UnsubclassWindow можно вызвать в CPageCtrl::OnDestroy
с использованием CContainedWindow можно обрабатывать сообщения любого окнаСпо известному HWND...