Задать вопрос
@Nimus2000

Почему не возникает событие MouseMove на пользовательском элементе, при маленьком движении мышки WPF?

<Grid>
       <local:UserCanvas MouseMove="UserCanvas_MouseMove" x:Name="canvas"></local:UserCanvas>
   </Grid>

public class UserCanvas : FrameworkElement{}
  public partial class MainWindow : Window
  {
      public MainWindow()
      {
          InitializeComponent();
      }

      private void UserCanvas_MouseMove(object sender, MouseEventArgs e)
      {
// при слабом движение мышки +-5px я вообще в этой функции не бывают, как так 
          var p = Mouse.GetPosition(canvas);
          Console.WriteLine(p);
          canvas.MouseMove(e);
          canvas.InvalidateVisual();
      }
  }


Как будто с 1 фпс работает.
При этом если вынести обработчик события мышки например в Grid или Windows все работает. В чем проблема и специфика.

Обновлю. Если OnRender оставить пустым или base.OnRender() то события вообще не происходит, ПОЧЕМУ ведь элемент находится находится.
Далее есть метод отрисовки, Я заметил что перерисовка не происходит, если нету изменения рисунка
если движении мышки почти не изменяет итоговое изображение, Вопрос, откуда Wpf знает что не будет изменения графики. каким образом, если она еще не отрисовала.

К примеру есть сложная геометрия, которая вроде бы остается той же. и допустим я хочу нарисовать маленький кружок в позиции мышки. А значит итоговая картина всегда будет разной. Тогда опять же почему не происходит события MouseMove.

Кто вообще запускает событие MouseMove? Каким образом оно связано с рендером содержимого?

И вообще каким образом происходит сравнение. Сколько на это времени уходит, где это описано?

И как это связано, с тем что если вынести обработчик события выше по иерархии, то он всегда сработает и всегда вызовет перерисовку.

Да проблема решается если добавить очистку. хотя и без очистки работает. обычно я использовал skia wpf библиотеку, и таких проблем не видел.
protected override void OnRender(DrawingContext drawingContext)
  {
   
      Rect bounds = new Rect(0, 0, w, h);
      Brush brush = new SolidColorBrush(Colors.Yellow);
      drawingContext.DrawRectangle(brush, null, bounds);
       //код

или
Window  MouseMove="UserCanvas_MouseMove">
<Grid >
    <local:UserCanvas  x:Name="canvas"></local:UserCanvas>
</Grid>

Почему эта строчка, либо вынес обработчика к Предку зависит от вызова событий MouseMove
  • Вопрос задан
  • 134 просмотра
Подписаться 2 Простой 1 комментарий
Пригласить эксперта
Ответы на вопрос 1
veselov4nton
@veselov4nton
Системный администратор.
Почему MouseMove не вызывается на UserCanvas
Ты создаёшь кастомный FrameworkElement, но он по умолчанию невидим и неучаствующий в хит-тестинге, если:

У него нет заливки
Он ничего не рисует в OnRender
У него IsHitTestVisible = false (по дефолту — true, но важно проверить)
У него Background = null (если это Panel/Control)
А FrameworkElement вообще без визуального контента — он не "осязаем" для мышки.

Поэтому, когда ты не рисуешь ничего или рисуешь то же самое, WPF считает: "Ну, зачем напрягаться?" — и не пересчитывает ни визуал, ни хит-тест.

Как это пофиксить правильно?
В UserCanvas добавь прозрачную заливку:
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, ActualWidth, ActualHeight));
// твоя отрисовка
}
Убедись, что элемент не перекрыт другими, и IsHitTestVisible = true
Не злоупотребляй InvalidateVisual() без надобности — это тяжёлая операция. Используй CompositionTarget.Rendering, если нужно трекать мышь независимо от WPF-инпутов.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы