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);
}
}