要重新创建我所做的工作,请创建一个新的AvaloniaUI项目.在MainWindow.cs中,通过调用this.FindDescendantOfType<TitleBar>();inprotected override void OnApplyTemplate(TemplateAppliedEventArgs e)获取标题栏对象.然后将任何事件添加到其PointerPressed事件. 但是,永远不会到达事件处理程序方法的断点.

推荐答案

你不能那样做.如果您判断TitleBar,您会发现它实际上是一个没有大小或函数的通用对象,只是存在于树中(不确定它们为什么不只给您一个空的,可能是一些内部可空的问题). 无论如何,你做不到的原因是因为Chrome是基于操作系统的,并由操作系统控制,而实现是特定于操作系统的.另一种 Select 是构建您自己的标题栏,并隐藏系统标题栏,自己提供必要的功能(请查看此选项以了解 idea =>;Custom TitleBar Template).

如果你不想这样做,而且你只是在做Windows应用程序,你可以窥探你自己的消息队列(安全,因为没有DLL注入,并且GUI线程不会跨非托管线程移动)来检测"非客户端",例如标题栏点击消息(WM_NCLBUTTONDOWN)并做出react .例如:

MainWindow.axaml

<Window xmlns="https://github.com/avaloniaui"
        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"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Test01.MainWindow"
        Title="Test01" >
    <Grid>
        <Label Name="MainLabel"/>
    </Grid>
</Window>

MainWindow.axaml.cs

using Avalonia.Controls;
using System;
using System.Runtime.InteropServices;

namespace Test01;

public partial class MainWindow : Window
{
    private const int WM_NCLBUTTONDOWN = 0x00a1;
    private const int WH_GETMESSAGE = 3;

    private IntPtr theHook;

    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();
        theHook = MyInterop.SetWindowsHookEx(WH_GETMESSAGE, MsgHook, IntPtr.Zero, MyInterop.GetCurrentThreadId());
        // var err = Marshal.GetLastWin32Error();
    }

    private int MsgHook(int nCode, IntPtr wParam, IntPtr lParam)
    {
        // mandatory shortcut
        if (nCode < 0) return MyInterop.CallNextHookEx(theHook, nCode, wParam, lParam);
        // is it a NC click?
        var msg = (MyInterop.MsgStruct?)Marshal.PtrToStructure(lParam, typeof(MyInterop.MsgStruct));
        if (msg?.message == WM_NCLBUTTONDOWN)
        {
            // your action
            MainLabel.Content = "I am pressed!!!";
        }

        return MyInterop.CallNextHookEx(theHook, nCode, wParam, lParam);
    }

}

MyInterop.cs

namespace Test01;

internal static class MyInterop
{
    [StructLayout(LayoutKind.Sequential)]
    public class MsgStruct
    {
        public IntPtr hwnd;
        public uint message;
        // we dont care about the rest of MSG struct
    }


    internal delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
    internal static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    internal static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll")]
    internal static extern uint GetCurrentThreadId();
}

这只是一个工作示例,您可以将其重新打包为一些可观察到的模式或事件启动器.

此外,这只适用于Windows,不适用于Linux和MacOS.对于X11,也有一个消息队列,所以我认为替代方案可能是可能的.对于MacOS,我一点也不确定.

注意:由于Avalonia(Xaml Compiler error when code-behind class contains a DllImport method #10046)中的错误,我不得不将所有外部定义移到一个单独的类中.一旦修复,MyInterop就可以合并到Main.cs中

Csharp相关问答推荐

使用封装的Span Range.Enumerator时引发IndexOutOfRangeResponse

Autofac:如何防止丢弃通过ServicCollection注册的服务?

EF Core:看不到任何查询日志(log)?

更新数据库中的对象失败,原因是:Microsoft. EntityFrame Core. GbUpdateConcurrencyResponse'

如何从顶部提取发票号作为单词发票后的第一个匹配

Serilog SQL服务器接收器使用UTC作为时间戳

如何使用Unity和MRTK3将手网添加到Hololens 2应用程序中

LINQ无法翻译SQLFunctions方法

使用客户端密钥为Fabric Rest API生成令牌

如何阻止注释被包含在C#release build. exe中

使用LayoutKind在C#中嵌套 struct .显式

模型绑定RazorPage表单

如何将不同类型的扩展参数的javascript函数转换成C#风格?

Cosmos SDK和Newtonsoft对静态只读记录的可能Mutations

CS1660无法将lambda表达式转换为类型INavigationBase,因为它不是委托类型

调用Task.Run()与DoSomethingAsync()有什么不同?

在.NET 7.0 API控制器项目中通过继承和显式调用基类使用依赖项注入

将内置的OrderedEumable&Quot;类设置为内部类有什么好处?

用于请求用户返回列表的C#Google API

Autofac -动态实例化:手动传递构造函数