| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > Drag&Drop между разными CTreeView видами |
| Автор: voov 17.7.2008, 18:05 | ||||
| У меня есть 2 вида унаследованые от CTreeView. Нужно итем из дерева одного вида перетянуть на итем дерева другого вида. Перетаскивание итема в дереве одного вида сделал по статье МСДН Dragging a Tree-View Item. В OnTvnBegindrag вида делаю
А в OnMouseMove
Вместе с курсором двигается картинка сделаная по итему дерева. Но при выходе курсора за пределы окна вида картинка исчезает. Как сделать, чтобы картинка не исчезала? |
| Автор: Earnest 18.7.2008, 10:04 |
| Можно попробовать в DragEnter другое окно передать (общего родителя или главное окно). Это именно оно все блокирует... |
| Автор: voov 18.7.2008, 10:54 | ||||
| Да, получилось. Earnest, спасибо. Верно говорят, что утро вечера мудренее. Вчера был в полном тупике, а сегодня и сам уже начал двигаться в этом направлении. В OnTvnBegindrag владельцем картинки сделал фрейм. Ниже код. Кстати, может есть способ попроще добраться до родительского фрейма? У меня в фрейме 2 сплиттера, потому приходится вызывать GetParent 3 раза.
Нужно было еще DragMove делать
|
| Автор: Earnest 18.7.2008, 11:35 |
| GetParentFrame попробуй |
| Автор: voov 18.7.2008, 11:47 |
точно, спасибо. Еще один момент. Теперь картинка появляется чуть выше чем нужно. Нужно в BeginDrag задать смещение вместо нулевой точки: pImageList->BeginDrag(0, CPoint(0, 0)); но никак не могу получить это смещение... |
| Автор: Earnest 18.7.2008, 12:03 | ||
Хм... у меня были проблемы с горизонтальным смещением... я делала так (кусок обработчика BEGINDRAG):
А вертикальное если и есть - то незаметное: пока как следует не отъедет мышь, картинка сливается Добавлено через 2 минуты и 21 секунду Кстати, если во время mousemove ты помечаешь dropTarget в дереве, не забудь обернуть это в DragLeave\DragEnter, иначе грязь будет |
| Автор: voov 18.7.2008, 14:32 | ||||
Решил проблему со смещением
Теперь картинка появляется в том же месте, что и раньше (когда владельцем картинки был сам вид)
|
| Автор: Earnest 21.7.2008, 09:11 | ||||
Я тоже. И если не делаю DragLeave\DragEnter - то возникает грязь: либо недорисованне выделение, либо лишнее... Не всегда, но бывает. Перед SelectDropTarget вызываешь DragLeave, а после DragEnter.
Все правильно. Только почему во фрейме-то MOUSEMOVE и LBUTTONUP... впрочем, если так удобнее, то дело твое. Я предпочитаю все делать в одном месте. А всю информацию о перетаскивании засунуть в отдельный класс, типа CDragInfo, чтобы не мусорить в классе-дереве, у которого есть и другие нагрузки. А, поняла - ты же между разными видами таскаешь. Только если виды одного типа, я бы все равно фрейм грузить не стала. Одно дело - использовать ссылку на него в DragEnter, а другое - засовывать ненужную ему функциональность. Ты же capture ставишь на дерево - так что маус-мув по-любому получишь. |
| Автор: voov 21.7.2008, 09:54 | ||||||
Capture я ставлю на фрейм. И перетаскивание нужно делать между разными видами. Виды разных типов, к тому же нужно будет таскать и на вид без дерева (потом). В фрейме 2 обработчика MOUSEMOVE и LBUTTONUP, которые выполняют необходимые действия по перетаскиванию картинки, по координатам курсора определяют над каким видом мышь и переадресуют дальнейшую обработку в соответствующий вид.
Так ты о методах CImageList. А я то думал о переопределенных методах вида (OnDragLeave, OnDragOver ...). Чтобы нормально отрисовывались выделеные итемы дерева я использую DragShowNolock(). Примерно так
|
| Автор: Earnest 21.7.2008, 15:32 |
| Да, действительно, DragShowNoLock, возможно, даже лучше... Насчет идеологии: представь, что таскать нужно между видами разных фреймов - кто тогда обрабатывать должен? Есть, конечно, возможность прорубиться через OLE Drag & Drop, но мне там активно не понравилось... Если речь идет о своем приложении, где ты царь и бог, проще ручками, как мы и делаем. Я, при перетаскивании между разными окнами (вообще не связанными, но в моем приложении) делала так: 1) определяем структуру CDragInfo, куда помещаем ссылку на окно-владельца (кто начал drag & drop), итем, указатель (или hWnd) окна, куда будем кидать (это определяется во время таскания), таймер (для авто-скроллинга во время таскания) и т.д. - все, что может понадобиться для задачи - скажем, тип таскаемого элемента, etc В этот класс переношу весь код, нужный для реализации (установку capture, выбор цели и прочая) 2) определяю указатель на этот объект во всех классах, которые могут начать перетаскивание своих элементов 3) определяю несколько сообщений: TVM_DRAGENTER, TVM_DRAGLEAVE, TVM_DROPITEM - чтобы минимизировать обмен между разными окнами и их знание друг о друге. 4) На BeginDrag окно-владелец создает объект dragInfo, на mouseMove, lbuttonup и по Escape вызывает соответствующие функции объекта (в 2 последних случаях - потом разрушает его). 5) В процессе обработки mouseMove объект dragInfo посылает окну, над которым находится курсор, сообщение DRAGENTER - типа, хочешь, тебе чего-нибудь кинут? Если оно отвечает "хочу" - это будет новая цель, а старой, если она была, посылают DRAGLEAVE (чтобы она сняла выделение droptarget). DROPITEM посылается при завершении перетаскивания. Таким образом, окна друг о друге могут ничего не знать, вся коммуникация идет через windows-сообщения + структура данных. Вся функциональность (почти) - в классе DragInfo, окна-владельцы только вызывают в нужные моменты соответствующие функции + выделяют у себя цель + реализую вставку (и\или удаление). Фактически, примерно так же работает OLE Drag & Drop, только там все гораздо тяжелее и накрученнее... |
| Автор: voov 21.7.2008, 16:23 |
| Чтож, спасибо за информацию. Приму к сведению. Для текущей задачи достаточно того, что уже есть. К тому же, не хочу переписывать уже рабочий код. Но в будущем пригодится. |