Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Замена CListCtrl на CMyListCtrl в CListView


Автор: AlexPro 23.11.2005, 12:43
Имеется класс, производный от CListView. Можно ли заменить подключенный к нему CListCtrl на свой (производный от CListCtrl) и как это правильно сделать?

Автор: Earnest 24.11.2005, 20:26
CLIstCtrl не подключен к CListView, он и есть CListView. Просто взгляд с другой стороны.
Достаточно посмотреть как реализован метод CListView::GetListCtrl:
Код

_AFXCVIEW_INLINE CListCtrl& CListView::GetListCtrl() const
{ return *(CListCtrl*)this; }

Поэтому подменить класс, как обычно, с помощью SubclassWindow не получится.
Да и зачем? Реализуй нужную функциональность в наследнике CListView.

Автор: AlexPro 25.11.2005, 05:36
Цитата(Earnest @ 24.11.2005, 20:26)
Достаточно посмотреть как реализован метод CListView::GetListCtrl

Да, это я, конечно, не посмотрел. Думал, есть способ, которым контрол подключается к виду, вроде того, как, например, меню прицепляется к окну.
Цитата(Earnest @ 24.11.2005, 20:26)
Да и зачем? Реализуй нужную функциональность в наследнике CListView

Я, собственно, так и делал, пока мне не понадобился список с аналогичным функционалом в диалоге, где, естественно, используется CListCtrl (или его наследник)
Можно, конечно, решить проблему путем замены CListView на CFormView и брошенным на форму CLIstCtrl, но по некоторым причинам мне не хотелось бы этого делать.

Автор: Earnest 25.11.2005, 19:58
Ясно, было у меня такое.
Классы, производные от CView, можно без проблем использовать в диалоге.
Все как обычно, добавляешь в ресурсах нужный контрол, а потом в DDX_Control подсовываешь класс, производный от View.
Несколько моментов все же придется учесть:

1) View обычно имеет конструктор без параметров, а документ свой получает где-то внутри MFC FrameWork. Но для диалога удобнее сделать еще один конструктор и прямо передать туда документ.

2) Это удобно еще и потому, что необходимо установить флаг режима использования: для динамического создания или в диалоге. Скажем, m_bDynamic. Устанавливается в TRUE в конструкторе для режима View, FALSE - для диалога. Флаг этот употребляется следующим образом:

3) В деструкторе необходимо обнулить указатель на документ (m_pDocument = 0), если
m_bDynamic = FALSE. Это для того, чтобы деструктор базового View вел себя тихо.

4) Необходимо переопределить PostNcDestroy таким образом:
Код

// перегружена, чтобы избежать безусловного вызова delete, как в CView::PostNcDestroy
void CXXXView::PostNcDestroy() 
{
   if (m_bDynamic) delete this;
}


5) Есть одно место, где View ожидает, что его парент является FrameWnd, опять переопределяем виртуальную функцию OnMouseActivate:
Код

// обход вызова CView::OnMouseActivate в случае использования в диалоге
// (исходная функция требует, чтобы верхнее окно было фреймом - см. код в MFC)
int CXXXView::OnMouseActivate (CWnd* pDesktopWnd,UINT nHitTest,UINT msg) 
{
    if (m_bDynamic)
        return CView::OnMouseActivate (pDesktopWnd,nHitTest,msg);
    else 
        return CWnd::OnMouseActivate (pDesktopWnd,nHitTest,msg);
}


Вот и все. Мой опыт основан на использовании класса, производного от TreeView, но сути это совершенно не меняет.

Автор: AlexPro 26.11.2005, 11:19
Хм. Мысль интересная, надо попробывать. Все никак не привыкну, что C++ допускает всякие извращения. О таком в правильных книгах не пишут smile .

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)