Каков наилучший способ показать окно WPF в месте расположения мыши (вверху слева от мыши)?

Я обнаружил, что это работает ЧАСТЬ времени, унаследовав точку мыши Windows Forms и вычтя высоту и ширину моего окна, чтобы установить левую и верхнюю части (так как размер моего окна фиксирован):

MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();
System.Windows.Point mouseLocation = GetMousePositionWindowsForms();
window.Left = mouseLocation.X - 300;
window.Top = mouseLocation.Y - 240;
window.Show();

Изменить: Вот код для получения позиции мыши...

public System.Windows.Point GetMousePositionWindowsForms()
{
    System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
    return new System.Windows.Point(point.X, point.Y);
}

Обратите внимание, что это работает, когда нижний правый край окна касается верхнего левого края курсора мыши. Но это ломается для разных разрешений экрана или может быть несколько мониторов с разной разрешающей способностью? Я еще не полностью сузил его, но я только что попробовал этот же код на другом ПК, и он, кажется, порождает окно не слева вверху от курсора мыши, а слева внизу и на хорошем расстоянии. мимо него...

Я, вероятно, должен добавить, что мои размеры окна к содержанию, ширине и высоте, так что я не могу просто использовать свойства ActualWidth и ActualHeight, так как они недоступны. Возможно, проблема в том, чтобы правильно подобрать размеры? Есть ли способ сделать это? Я точно знаю, что 300 и 240 соответствуют моим основным ПК с двумя мониторами с разрешением 1920x1080, так как я вычислил ширину и высоту всех объектов в моем окне, которые я явно выбрал. Изменить: Только что попытался явно установить высоту и ширину 240/300, чтобы убедиться, что окно больше не соответствует размеру содержимого, и у меня все еще есть эта проблема при вычитании фактической высоты и ширины!

Есть идеи?

5 ответов

Решение

В конце концов, это сделало свое дело:

        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            MoveBottomRightEdgeOfWindowToMousePosition();
        }

        private void MoveBottomRightEdgeOfWindowToMousePosition()
        {
            var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
            var mouse = transform.Transform(GetMousePosition());
            Left = mouse.X - ActualWidth;
            Top = mouse.Y - ActualHeight;
        }

        public System.Windows.Point GetMousePosition()
        {
            System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
            return new System.Windows.Point(point.X, point.Y);
        }

Разве вы не можете использовать что-то подобное?

Point mousePositionInApp = Mouse.GetPosition(Application.Current.MainWindow);
Point mousePositionInScreenCoordinates = 
    Application.Current.MainWindow.PointToScreen(mousePositionInApp);

Я не был в состоянии проверить это, но я думаю, что это должно работать.


ОБНОВЛЕНИЕ >>>

Вам не нужно использовать Application.Current.MainWindow в качестве параметра в этих методах... он все равно должен работать, если у вас есть доступ к Button или другой UIElement в обработчике:

Point mousePositionInApp = Mouse.GetPosition(openButton);
Point mousePositionInScreenCoordinates = openButton.PointToScreen(mousePositionInApp);

Опять же, я не смог проверить это, но если и это не удастся, тогда вы можете найти еще один метод в разделе Как получить текущие координаты экрана мыши в WPF? сообщение.

Вы также можете сделать это, слегка изменив исходный пример и разместив окно перед его показом.

MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();

var helper = new WindowInteropHelper(window);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
var transformFromDevice = hwndSource.CompositionTarget.TransformFromDevice;

System.Windows.Point wpfMouseLocation = transformFromDevice.Transform(GetMousePositionWindowsForms());
window.Left = wpfMouseLocation.X - 300;
window.Top = wpfMouseLocation.Y - 240;
window.Show();

Также вы можете сделать, как показано ниже:

      private void Button_Click(object sender, RoutedEventArgs e)
{
    ConfigWindow cw = new ConfigWindow();
    var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
    var mouse = transform.Transform(GetMousePosition());
    cw.WindowStartupLocation = WindowStartupLocation.Manual;
    cw.Left = mouse.X - cw.ActualWidth;
    cw.Top = mouse.Y - cw.ActualHeight;
    cw.Show();
}

public System.Windows.Point GetMousePosition()
{
    System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
    return new System.Windows.Point(point.X, point.Y);
}

Как user246758 прокомментировал ответ Александру:

Мне повезло больше с подключением событий к событию «Загружено»; Я обнаружил эффект мигания, когда диалог перемещается из исходной позиции визуализации, если я использовал OnContentRendered

Я публикую этот ответ, так как не смог отредактировать ответ Александру.

Загруженное событие у меня не сработало, и после некоторых исследований я нашел это . Согласно этой статье, я попробовалSourceInitializedмероприятие и результат хорошие. Он не производит мигающего эффекта, как описывает Гордон, и напрямую отображает позицию курсора.

Другие вопросы по тегам