Еще раз про сабклассинг...
От: KaSA  
Дата: 05.02.02 08:02
Оценка:
Блин, думал все, разобрался...ан нет. Обработчик WM_DRAWITEM, который в
COwnerDraw, не срабатывает и все тут.
Вот кусок кода:

это диалог...
class CLogviewDlg : public CDialogImpl<CLogviewDlg>  ,
        CWinDataExchange<CLogviewDlg>,
        CDialogResize<CLogviewDlg>
{
public:
    CLogviewDlg::CLogviewDlg();
    
    enum { IDD = IDD_LOGVIEW_DIALOG };

    BEGIN_MSG_MAP_EX(CLogviewDlg)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
        COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
        COMMAND_ID_HANDLER(IDC_AUTOUPDATE_CHECK, OnAutoUpdate)
        COMMAND_ID_HANDLER(IDC_UPDATE_BUTTON, OnUpdate)
        MSG_WM_SHOWWINDOW(OnShowWindow)
        MSG_WM_TIMER(OnTimer)
    END_MSG_MAP()

    BEGIN_DLGRESIZE_MAP(CLogviewDlg)
        DLGRESIZE_CONTROL(IDC_LOG_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
        DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
    END_DLGRESIZE_MAP()

    BEGIN_DDX_MAP(CLogviewDlg)
        DDX_CONTROL(IDC_LOG_LIST, clb)
    END_DDX_MAP()

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
    LRESULT OnAutoUpdate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        CButton b(GetDlgItem(IDC_AUTOUPDATE_CHECK));
        if (b.GetCheck())
            SetTimer(1, 1000);
        else
            KillTimer(1);
        return 0;    
    }

    LRESULT OnUpdate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        UpdateAppend();
        return 0;
    }

    void OnShowWindow(BOOL bShow, int nStatus){ if (bShow) Update(); }
    
    void OnTimer(UINT id, TIMERPROC* proc)
    {
        UpdateAppend();
    }

    LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        ShowWindow(SW_HIDE);
        return 0;
    }

public:
    void SetLogPath(const char* lpath);
    void Update();
    void UpdateAppend();

private:
    char m_LogFile[MAX_PATH];
    CColorListBox clb;
    DWORD m_dwLastLogSize;



а это контрол...
class CColorListBox : public CWindowImpl<CColorListBox, CListBox> , 
        COwnerDraw<CColorListBox>        
                    
{
public:
    DECLARE_WND_SUPERCLASS(NULL, CListBox::GetWndClassName())

    BEGIN_MSG_MAP_EX(CColorListBox)
    CHAIN_MSG_MAP(COwnerDraw<CColorListBox>)
    END_MSG_MAP()


    void DrawItem(LPDRAWITEMSTRUCT lpdis)
    {
        ATLASSERT(false);
    }

};


Дык, вот, в DrawItem попасть не удается...почему?
Где тут ошибка? Помогите, кто знает!

Спасибо.
Re: Еще раз про сабклассинг...
От: TepMuHyc  
Дата: 05.02.02 08:49
Оценка: 6 (1)
Здравствуйте KaSA, Вы писали:

KSA>Дык, вот, в DrawItem попасть не удается...почему? Где тут ошибка?

Ошибка в том, что WM_DRAWITEM посылается родительскому окну, а не самому контролу.
То есть сабкалссинг здесь, в общем случае, неприменим.

KSA>Помогите, кто знает!

Теперь о том кк выйти из этой ситуации.
Способ 1: Обрабатывать WM_DRAWITEM в родительском окне.
Это очень удобно если контрол "одноразовый" (т.е. такой который для непригоден
повторного использования).

Способ 2: Сделать вот так (хорошо для "реюзабельных" котролов):
//в родительском окне...
    BEGIN_MSG_MAP_EX(CLogviewDlg)
        ...
        MSG_WM_TIMER(OnTimer)
        REFLECT_NOTIFICATIONS() //это пнет WM_DRAWITEM обратно в контрол
    END_MSG_MAP()

//в контроле...
    BEGIN_MSG_MAP_EX(CColorListBox)
        MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) //заметь что код сообщения начинается на OCM_
    END_MSG_MAP()
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re[2]: Еще раз про сабклассинг...
От: VladNG  
Дата: 05.02.02 13:25
Оценка:
Здравствуйте TepMuHyc, Вы писали:

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


TMH>//в контроле...

TMH> BEGIN_MSG_MAP_EX(CColorListBox)
TMH> MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) //заметь что код сообщения начинается на OCM_
TMH> END_MSG_MAP()
TMH>[/ccode]

Контрол унаследован от COwnerDraw поэтому обрабатывать OCM_DRAWITEM не надо. А надо написать
функцию
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.