Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SubClassing CLictCtrl 
:(
    Опции темы
Andrey44
Дата 15.7.2009, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



У меня есть класс наследник от CLictCtrl и есть HWND SysListView32
Пытаюсь сделать так 
Код

_listCtrl.SubclassWindow(hwndList);

Но падаю в wincore.cpp
Код

BOOL CWnd::Attach(HWND hWndNew)
{
    ASSERT(m_hWnd == NULL);     // only attach once, detach on destroy
    ASSERT(FromHandlePermanent(hWndNew) == NULL);//<-вот тут вылетает
        // must not already be in permanent map

    if (hWndNew == NULL)
        return FALSE;


Что я делаю не так?


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 15.7.2009, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Либо не там вызываешь, либо сабклассится дважды.
Конкретно, тебе сообщают, что данное окно (hwndNew) уже приаттачено к какому-то объекту. 
Поскольку прошел первый ассерт, то это другой объект (экземпляр)...
Похоже на косяк, типа аттач к автоматичкеской переменной или что-то вроде...
А что, не проще DDX_Control в DoDataExchange вставить? Зачем явно вызывать SubclassWindow?


--------------------
...
PM   Вверх
Andrey44
Дата 16.7.2009, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Цитата(Earnest @  15.7.2009,  19:22 Найти цитируемый пост)
А что, не проще DDX_Control в DoDataExchange вставить? Зачем явно вызывать SubclassWindow? 

Само окно SysListView32 создается отдельно в длл.
Я могу получить его только HWND. И есть класс наследник CListCtrl. Вот я и хочу прикрутить его к HWND.
Earnest, что можно придумать? smile 


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 16.7.2009, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Да SubclassWindow - нормальный путь, DDX_Control его и вызывает собственно.
Нужно причину искать. Эта DLL, где ListView создается - она тоже MFC? А может даже extension и там у этого окна есть экземпляр класса?
Тогда низя! Может быть только одно отображение hWnd -> CWnd, иначе ничего работать не будет.
Но если очень хочется, то можно. Но с оглядкой: просто Attach вызове (к своему классу) и на его деструкторе не забудь обнулить hWnd, а то плохо будет... Но имей в виду, это будет "ненастоящий" attach - для MFC-оболочки твоего окна как не было, так и не будет (все сообщения будут приходить "тому" окну).

Чобы что-то посоветовать, нужно понять, че те надо: конкретно, откуда такая надобность...
Кстати, если ты можешь получить хандл, то и окно постоянное получить не проблема FromHandlePermanenet, а затем, если знаешь какого класса объект, то преобразовть DYNAMIC_DOWNCAST (если класс DECLARE_DYNAMIC) или dynamic_cast (если RTTI включен).


--------------------
...
PM   Вверх
Andrey44
Дата 16.7.2009, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Вобщем есть движок который читая XML файл строит на окне меню с разными контролами которые написаны в XML
Но есть еще возможно делать обычные WIN контролы.
Но понадобилось сделать CListCtrl в стиле всех контролов и есть возможность получать HWND.
И вот я написал класс который должен переделать окно под общий стиль.
Да, кстати контрол в длл создается с MFC.
Если просто делать
Код

_listCtrl = reinterpret_cast<CSkinListCtrl*>(CWnd::FromHandlePermanent(_pdashEngine->GetControlWindow(_T("listView"))));
то все проходит нормально, но я не получаю управление контролом.
А если 
Код

_listCtrl.SubclassWindow(_pdashEngine->GetControlWindow(_T("listView"))));

то падает при .......ну сверху описано.

Earnest, теперь ты поняла в чем проблема?

Это сообщение отредактировал(а) Andrey44 - 16.7.2009, 10:23


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 16.7.2009, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Andrey44 @  16.7.2009,  11:22 Найти цитируемый пост)
то все проходит нормально, но я не получаю управление контролом.

А сие что значит? Кстати, лист-контрол-то именно этот класс имеет (CSkinListCtrl)? Иначе некорректно. И лучще использовать не reinterpret_cast, a dynamic_cast или хотя бы static_cast (если не включено RRTI, но тогда лучше DYNAMIC_DOWNCAST).
Если у тебя есть hWnd, то ты можешь сделать с окном практически все (в его процессе, конечно). MFC-класс всего лишь оболочка для удобства (CListCtrl не содержит данных). А вот CSkinListCtrl вполне может содержать, и тогда нужно быть уверенным, что это именно он создается в библиотеке.

Добавлено через 4 минуты и 59 секунд
Фактически, насколько я поняла, тебе требуется подменить класс, который используется в библиотеке для созхдания лист-вью на свой... А там тоже какой-то MFC-класс... Чисто SubclassWindow не прокатит, конечно, это же не АПИ, хотя слово похожее... Во-первых, нужно поковыряться в библиотеке - возможно, там что-то предусмотрено на этот предмет, а если нет, то боюсь не получится... Разве что с рисованием (использовать CustomDraw, т.к. эти уведомления парент обрабатывает). Но и то при условии, что сам исходный класс его не использует.


--------------------
...
PM   Вверх
Andrey44
Дата 16.7.2009, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Вобщем можно сделать вывод что разным потокам не разрешается совместно использовать объекты MFC-классов

Добавлено через 1 минуту и 15 секунд
Цитата(Earnest @  16.7.2009,  12:05 Найти цитируемый пост)
А сие что значит?

Это значит что в CSkinListCtrl не приходят сообщения


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Andrey44
Дата 16.7.2009, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Короче придется делать через GetWindowLong(hwnd, GWL_WNDPROC);
и SetWindowLong(hwnd, GWL_WNDPROC, NewWndProc);


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 16.7.2009, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Andrey44 @  16.7.2009,  13:13 Найти цитируемый пост)
Вобщем можно сделать вывод что разным потокам не разрешается совместно использовать объекты MFC-классов

Непричем здесь разные потоки. Нельзя замэпить одно окно на два разных MFC-объекта - это да. Но это из другой оперы.
Цитата(Andrey44 @  16.7.2009,  13:47 Найти цитируемый пост)
Короче придется делать через GetWindowLong(hwnd, GWL_WNDPROC);
и SetWindowLong(hwnd, GWL_WNDPROC, NewWndProc); 

Это тебе тоже может отлиться, если в библиотеке MFC-класс, то все развалится. Если ты подменишь оконную процедуру лист-вью, которое обернуто в MFC-класс, этот класс перестанет работать, т.е. ты потеряешь функциональность, которая есть в DLL.



--------------------
...
PM   Вверх
Andrey44
Дата 16.7.2009, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Цитата(Earnest @  16.7.2009,  14:39 Найти цитируемый пост)

Это тебе тоже может отлиться, если в библиотеке MFC-класс, то все развалится. Если ты подменишь оконную процедуру лист-вью, которое обернуто в MFC-класс, этот класс перестанет работать, т.е. ты потеряешь функциональность, которая есть в DLL

В длл никакой функциональности нет. Есть разные контролы, а вот листвью нет. Но там предусмотрено создание стандартных контролов. Вот и создается SysListView32 в МФЦ оболочке. Так что я теперь просто хочу подменить оконную процедуру и взять все управление на себя.


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Andrey44
Дата 17.7.2009, 06:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Делаю :
Код

HWND hwndList = _pdashEngine->GetControlWindow(_T("listView"));
OldListWindowProc = (WNDPROC)GetWindowLong(hwndList, GWL_WNDPROC);
SetWindowLong(hwndList, GWL_WNDPROC, (LONG)ListWindowProc);
ListView_SetView(hwndList, LV_VIEW_DETAILS);
HWND header = ListView_GetHeader(hwndList);
_header.SubclassWindow(header);//???????????????

Почему header сабклассится? Он ведь тоже объект класса МФЦ CHeaderCtrl


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 17.7.2009, 06:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Все равно подменять оконную функцию нельзя! Потому что  у всех MFC-окон общая оконная функция, которая и обеспечивает работу оболочки (хождение сообщения и т.д.) Если в DLL нет никакай функциональности, то тогда можно просто перед SubclassWindow сделать Detach. Т.е. получить окно по hWnd (FromHandlePermanent) и сделать ему детач. Это, конечно, кривовато, и может привести к утечкам памяти (хз как окно в библиотеке создается, скорее всего динамически, но можно попробовать и удалить его).

Добавлено через 2 минуты и 10 секунд
Цитата(Andrey44 @  17.7.2009,  07:42 Найти цитируемый пост)
Почему header сабклассится? Он ведь тоже объект класса МФЦ CHeaderCtrl 

Кто тебе сказал? Это просто АПИ-шное окно. Стандартный лист-контрол его не сабклассит. А то, что тебе может вернуться CWnd - так это временное окно. Есть большая разница между FromHandle и FromHandlePermanent


--------------------
...
PM   Вверх
Andrey44
Дата 17.7.2009, 07:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Earnest, объясни пожалуйста на пальцах, что-то я не пойму.
Надо делать так?
Код

CListCtrl * listCtrl = reinterpret_cast<CListCtrl*>(CListCtrl::FromHandlePermanent(_pdashEngine->GetControlWindow(_T("listView"))));
_skinListCtrl.SubclassWindow(listCtrl->Detach());

Или я не правильно понял?

Это сообщение отредактировал(а) Andrey44 - 17.7.2009, 07:27


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Andrey44
Дата 17.7.2009, 07:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Earnest, если так то вылетает теперь в другом месте
Код

BOOL CWnd::SubclassWindow(HWND hWnd)
{
    if (!Attach(hWnd))
        return FALSE;

    // allow any other subclassing to occur
    PreSubclassWindow();

    // now hook into the AFX WndProc
    WNDPROC* lplpfn = GetSuperWndProcAddr();
    WNDPROC oldWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC,
        (INT_PTR)AfxGetAfxWndProc());
    ASSERT(oldWndProc != AfxGetAfxWndProc());//<- Падает вот тут

    if (*lplpfn == NULL)
        *lplpfn = oldWndProc;   // the first control of that type created



--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 17.7.2009, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Andrey44 @  17.7.2009,  08:27 Найти цитируемый пост)
<- Падает вот тут

Т.е детач ты сделал, надо полагать. Видимо, нужно отбить и процедуру... она обнаружиает, что ты пытаешься сабклассить окно, которое уже сабкласировано MFC и возмущается... Я бы не парилась, а просто сделала сначала Detach этому FromHandlePermanent, а потом Attach к своему классу. Вроде должно пройти... сабклассинг делать не надо, т.к. процедура уже нужная впарена.
На всякий случай,
reinterpret_cast<CListCtrl*>(CListCtrl::FromHandlePermanent - масло маслянное. Чтобы отшибить хандл или сабклассить хватит и обычного CWnd:
Код

HWND hWnd = ...
CWnd* pList = CWnd::FromHandlePermanent(hWnd);
if (pWnd) { pWnd->Detach(); myList.Attach (hWnd); }
else MyList.SubclassWindow (hWnd);



--------------------
...
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0646 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.