Нарисованный владельцем CTabCtrl в WTL
WTL/WIN32 новичок здесь, изо всех сил пытаясь понять, как сообщения передаются.
Я пытаюсь написать нарисованный владельцем CTabCtrl в WTL. По какой-то (по крайней мере для меня) непонятной причине WM_DRAWITEM отправляется в родительское окно, а не в окно, которое на самом деле нужно знать. Что затрудняет создание хорошего, автономного графического интерфейса для простой замены CTabCtrl. Я всегда мог захватить сообщение в родительском и передать его элементу управления вкладками, но это было бы плохим дизайном ОО. Есть ли способ перехватить сообщение, не требуя дополнительного кода перенаправления в классе владельца / родителя?
РЕДАКТИРОВАТЬ: После небольшого поиска в Google, у меня теперь есть
class CQueryTabCtrl :
public CWindowImpl<CQueryTabCtrl, CTabCtrl>,
public COwnerDraw<CQueryTabCtrl>
{
public:
DECLARE_WND_SUPERCLASS(NULL, CTabCtrl::GetWndClassName())
BEGIN_MSG_MAP(CQueryTabCtrl)
CHAIN_MSG_MAP(COwnerDraw<CQueryTabCtrl>)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)
{
}
void DrawItem ( LPDRAWITEMSTRUCT lpdis )
{
CDCHandle dc = lpdis->hDC;
CDC dcMem;
dcMem.CreateCompatibleDC ( dc );
dc.SaveDC();
dcMem.SaveDC();
dc.FillSolidRect ( &lpdis->rcItem, RGB(255,0,0) );
dcMem.RestoreDC(-1);
dc.RestoreDC(-1);
}
};
Что, очевидно, совершенно неверно, поскольку DrawItem() никогда не вызывается.
2 ответа
Этот ответ немного запоздал на вечеринку, но может помочь другим...
Невозможно напрямую получить отраженные сообщения без дополнительного кода маршрутизации, потому что именно так работает оконный обмен сообщениями в Window, как указывает Роман.
ATL, однако, имеет механизмы для отображения сообщений на дочерние окна, что, по крайней мере, помогает свести к минимуму самописанный код.
1) согласиться на отражение
Для этого требуется дополнительный шаг в родительском окне, чтобы он отображал на них сообщения дочерних окон, используя REFLECT_NOTIFICATIONS()
макрос:
// Just a made-up dialog class for outlining message reflection installed on the parent window
class SomeDialog : public CDialogImpl<SomeDialog, CWindow>
{
public:
BEGIN_MSG_MAP_EX(SomeDialog)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
};
2) Обрабатывать отраженные (владелец-рисовать) сообщения
Поскольку ваш элемент управления будет получать отраженные сообщения, а в микшине COwnerDraw предусмотрена альтернативная карта сообщений для них, вы просто подключаетесь к этой карте сообщений, используя CHAIN_MSG_MAP_ALT()
макро.
class CQueryTabCtrl :
public CWindowImpl<CQueryTabCtrl, CTabCtrl>,
public COwnerDraw<CQueryTabCtrl>
{
public:
DECLARE_WND_SUPERCLASS(NULL, CTabCtrl::GetWndClassName())
BEGIN_MSG_MAP(CQueryTabCtrl)
CHAIN_MSG_MAP_ALT(COwnerDraw<CQueryTabCtrl>, 1)
END_MSG_MAP()
void DrawItem(LPDRAWITEMSTRUCT)
{
// ...
}
};
Также посмотрите полный нарисованный владельцем элемент управления tablist из репозитория wtlext, который может служить примером (Отказ от ответственности: я связан с автором FireDaemon Technologies Ltd).
WM_DRAWITEM
отправляется родителю по замыслу.
Отправляется в родительское окно нарисованной владельцем кнопки, поля со списком, списка или меню, когда визуальный аспект кнопки, поля со списком или списка изменяется.
Вы обрабатываете это в окне хостинга, и с WTL вы можете использовать COwnerDraw
класс на него и / или отражать сообщения там, чтобы они отправлялись обратно в окно, где ваш подкласс WindowProc
будет обращаться с ними, как вы, возможно, изначально планировали.