moved to MVVM architecture
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using CursorLang.Interop;
|
||||
using CursorLang.Services;
|
||||
using CursorLang.ViewModels;
|
||||
|
||||
namespace CursorLang.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Всплывающая подсказка у курсора с коротким именем раскладки.
|
||||
/// Отвечает только за показ: когда её убрать, решает <see cref="LayoutPopupService"/>.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Показывает подсказку у текущего положения курсора.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user