SubClassing
От: User99  
Дата: 25.09.02 07:58
Оценка:
Есть класс
class CPageCtrl : public CTabCtrl
{
}
При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?
Re: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 08:13
Оценка:
Здравствуйте User99, Вы писали:

U>Есть класс

U>class CPageCtrl : public CTabCtrl
U>{
U>}
U>При инициализации диалога приаттачиваю к нему TabCtrl имеющийся на данном диалоге. Как получать события, происходящие в приатаченном контроле в этом классе? Знаю, что можно получать нотификационные сообщения в самом диалоге, а из него уже управлять объектом данного класса, но правильно ли это? В MFC были для этого виртуальные функции,а как быть в WTL?

в WTL для этого существует карта сообщений. Всякие там
BEGIN_MSG_MAP()
MESSAGE_HANDLER()
NOTIFY_CODE_HANDLER()
Re[2]: SubClassing
От: User99  
Дата: 25.09.02 08:30
Оценка:
Здравствуйте Алекс, Вы писали:

А>в WTL для этого существует карта сообщений. Всякие там


class CPageCtrl :  public CTabCtrl

{
public:
    bool SubClassWindow(const HWND wnd);
    int SetCurSel(int nItem);
    void AdjustPageSize();
    bool ShowPage(int nPage);
    BEGIN_MSG_MAP(CPageCtrl)
        REFLECT_NOTIFICATIONS()
        MESSAGE_HANDLER(TCN_SELCHANGE,OnChangePage)
        //COMMAND_HANDLER(IDC_TAB,TCN_SELCHANGE, f1)
        //COMMAND_RANGE_HANDLER(0,100000,f1)
    END_MSG_MAP()

    int AddItem( HWND hwnd, const TCHAR* lpcText);
    CPageCtrl();
    virtual ~CPageCtrl();
protected:
    HWND    m_hWndCurrent;
    LRESULT OnChangePage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

Только не получаю я сообщений вообще никаких. Наверное нужно добавить когото еще в предки. Вот только кого? Статейку по wtl местную читал — непомогает. Если несложно объясните неучу. Хочется закладки менять, но не из диалога, а из приведенного класса. Проблемма только с получением событий.
Re[3]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 08:52
Оценка:
Здравствуйте User99, Вы писали:

U>Здравствуйте Алекс, Вы писали:


А>>в WTL для этого существует карта сообщений. Всякие там


[]

U>Только не получаю я сообщений вообще никаких. Наверное нужно добавить когото еще в предки. Вот только кого? Статейку по wtl местную читал — непомогает. Если несложно объясните неучу. Хочется закладки менять, но не из диалога, а из приведенного класса. Проблемма только с получением событий.


я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.
Re[4]: SubClassing
От: User99  
Дата: 25.09.02 09:26
Оценка:
Здравствуйте Алекс, Вы писали:

А>я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.


Если приаттачиваешся — значит просто держишь хэндл окошка, и через него можешь этим окошком уаправлять, но никакие сообщения к тебе не идут, т.к. у окошка своя оконная процедура.

сабклассишь — аттачь + подмена оконной функции следовательно получаешь все события от данного окна.
Верно?

Хотелось конечно второй вариант, но насколько я понимаю у CTabCtrl не оконной функции. Нужно еще наследоваться и от CWindowImpl, НО КАК ЭТО СДЕЛАТЬ? у CTabCtrl CWindowImpl общий предок.
Re[5]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 09:38
Оценка: 8 (1)
Здравствуйте User99, Вы писали:

U>Здравствуйте Алекс, Вы писали:


А>>я не понял: ты приаттачиваешсь или сабклассишь? Это разные вещи. См. туже статью, функцию SubclassWindow.


U>Если приаттачиваешся — значит просто держишь хэндл окошка, и через него можешь этим окошком уаправлять, но никакие сообщения к тебе не идут, т.к. у окошка своя оконная процедура.


U>сабклассишь — аттачь + подмена оконной функции следовательно получаешь все события от данного окна.

U>Верно?

U>Хотелось конечно второй вариант, но насколько я понимаю у CTabCtrl не оконной функции. Нужно еще наследоваться и от CWindowImpl, НО КАК ЭТО СДЕЛАТЬ? у CTabCtrl CWindowImpl общий предок.


типа такого
class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl>
Re: SubClassing
От: Al-Ko  
Дата: 25.09.02 09:48
Оценка:
Здравствуйте 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()

};


начнешь получать события предка CTabCtrl

Или это не то, что тебя интересовало?
Старый глюк лучше новых двух!
Re[2]: SubClassing
От: User99  
Дата: 25.09.02 09:59
Оценка:
Здравствуйте 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. См. предидущую ветку. В общем-то я уже ответ на свой вопрос получил.
Re[2]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 10:02
Оценка:
Здравствуйте Al-Ko, Вы писали:

AK>Здравствуйте User99, Вы писали:


хъ

AK>

AK>
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()

AK>};
AK>


AK>начнешь получать события предка CTabCtrl


У CTabCtrl нет карты. Это просто обертка сообщений TCM_ххх.
Re[6]: SubClassing
От: User99  
Дата: 25.09.02 11:22
Оценка:
Здравствуйте Алекс.
Не пойму какое сообщение ловить в классе class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl>
для реакции о смене закладки.
Вроде бы должно точно приходить отраженное TCN_SELCHANGING + OCM__BASE (REFLECT_NOTIFICATIONS в карте есть), но не приходит. Нотификационное тоже не приходит ( мне кажется, что и недолжно), приходит только нажатие левой кнопки мыши, но ведь это не-то. Может есть какие мысли?
Re[7]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 11:29
Оценка:
Здравствуйте User99, Вы писали:

U>Здравствуйте Алекс.

U>Не пойму какое сообщение ловить в классе class CPageCtrl : public CWindowImpl<CPageCtrl, CTabCtrl>
U>для реакции о смене закладки.
U>Вроде бы должно точно приходить отраженное TCN_SELCHANGING + OCM__BASE (REFLECT_NOTIFICATIONS в карте есть), но не приходит. Нотификационное тоже не приходит ( мне кажется, что и недолжно), приходит только нажатие левой кнопки мыши, но ведь это не-то. Может есть какие мысли?

есть. Нафига тебе REFLECT_NOTIFICATIONS?
Убери его и просто лови TCN_SELCHANGE.
Re[8]: SubClassing
От: User99  
Дата: 25.09.02 11:36
Оценка:
Здравствуйте Алекс, Вы писали:

А>есть. Нафига тебе REFLECT_NOTIFICATIONS?

А>Убери его и просто лови TCN_SELCHANGE.

NOTIFY_ID_HANDLER(TCN_SELCHANGE,f1)
MESSAGE_HANDLER(TCN_SELCHANGE,f2)

Не приходит ни в первую ни во вторую функцию
Re[9]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 11:42
Оценка:
Здравствуйте User99, Вы писали:

U>Здравствуйте Алекс, Вы писали:


А>>есть. Нафига тебе REFLECT_NOTIFICATIONS?

А>>Убери его и просто лови TCN_SELCHANGE.

U>NOTIFY_ID_HANDLER(TCN_SELCHANGE,f1)

U>MESSAGE_HANDLER(TCN_SELCHANGE,f2)

U>Не приходит ни в первую ни во вторую функцию


бац, бац и мимо. гы, гы.

NOTIFY_CODE_HANDLER() не пробовал?
Re[10]: SubClassing
От: User99  
Дата: 25.09.02 11:51
Оценка:
Здравствуйте Алекс, Вы писали:
А>NOTIFY_CODE_HANDLER() не пробовал?
И это тоже. WM_NOTIFY вообще не приходит на это действие.
Re[11]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 11:52
Оценка:
Здравствуйте User99, Вы писали:

U>Здравствуйте Алекс, Вы писали:

А>>NOTIFY_CODE_HANDLER() не пробовал?
U>И это тоже. WM_NOTIFY вообще не приходит на это действие.

карту покажи.
Re[12]: SubClassing
От: User99  
Дата: 25.09.02 12:01
Оценка:
Здравствуйте Алекс, Вы писали:

А>карту покажи.


class CPageCtrl :   public CWindowImpl<CPageCtrl, CTabCtrl>

//public CTabCtrl//, public CWindowImpl<CPageCtrl>
{
public:
    LPARAM OnChangePage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bHandled);
    LPARAM f1(int wp,LPNMHDR i2,BOOL b2)
    {
        return 0;
    }

    BEGIN_MSG_MAP(CPageCtrl)
        NOTIFY_CODE_HANDLER(TCN_SELCHANGE,f1) 
    END_MSG_MAP()

    int SetCurSel(int nItem);
    void AdjustPageSize();
    bool ShowPage(int nPage);

    int AddItem( HWND hwnd, const TCHAR* lpcText);
    CPageCtrl();
    virtual ~CPageCtrl();
protected:
    HWND    m_hWndCurrent;
};
Re[13]: SubClassing
От: Алекс Россия http://wise-orm.com
Дата: 25.09.02 12:14
Оценка:
Здравствуйте User99, Вы писали:

хъ

и f1 никогда не вызывается?
странно.

Советы:
1. попробуй MESSAGE_HANDLER половить wm_notify
2. попробуй половить TCN_SELCHANGE спаем (шпионом, по русски (spy))

а вообще у меня догадка возникла.

ведь wm_notify приходит к паренту, т.е. в диалог. Соответственно
NOTIFY_CODE_HANDLER(TCN_SELCHANGE,f1)

можно отловить там. Можно воспользоваться тем же самым refletion в его карте, чтобы отфудболить сообщения в CPageCtrl.
Re[14]: SubClassing
От: User99  
Дата: 25.09.02 12:50
Оценка:
Здравствуйте Алекс, Вы писали:

Если воспользоваться 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);
}
Re: SubClassing
От: Юнусов Булат Россия  
Дата: 25.09.02 17:29
Оценка:
Здравствуйте User99, Вы писали:

http://home.worldonline.dk/viksoe/tabdlg.htm
Re: SubClassing
От: romant Россия  
Дата: 05.10.04 13:04
Оценка:
Здравствуйте, 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)
{
// бла-бла-бла
}

CPageCtrl::OnCreate(LPCREATESTRUCT pcs)
{
// бла-бла-бла
m_wndParent.SubclassWindow(pcs->hwndParent);
}

мапа:
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...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.