WinUI3

WinUI3是当前微软开发的最新的UI框架,之前我只会win32的时候,需要处理令人讨厌的消息回调,如今,使用WinUI3和写前后端一样方便,甚至后端还是C#,好写,爽。不过缺点就是编译出来文件很大,而且并不是一个单独的exe。当然可以用MSIX打包就是了。

使用教程

image-20250531212907488

选择这里面的空白应用,已打包(桌面版中的WinUI 3)

image-20250531212950045

左边的App.xaml是入口点,下面的MainWindows.xaml是主类

xaml中可以设置控件的基本属性,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<Grid>
<Grid Grid.Row="2" Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition x:Name="MiddlePaddingColumn" Width="10"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>

<TextBox
x:Name="FileInputTextBox"
Grid.Row="1"
Height="32"
Margin="12,8,12,8"
VerticalContentAlignment="Center"
PlaceholderText="拖曳文件或双击打开文件..."
AllowDrop="True"
Drop="FileInputTextBox_Drop"/>
<Grid Grid.Column="2">
<Button Click="Button_Click">点击</Button>

</Grid>
</Grid>
</Grid>

先创建了一个横向(ColumnDefinitions)的Grid,然后创建不同的控件放入,其中Drop事件绑定了FileInputTextBox_Drop函数,Click绑定了Button_Click这个函数,这个函数在该xaml所属的cs文件中定义,打开cs文件

image-20250531215705446

可以看到入口点

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace WinUItest
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

可以通过在InitializeComponent之后添加更多内容实现窗口属性的修改,比如这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public MainWindow()
{
InitializeComponent();
DriverControl.DriverService.LogEvent += LogHandler;
// 实现主题栏高亮
ExtendsContentIntoTitleBar = true;
Activated += MainWindow_Activated;


// 设置大小
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);

uint dpi = DpiHelper.GetDpiForWindow(hWnd);
double scaleFactor = dpi / 96.0;
int logicalX = 500;
int logicalY = 500;
int logicalWidth = 616;
int logicalHeight = 248;

int physicalX = (int)(logicalX * scaleFactor);
int physicalY = (int)(logicalY * scaleFactor);
int physicalWidth = (int)(logicalWidth * scaleFactor);
int physicalHeight = (int)(logicalHeight * scaleFactor);

// 创建物理像素的大小矩形
RectInt32 newSize = new RectInt32(physicalX, physicalY, physicalWidth, physicalHeight);
appWindow.MoveAndResize(newSize);
if (appWindow.Presenter is OverlappedPresenter presenter)
{
// 锁定大小
presenter.IsResizable = false;
}

// 将输入框双击事件重载
FileInputTextBox.AddHandler(TextBox.DoubleTappedEvent, new DoubleTappedEventHandler(FileInputTextBox_DoubleTapped), true);


}

上面绑定的函数直接定义即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private string path;
private string name;

private async void FileInputTextBox_Drop(object sender, DragEventArgs e)
{
// 检查拖放进来的数据是否包含文件项
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
// 获取拖放进来的 StorageItems
var items = await e.DataView.GetStorageItemsAsync();
if (items.Count > 0)
{
if (items[0] is StorageFile file)
{
FileInputTextBox.Text = file.Path;
path = file.Path;
name = Path.GetFileNameWithoutExtension(file.Name);
}
}
}

e.Handled = true;
}
private void FileInputTextBox_DragOver(object sender, DragEventArgs e)
{
// 指定系统接受复制操作,否则拖放不会被允许
e.AcceptedOperation =
Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;

e.Handled = true;
}

这样就好了

click同理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private async void click(object sender, RoutedEventArgs e)
{
ContentDialog dialog = new ContentDialog
{
Title = name,
Content = path,
CloseButtonText = "关闭",
XamlRoot = this.Content.XamlRoot
};

ContentDialogResult result = await dialog.ShowAsync();


}

大概就是这样,总之就是写回调+系统API就好了