mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-15 07:43:20 +08:00
优化了PickerWindow的表现效果
This commit is contained in:
@@ -1,37 +1,183 @@
|
|||||||
<Window x:Class="BetterGenshinImpact.View.PickerWindow"
|
<Window x:Class="BetterGenshinImpact.View.PickerWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
Title="选择捕获窗口"
|
Title="选择捕获窗口"
|
||||||
Width="800"
|
Width="800"
|
||||||
Height="450"
|
Height="450"
|
||||||
FontFamily="{DynamicResource TextThemeFontFamily}"
|
WindowStartupLocation="CenterScreen"
|
||||||
mc:Ignorable="d">
|
Background="#FF1E1E1E">
|
||||||
<Grid Background="Black">
|
|
||||||
|
<Window.Resources>
|
||||||
|
<!-- ListBoxItem Fluent UI 样式 -->
|
||||||
|
<Style TargetType="ListBoxItem">
|
||||||
|
<Setter Property="Margin" Value="8,4" />
|
||||||
|
<Setter Property="Padding" Value="12" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ListBoxItem">
|
||||||
|
<Border x:Name="Border"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="8"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="Transparent">
|
||||||
|
<Grid>
|
||||||
|
<Border x:Name="SelectionBackground"
|
||||||
|
Background="#30FFFFFF"
|
||||||
|
CornerRadius="8"
|
||||||
|
Opacity="0"/>
|
||||||
|
<ContentPresenter />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="SelectionBackground" Property="Opacity" Value="0.1" />
|
||||||
|
<Setter TargetName="Border" Property="BorderBrush" Value="#20FFFFFF" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter TargetName="SelectionBackground" Property="Opacity" Value="0.2" />
|
||||||
|
<Setter TargetName="Border" Property="BorderBrush" Value="#40FFFFFF" />
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<StackPanel Grid.Row="0"
|
<!-- 标题区域 -->
|
||||||
Margin="5,0"
|
<Border Grid.Row="0"
|
||||||
Background="White"
|
Background="#FF252525"
|
||||||
Orientation="Horizontal">
|
Padding="24,20">
|
||||||
<TextBlock FontSize="20" Text="双击选中要捕获的窗口" />
|
<Grid>
|
||||||
</StackPanel>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<ListBox x:Name="WindowList"
|
<TextBlock Text="选择捕获窗口"
|
||||||
Grid.Row="1"
|
FontSize="24"
|
||||||
Padding="0,10"
|
FontWeight="SemiBold"
|
||||||
BorderThickness="0">
|
Foreground="#FFFFFF"/>
|
||||||
<ListBox.ItemTemplate>
|
|
||||||
<DataTemplate>
|
<TextBlock Grid.Row="1"
|
||||||
<ContentControl MouseDoubleClick="WindowsOnMouseDoubleClick">
|
Text="双击选中要捕获的窗口"
|
||||||
<TextBlock FontSize="14" Text="{Binding Name}" />
|
Margin="0,8,0,0"
|
||||||
</ContentControl>
|
Foreground="#99FFFFFF"
|
||||||
</DataTemplate>
|
FontSize="14"/>
|
||||||
</ListBox.ItemTemplate>
|
</Grid>
|
||||||
</ListBox>
|
</Border>
|
||||||
|
|
||||||
|
<ScrollViewer Grid.Row="1"
|
||||||
|
PanningMode="VerticalOnly"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||||
|
<ListBox x:Name="WindowList"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderThickness="0"
|
||||||
|
MouseDoubleClick="WindowsOnMouseDoubleClick"
|
||||||
|
VirtualizingPanel.IsVirtualizing="True"
|
||||||
|
VirtualizingPanel.VirtualizationMode="Recycling"
|
||||||
|
ScrollViewer.CanContentScroll="False">
|
||||||
|
<ListBox.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListBoxItem">
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
<Setter Property="Margin" Value="4"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ListBoxItem">
|
||||||
|
<Border x:Name="Border"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="8"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="Transparent">
|
||||||
|
<ContentPresenter/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Trigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
|
||||||
|
To="#22FFFFFF"
|
||||||
|
Duration="0:0:0.2">
|
||||||
|
<ColorAnimation.EasingFunction>
|
||||||
|
<ExponentialEase EasingMode="EaseOut"/>
|
||||||
|
</ColorAnimation.EasingFunction>
|
||||||
|
</ColorAnimation>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.EnterActions>
|
||||||
|
<Trigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation Storyboard.TargetName="Border"
|
||||||
|
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
|
||||||
|
To="#00000000"
|
||||||
|
Duration="0:0:0.2">
|
||||||
|
<ColorAnimation.EasingFunction>
|
||||||
|
<ExponentialEase EasingMode="EaseOut"/>
|
||||||
|
</ColorAnimation.EasingFunction>
|
||||||
|
</ColorAnimation>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.ExitActions>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter TargetName="Border" Property="Background" Value="#33FFFFFF"/>
|
||||||
|
<Setter TargetName="Border" Property="BorderBrush" Value="#44FFFFFF"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ListBox.ItemContainerStyle>
|
||||||
|
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Margin="12,8" Height="48">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- 内容层 -->
|
||||||
|
<Border Grid.Column="0"
|
||||||
|
Width="40"
|
||||||
|
Height="40"
|
||||||
|
Background="#22FFFFFF"
|
||||||
|
CornerRadius="4"
|
||||||
|
Margin="0,0,12,0">
|
||||||
|
<Image Width="24"
|
||||||
|
Height="24"
|
||||||
|
Source="{Binding Icon}"
|
||||||
|
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<StackPanel Grid.Column="1"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock Text="{Binding Name}"
|
||||||
|
FontSize="14"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Foreground="#FFFFFF"/>
|
||||||
|
<TextBlock Text="{Binding ProcessName}"
|
||||||
|
FontSize="12"
|
||||||
|
Foreground="#99FFFFFF"
|
||||||
|
Margin="0,4,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -7,71 +7,160 @@ using System.Windows;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using Vanara.PInvoke;
|
using Vanara.PInvoke;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace BetterGenshinImpact.View;
|
namespace BetterGenshinImpact.View;
|
||||||
|
|
||||||
public partial class PickerWindow : Window
|
public partial class PickerWindow : Window
|
||||||
{
|
{
|
||||||
private static readonly string[] _ignoreProcesses = ["applicationframehost", "shellexperiencehost", "systemsettings", "winstore.app", "searchui"];
|
private static readonly string[] _ignoreProcesses = ["applicationframehost", "shellexperiencehost", "systemsettings", "winstore.app", "searchui"];
|
||||||
|
private bool _isSelected = false;
|
||||||
public PickerWindow()
|
public PickerWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.InitializeDpiAwareness();
|
this.InitializeDpiAwareness();
|
||||||
Loaded += OnLoaded;
|
Loaded += OnLoaded;
|
||||||
}
|
}
|
||||||
|
public class CapturableWindow
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
|
||||||
|
public IntPtr Handle { get; set; }
|
||||||
|
public ImageSource Icon { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
FindWindows();
|
FindWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntPtr PickCaptureTarget(IntPtr hWnd)
|
public bool PickCaptureTarget(IntPtr hWnd,out IntPtr PickedWindow)
|
||||||
{
|
{
|
||||||
new WindowInteropHelper(this).Owner = hWnd;
|
new WindowInteropHelper(this).Owner = hWnd;
|
||||||
ShowDialog();
|
ShowDialog();
|
||||||
|
if(!_isSelected)
|
||||||
return ((CapturableWindow?)WindowList.SelectedItem)?.Handle ?? IntPtr.Zero;
|
{
|
||||||
|
PickedWindow = IntPtr.Zero;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PickedWindow = ((CapturableWindow?)WindowList.SelectedItem)?.Handle ?? IntPtr.Zero;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void FindWindows()
|
private unsafe void FindWindows()
|
||||||
{
|
{
|
||||||
var wih = new WindowInteropHelper(this);
|
var wih = new WindowInteropHelper(this);
|
||||||
|
var windows = new List<CapturableWindow>();
|
||||||
|
|
||||||
User32.EnumWindows((hWnd, lParam) =>
|
User32.EnumWindows((hWnd, lParam) =>
|
||||||
{
|
{
|
||||||
// ignore invisible windows
|
if (!User32.IsWindowVisible(hWnd) || wih.Handle == hWnd)
|
||||||
if (!User32.IsWindowVisible(hWnd))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// ignore untitled windows
|
|
||||||
var title = new StringBuilder(1024);
|
var title = new StringBuilder(1024);
|
||||||
_ = User32.GetWindowText(hWnd, title, title.Capacity);
|
_ = User32.GetWindowText(hWnd, title, title.Capacity);
|
||||||
if (string.IsNullOrWhiteSpace(title.ToString()))
|
if (string.IsNullOrWhiteSpace(title.ToString()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// ignore me
|
|
||||||
if (wih.Handle == hWnd)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
_ = User32.GetWindowThreadProcessId(hWnd, out var processId);
|
_ = User32.GetWindowThreadProcessId(hWnd, out var processId);
|
||||||
|
|
||||||
// ignore by process name
|
|
||||||
var process = Process.GetProcessById((int)processId);
|
var process = Process.GetProcessById((int)processId);
|
||||||
if (_ignoreProcesses.Contains(process.ProcessName.ToLower()))
|
if (_ignoreProcesses.Contains(process.ProcessName.ToLower()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
WindowList.Items.Add(new CapturableWindow
|
// 获取窗口图标
|
||||||
|
var icon = GetWindowIcon((IntPtr)hWnd);
|
||||||
|
|
||||||
|
windows.Add(new CapturableWindow
|
||||||
{
|
{
|
||||||
Handle = (IntPtr)hWnd,
|
Handle = (IntPtr)hWnd,
|
||||||
Name = $"{title} ({process.ProcessName}.exe)"
|
Name = title.ToString(),
|
||||||
|
ProcessName = process.ProcessName,
|
||||||
|
Icon = icon
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, IntPtr.Zero);
|
}, IntPtr.Zero);
|
||||||
|
|
||||||
|
WindowList.ItemsSource = windows;
|
||||||
|
}
|
||||||
|
private ImageSource GetWindowIcon(IntPtr hWnd)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const int ICON_BIG = 1; // WM_GETICON large icon constant
|
||||||
|
const int ICON_SMALL = 0; // WM_GETICON small icon constant
|
||||||
|
const int GCL_HICON = -14; // GetClassLong index for icon
|
||||||
|
|
||||||
|
// 尝试获取窗口大图标
|
||||||
|
var iconHandle = User32.SendMessage(hWnd, User32.WindowMessage.WM_GETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
|
||||||
|
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// 尝试获取窗口小图标
|
||||||
|
iconHandle = User32.SendMessage(hWnd, User32.WindowMessage.WM_GETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// 尝试获取窗口类图标
|
||||||
|
iconHandle = User32.GetClassLong(hWnd, GCL_HICON);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconHandle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return Imaging.CreateBitmapSourceFromHIcon(
|
||||||
|
iconHandle,
|
||||||
|
Int32Rect.Empty,
|
||||||
|
BitmapSizeOptions.FromEmptyOptions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"获取窗口图标失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果获取失败,返回一个默认图标或null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private bool IsGenshinWindow(string windowName)
|
||||||
|
{
|
||||||
|
// 判断是否包含原神相关的进程名 TODO:更加健壮的判断
|
||||||
|
return windowName == "原神";
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AskIsThisGenshinImpact(string windowName)
|
||||||
|
{
|
||||||
|
var res = MessageBox.Question(
|
||||||
|
$"""
|
||||||
|
这看起来不像是原神,确定要选择这个窗口吗?
|
||||||
|
|
||||||
|
当前选择的窗口:{windowName}
|
||||||
|
""",
|
||||||
|
"确认选择",
|
||||||
|
MessageBoxButton.YesNo,
|
||||||
|
MessageBoxResult.No
|
||||||
|
);
|
||||||
|
return res == MessageBoxResult.Yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WindowsOnMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
private void WindowsOnMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
|
var selectedWindow = WindowList.SelectedItem as CapturableWindow;
|
||||||
|
if (selectedWindow == null) return;
|
||||||
|
|
||||||
|
// 如果不是原神窗口,询问用户是否确认
|
||||||
|
if (!IsGenshinWindow(selectedWindow.Name))
|
||||||
|
{
|
||||||
|
if (!AskIsThisGenshinImpact(selectedWindow.Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_isSelected = true;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,29 +139,42 @@ public partial class HomePageViewModel : ObservableObject, INavigationAware, IVi
|
|||||||
private void OnStartCaptureTest()
|
private void OnStartCaptureTest()
|
||||||
{
|
{
|
||||||
var picker = new PickerWindow();
|
var picker = new PickerWindow();
|
||||||
var hWnd = picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle);
|
|
||||||
if (hWnd != IntPtr.Zero)
|
if (picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle, out var hWnd))
|
||||||
{
|
{
|
||||||
var captureWindow = new CaptureTestWindow();
|
if (hWnd != IntPtr.Zero)
|
||||||
captureWindow.StartCapture(hWnd, Config.CaptureMode.ToCaptureMode());
|
{
|
||||||
captureWindow.Show();
|
var captureWindow = new CaptureTestWindow();
|
||||||
|
captureWindow.StartCapture(hWnd, Config.CaptureMode.ToCaptureMode());
|
||||||
|
captureWindow.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Error("选择的窗体句柄为空");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void OnManualPickWindow()
|
private void OnManualPickWindow()
|
||||||
{
|
{
|
||||||
var picker = new PickerWindow();
|
var picker = new PickerWindow();
|
||||||
var hWnd = picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle);
|
if(picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle,out var hWnd))
|
||||||
if (hWnd != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
_hWnd = hWnd;
|
if (hWnd != IntPtr.Zero)
|
||||||
Start(hWnd);
|
{
|
||||||
}
|
_hWnd = hWnd;
|
||||||
else
|
Start(hWnd);
|
||||||
{
|
}
|
||||||
MessageBox.Error("选择的窗体句柄为空!");
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Error("选择的窗体句柄为空!");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -181,8 +194,13 @@ public partial class HomePageViewModel : ObservableObject, INavigationAware, IVi
|
|||||||
var hWnd = SystemControl.FindGenshinImpactHandle();
|
var hWnd = SystemControl.FindGenshinImpactHandle();
|
||||||
if (hWnd == IntPtr.Zero)
|
if (hWnd == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (Config.GenshinStartConfig.LinkedStartEnabled && !string.IsNullOrEmpty(Config.GenshinStartConfig.InstallPath))
|
if (Config.GenshinStartConfig.LinkedStartEnabled)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(Config.GenshinStartConfig.InstallPath))
|
||||||
|
{
|
||||||
|
MessageBox.Error("没有找到原神的安装路径");
|
||||||
|
return;
|
||||||
|
}
|
||||||
hWnd = await SystemControl.StartFromLocalAsync(Config.GenshinStartConfig.InstallPath);
|
hWnd = await SystemControl.StartFromLocalAsync(Config.GenshinStartConfig.InstallPath);
|
||||||
if (hWnd != IntPtr.Zero)
|
if (hWnd != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
|
|||||||
1
View/PickerWindow.xaml
Normal file
1
View/PickerWindow.xaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Reference in New Issue
Block a user