Drag-n-Drop ИЗ окна, работающего в другом потоке
Select messages from
# through # FAQ
[/[Print]\]

Total Commander -> Написание плагинов для Total Commander

#1: Drag-n-Drop ИЗ окна, работающего в другом потоке Author: MVVLocation: Ростов-Дон PostPosted: Thu Oct 28, 2010 14:27
    —
Жил я себе, не тужил, пока не возникла необходимость реализовать тривиальное перетаскивание файлов из моего окна в любое другое. Но каков был шок, когда я понял, что кроме как через дебри OLE это реализовать невозможно. И что надо нагородить не один огород, чтобы реализовать такую мелочь. И началось...

Когда моё окно работает в основном потоке, и в нем же была вызвана OleInitialize, все нормально - с этой частью задачи я вроде разобрался.

Но теперь мне нужно сделать, чтобы то же самое работало, если я перетаскиваю файлы из окна, которое создано в другом потоке. Если конкретно, мой плагин создает поток, в нем - окно, в котором есть SysListView32, и из него мне надо суметь сделать перетаскивание файлов в другие окна.

Насколько я успел понять, Microsoft вплоть до Windows 7 не удосужилась сделать OLE-подсистему многопоточной, поэтому работать с COM-объектами можно только в одном-единственном потоке приложения. И, разумеется, это не мой поток, так как тотал сам по себе тоже умеет перетаскивать файлы.

Я пробовал при перетаскивании посылать окну тотала сообщение, в хуке которого (хук создается из основного потока) формировать структуру DROPFILES, создавать IDataObject и инициировать перетаскивание, вызывая [SH]DoDragDrop, но ничего не получается - оба окна (мое и тотала) на вид подвисают, потом при наведении мыши на окно тотала оно отвисает, и функция [SH]DoDragDrop говорит, что "Объект успешно передан приложению". И никакого перетаскивания не возникает и в помине... При тупом сабклассинге окна (при переопределении оконной процедуры через SetWindowLong[Ptr]) эффект тот же. При умном, наверное, был бы таким же, но попытка сабклассить по-умному (через SetWindowSubclass) вообще рушит тотал.

Поделился бы кто идейкой - было бы весьма кстати. Idea

#2:  Author: MVVLocation: Ростов-Дон PostPosted: Sat Mar 26, 2011 18:26
    —
Н-да, все оказалось так просто - тупо вызывать OleInitialize из каждого потока, в котором нужно использовать dnd, игнорируя все сказания об однопоточности модели OLE. И всё нормально работает безо всяких извращений.

Попутно возникла и была решена другая проблема - вызов OleUninitialize во время завершения приложения может завесить его или вызвать кучу других ошибок - поэтому нужно избегать вызовов OleUninitialize, когда один из потоков выполняет код функции DllMain (например, такая ситуация возникает, если основной поток закрывается и экстренно приказывает фоновым завершить работу). Собственно, об этом написано в MSDN, хотя и не так подробно.



Total Commander -> Написание плагинов для Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Page 1 of 1

Powered by phpBB © 2001, 2005 phpBB Group