Поиск Winforms System.ComponentModel.Design Дизайн поверхности BeginDrag / EndDrag Хук событий - PullRequest
0 голосов
/ 16 января 2019

Я использую C #, Winforms, VS 2017 Enterprise и полную .NET Framework 4.7.2.

[Секция TLDR в конце!]

Я интенсивно работал с пространством имен System.ComponentModel.Design, чтобы создать работающий Visual Studio-подобный дизайнер Winforms. Настройка среды для такого дизайнера форм для конечного пользователя требует глубокого понимания объектов и интерфейсов в вышеупомянутом пространстве имен (и как их всех соединить), а также компонентов панели инструментов и сетки свойств. Поэтому я не могу опубликовать образец кода. Этот вопрос требует знания класса DesignSurface (https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.design.designsurface?view=netframework-4.7.2).

Кажется, что в области конструктора не возникает событие, когда пользователь перетаскивает выбранный элемент управления через поверхность конструктора. Мне нужно подключиться к событиям «begin-drag» / «end-drag», чтобы я мог выполнить очистку, а затем повторно визуализировать информационную панель, которая отражает текущую позицию всех элементов управления. (Я не хочу использовать таймеры для периодического обновления этой информации.)

Есть интерфейс ISelectionService, который я реализовал. Но это дает информацию только о том, какие элементы управления / компоненты выбраны. Это не помогает зафиксировать событие, которое возникает, когда начинается или заканчивается операция перетаскивания элемента управления.

Подробная информация о событиях поверхности дизайна отображается здесь: https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.design?view=netframework-4.7.2

Я пытался использовать событие IComponentChangeService's ComponentChanged, но оно срабатывает только после завершения операции перетаскивания элемента управления (и мне нужно определить, когда операция перетаскивания элемента управления начинается и заканчивается) ...

В качестве последнего средства я использовал Spy ++, чтобы увидеть, какие события возникают, когда элемент управления выбирается и перетаскивается по поверхности конструктора. Spy ++ помог мне идентифицировать начальное сообщение WM.LBUTTONDOWN и различные сообщения о перемещении мыши и т. Д., Но использование этих сообщений потребовало бы большого дополнительного кодирования, чтобы гарантировать, что кнопка мыши была нажата на элементе управления на поверхности конструктора, что элемент управления был фактически выбран, и что кнопка мыши остается нажатой, и т. д. - и даже тогда, я все еще не был бы уверен, что элемент управления не изменен по сравнению с перемещением. Конечно, в идеале я бы хотел подключиться к логике конструктора, которая реагирует на событие drag-begin.

Наконец, мое требование - определить, когда перетаскивается один выбранный элемент управления или когда несколько выбранных элементов управления перетаскиваются как группа. В обоих случаях мне нужно знать, когда начинается перетаскивание и когда оно заканчивается. (Для ясности: я имею в виду элементы управления, которые уже находятся на поверхности конструктора - я не имею в виду элементы управления на панели инструментов, которые перетаскиваются на поверхность конструктора ...)

TLDR: То, что я ищу, это способ подключиться к событию, которое срабатывает, как только элемент управления или группа элементов управления уже находятся на поверхности конструктора, перетаскивается, и способ подключиться к событию, которое срабатывает, когда эта операция перетаскивания имеет закончился.

Есть мысли?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

В дополнение Прекрасный и правильный ответ Резы (который я принял в качестве ответа) по этой довольно специализированной теме:

Существует много возможных / жизнеспособных способов подключения дизайнера Winforms и его зависимых объектов (набор инструментов, сетка свойств и т. Д.), Поэтому последовательность / время добавления определенных служб дизайнера в контейнер служб области разработки будут отличаться. , Некоторые службы должны быть явно добавлены (например, INameCreationService или IToolboxService); другие добавляются фреймворком.

Я еще не пришел к выводу, когда именно фреймворк добавляет BehaviorService к контейнеру сервисов, но я пришел к выводу, что этот сервис добавляется в любой работающий сервис дизайна (то есть тот, который позволяет вам уже перетаскивать добавлены элементы управления вокруг поверхности дизайна с помощью мыши).

Кроме того, многие объекты в пространстве имен System.ComponentModel.Design предлагают доступ к набору доступных служб, предоставляя метод GetService(). (В ответе Резы используется метод GetService объекта Site.) Если вы обнаружите, что GetService(typeof(BehaviorService)) не может вернуть действительный объект BehaviorService, это обычно означает, что BehaviorService еще не был добавлено в область дизайна ... Я говорю "пока", потому что элементы управления перетаскиванием, уже размещенные в области конструктора, требуют наличия BehaviorService в контейнере службы хоста. Поэтому, если ваша попытка получить экземпляр BehaviorService с использованием метода GetService не удалась, есть вероятность, что BehaviorService просто еще не был добавлен в конструкторскую среду. Чтобы решить эту проблему, вам обычно просто нужно переместить код для перехвата BehaviorService событий куда-нибудь вниз по течению.

Чтобы проверить, какие службы уже добавлены в область проектирования, вы можете проверить коллекцию ServiceContainer объекта поверхности проектирования Services, которая содержит полный список служб. Как предлагает Реза, хорошим местом для добавления кода, необходимого для подключения к событиям BehaviorService, является обработчик событий OnHandleCreated базовой формы.

0 голосов
/ 19 января 2019

Вы можете получить BehaviorService и подписаться на его BeginDrag и EndDrag события.

  • BeginDrag: происходит, когдаBehaviorService начинает операцию перетаскивания.
  • EndDrag: Происходит, когда BehaviorService завершает операцию перетаскивания.

Пример

Сначала вам нужно получить экземпляр BehaviorService, например, если у вас есть доступ к дизайнеру, хосту дизайнера или сайту, вы можете получить службу поведения следующим образом:

var behaviorSvc = (BehaviorService)Site.GetService(typeof(BehaviorService));

Затем подпишитесь на события:

behaviorSvc.BeginDrag += BehaviorSvc_BeginDrag;
behaviorSvc.EndDrag += BehaviorSvc_EndDrag;

и обработайте события:

private void BehaviorSvc_EndDrag(object sender, BehaviorDragDropEventArgs e)
{  
}

private void BehaviorSvc_BeginDrag(object sender, BehaviorDragDropEventArgs e)
{
}
...