#c_sharp #winforms #winapi
В процессе поиска решения для этого вопроса, появился новый вопрос.
У контролов WinForms для работы с Drag'n'Drop в .NET предусмотрено несколько типовых
событий и метод DoDragDrop.
Но есть несколько проблем связанных с ними. Если мы активируем DoDragDrop по событию
MouseDown, то до завершения процесса перетаскивания окно нашей программы не получает
события мыши, но получает события связанные с процедурой перетаскивания. Пока вроде
все логично, но если после активации перетаскивания объекта мышь не перемещается, то
процедура завершается не сразу, а с неопределенным таймаутом, и в это время события
мыши не передаются нашему окну, что собственно и вызвало проблему описанную в вопросе
по ссылке выше.
Для TreeView и ListView оказалось есть решение из коробки - событие ItemDrag, но
для других контролов, которые потенциально могли бы стать источником для Drag'n'Drop,
такого решения не предусмотрено.
Пока в голову пришло только одно решение:
По событию MouseDown поднимать флаг о возможном начале перетаскивания и запоминать
потенциальный объект перетаскивания в приватных полях формы.
По событию MouseMove проверять флаг и состояние клавиш мыши, и если заданные условия
выполнены, вызвать метод DoDragDrop в параметры которого передать предварительно сохраненный
объект в качестве данных для перетаскивания. После этого сбросить флаг.
Но мне почему-то кажется что это костыль, потому что в зависимости от того, что и
откуда мы собираемся перетаскивать, код будет различаться и его придется дублировать
для каждой формы, в которой потребуется такой функционал.
Собственно вопрос, правильно ли я понимаю, что процесс перетаскивания выполняется
в контексте операционной системы, а не отдельных программ, для обеспечения возможности
перетаскивания объектов между программами? Если предположение верное, то существует
ли решение обойти перечисленные проблемы более гибко, без строительства велосипедов
из костылей? Если мое предположение не верно - то в ответе хотелось бы увидеть как
это работает на самом деле.
Вопрос адресован скорее знатока WinAPI, но решение хотелось бы получить в контексте
C#. В принципе, мне, подойдет любое решение, которое можно будет адаптировать для .NET,
если оно будет лучше уже изложенного.
Ответы
Ответ 1
Буду рассуждать логически: У тебя не так уж много контролов, которые могут принимать в себя перетаскиваемый обьект. Уверен, их на форме от силы 1-3. Так почему бы не посмотреть как реализован ItemDrag в TreeView и ListView (благо, соурсы легко гуглятся по запросу "treeview source code") и не реализовать нужный тебе ItemDrag ивент в нужных контролах путем наследования и последующего расширения возможностей? Код будет, скорее всего, практически, идентичным.(я имею ввиду код ItemDrag для всех наследников оригинальных класов) Код твоей программы не будет замусориватся лишними флагами и методами. Все будет все так же читабельно, как если бы эти методы там были из коробки :)Ответ 2
Я бы обернул контролы, в которых необходимо задействовать Drag'n'Drop в следующую оболочку : Описать поле, в котором находится объект. Относительно этого объекта, производить рефреш, если его заменили другим. Описать метод GetInnerType() - определение типа объекта который может принять в себя контрол. Ну и описать относительно контролов с оболочкой MouseDown и MouseUp, с проверкой поля IsDragging и DragContainer - где находится текущий объект. Собственно на MouseUp определять тип объекта относительно DragContainer и сверять с GetInnerType объекта который принимает в себя этот объект, ну и принимать или не принимать внутрь себя объект. Пока такие мысли. Оборачивать контрол..
Комментариев нет:
Отправить комментарий