Files
better-genshin-impact/BetterGenshinImpact/View/MaskWindow.xaml.cs

201 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.GameTask;
using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Helpers.DpiAwareness;
using BetterGenshinImpact.View.Drawable;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using Vanara.PInvoke;
using FontFamily = System.Windows.Media.FontFamily;
namespace BetterGenshinImpact.View;
/// <summary>
/// 一个用于覆盖在游戏窗口上的窗口,用于显示识别结果、显示日志、设置区域位置等
/// 请使用 Instance 方法获取单例
/// </summary>
public partial class MaskWindow : Window
{
private static MaskWindow? _maskWindow;
private static readonly Typeface MyTypeface = new FontFamily("Microsoft Yahei UI").GetTypefaces().First();
static MaskWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MaskWindow), new FrameworkPropertyMetadata(typeof(MaskWindow)));
}
public static MaskWindow Instance()
{
if (_maskWindow == null)
{
throw new Exception("MaskWindow 未初始化");
}
return _maskWindow;
}
public bool IsClosed { get; private set; }
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
IsClosed = true;
}
public void RefreshPosition(IntPtr hWnd)
{
//if (SystemControl.IsFullScreenMode(hWnd))
//{
// Hide();
//}
var currentRect = SystemControl.GetCaptureRect(hWnd);
double dpiScale = DpiHelper.ScaleY;
RefreshPosition(currentRect, dpiScale);
}
public void RefreshPosition(RECT currentRect, double dpiScale)
{
Invoke(() =>
{
Left = currentRect.Left / dpiScale;
Top = currentRect.Top / dpiScale;
Width = currentRect.Width / dpiScale;
Height = currentRect.Height / dpiScale;
Canvas.SetTop(LogTextBoxWrapper, Height - LogTextBoxWrapper.Height - 65);
});
// 重新计算控件位置
// shit code 预定了
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(this, "RefreshSettings", new object(), "重新计算控件位置"));
}
public MaskWindow()
{
_maskWindow = this;
this.SetResourceReference(StyleProperty, typeof(MaskWindow));
InitializeComponent();
this.InitializeDpiAwareness();
LogTextBox.TextChanged += LogTextBoxTextChanged;
//AddAreaSettingsControl("测试识别窗口");
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
this.SetLayeredWindow();
}
private void LogTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
var textRange = new TextRange(LogTextBox.Document.ContentStart, LogTextBox.Document.ContentEnd);
if (textRange.Text.Length > 10000)
{
LogTextBox.Document.Blocks.Clear();
}
LogTextBox.ScrollToEnd();
}
public void Refresh()
{
Dispatcher.Invoke(InvalidateVisual);
}
public void Invoke(Action action)
{
Dispatcher.Invoke(action);
}
protected override void OnRender(DrawingContext drawingContext)
{
try
{
var cnt = VisionContext.Instance().DrawContent.RectList.Count + VisionContext.Instance().DrawContent.TextList.Count;
if (cnt == 0)
{
return;
}
// 先有上方判断的原因是有可能Render的时候配置还未初始化
if (!TaskContext.Instance().Config.MaskWindowConfig.DisplayRecognitionResultsOnMask)
{
return;
}
foreach (var kv in VisionContext.Instance().DrawContent.RectList)
{
foreach (var drawable in kv.Value)
{
if (!drawable.IsEmpty)
{
drawingContext.DrawRectangle(Brushes.Transparent,
new Pen(new SolidColorBrush(drawable.Pen.Color.ToWindowsColor()), drawable.Pen.Width),
drawable.Rect);
}
}
}
foreach (var kv in VisionContext.Instance().DrawContent.TextList)
{
foreach (var drawable in kv.Value)
{
if (!drawable.IsEmpty)
{
drawingContext.DrawText(new FormattedText(drawable.Text,
CultureInfo.GetCultureInfo("zh-cn"),
FlowDirection.LeftToRight,
MyTypeface,
36, Brushes.Black, 1), drawable.Point);
}
}
}
}
catch (Exception e)
{
Debug.WriteLine(e);
}
base.OnRender(drawingContext);
}
public RichTextBox LogBox => LogTextBox;
}
file static class MaskWindowExtension
{
public static void SetLayeredWindow(this Window window, bool isLayered = true)
{
SetLayeredWindow(new WindowInteropHelper(window).Handle, isLayered);
}
private static void SetLayeredWindow(nint hWnd, bool isLayered = true)
{
int style = User32.GetWindowLong(hWnd, User32.WindowLongFlags.GWL_EXSTYLE);
if (isLayered)
{
style |= (int)User32.WindowStylesEx.WS_EX_TRANSPARENT;
style |= (int)User32.WindowStylesEx.WS_EX_LAYERED;
}
else
{
style &= ~(int)User32.WindowStylesEx.WS_EX_TRANSPARENT;
style &= ~(int)User32.WindowStylesEx.WS_EX_LAYERED;
}
_ = User32.SetWindowLong(hWnd, User32.WindowLongFlags.GWL_EXSTYLE, style);
}
}