using System.Windows; using System.Windows.Interop; using CursorLang.Interop; using CursorLang.Services; using CursorLang.ViewModels; namespace CursorLang.Views; /// /// Всплывающая подсказка у курсора с коротким именем раскладки. /// Отвечает только за показ: когда её убрать, решает . /// public partial class LayoutPopupWindow : Window { private readonly double _cursorOffset; private PopupWindowNative.Point _cursor; public LayoutPopupWindow(LayoutPopupViewModel viewModel, PopupOptions options) { InitializeComponent(); DataContext = viewModel; _cursorOffset = options.CursorOffset; } /// /// Показывает подсказку у текущего положения курсора. /// public void ShowAtCursor() { ResizeToContent(); _cursor = PopupWindowNative.GetCursorPosition(); // Для уже созданного окна двигаем до показа; при самом первом вызове // хэндла ещё нет, и позиционирование выполнит OnSourceInitialized MoveToCursor(); Show(); } // Хэндл создан, но окно ещё не отрисовано: здесь и настраиваем стили, // и ставим окно на место, чтобы первый показ прошёл уже на нужном мониторе protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); PopupWindowNative.MakePassive(new WindowInteropHelper(this).Handle); MoveToCursor(); } // Размер считаем сами, а не через SizeToContent: тот вычисляет его при создании // окна, когда содержимое ещё не измерено, и первый показ выходит шире текста. // Рамок у окна нет, поэтому его размер равен размеру содержимого private void ResizeToContent() { var content = (FrameworkElement)Content; content.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); Width = content.DesiredSize.Width; Height = content.DesiredSize.Height; } private void MoveToCursor() { IntPtr handle = new WindowInteropHelper(this).Handle; if (handle == IntPtr.Zero) { return; } // Отступ задан в единицах WPF, а двигаем окно в пикселях: пересчитываем // его по масштабу монитора, на котором сейчас курсор int offset = (int)Math.Round(_cursorOffset * PopupWindowNative.GetScaleAt(_cursor)); PopupWindowNative.MoveTo(handle, _cursor.X + offset, _cursor.Y + offset); } }