2

.NET 创建无边框的跨平台应用 - tokengo

 11 months ago
source link: https://www.cnblogs.com/hejiale010426/p/17440603.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

.NET 创建无边框的跨平台应用

在创建了Photino应用程序以后我们发现它自带了一个标题栏,并且非常丑,我们现在要做的就是去掉这个很丑的自带标题栏,并且自定义一个更好看的,下面我们将用Masa Blazor提供的模板去进行实战。

安装Masa Blazor提供的rc2的模板

dotnet new install Masa.Template::1.0.0-rc.2
image.png
  • 打开VS2022 => 新建项目
  • 搜索到一下类别!
    image.png
  • 然后创建Gotrays名称的项目
image.png

无边框处理

修改Program.cs代码,增加SetChromeless,设置无边框

using Gotrays;
using Microsoft.Extensions.DependencyInjection;
using Photino.Blazor;

internal class Program
{
    [STAThread]
    private static void Main(string[] args)
    {
        var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);

        appBuilder.RootComponents.Add<App>("#app");
        appBuilder.Services.AddMasaBlazor();

        var app = appBuilder.Build();

        app.MainWindow
            .SetTitle("Photino Blazor Sample")
            .SetChromeless(true);

        AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
        {
        };

        app.Run();
    }
}

启动以后的效果:

image.png
这样就完成了我们的无边框,但是也并不是直接可以使用,你会发现它无法拖动!下面我们将让他可以被拖动

完善无边框拖动

我们需要支持拖动我们的标题栏的时候带动我们的窗口!

下面开始修改代码实现这个逻辑

image.png

我们的标题栏的css的样式是m-app-bar

打开wwwroot/index.html并且修改为以下代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
    <title>Gotrays</title>
    <base href="/" />
    <link href="_content/Masa.Blazor/css/masa-blazor.min.css" rel="stylesheet">
    <link href="css/app.css" rel="stylesheet" />
    <link href="Gotrays.styles.css" rel="stylesheet" />
    <link href="https://cdn.masastack.com/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
    <link href="https://cdn.masastack.com/npm/materialicons/materialicons.css" rel="stylesheet">
    <link href="https://cdn.masastack.com/npm/fontawesome/v5.0.13/css/all.css" rel="stylesheet">
    <style>
        #app .m-app-bar {
            -webkit-app-region: drag;
        }

        html {
            overflow: hidden;
        }
    </style>
</head>

<body>

    <div class="status-bar-safe-area"></div>
    <div id="app">Loading...</div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <script src="_framework/blazor.webview.js"></script>
    <script src="_content/BlazorComponent/js/blazor-component.js"></script>

    <script>
        let start = false;
        let pageX = 0;
        let pageY = 0;
        document.body.addEventListener('mousedown', evt => {
            const { target } = evt;
            const appRegion = getComputedStyle(target)['-webkit-app-region'];
            const app = document.getElementById("m-app-bar");
            app.addEventListener('mousemove', onmousemove)

            app.addEventListener("mousedown", (e) => {
                console.log(e.pageX, e.pageY);
                pageX = e.pageX;
                pageY = e.pageY;
                start = true;
            })

            app.addEventListener("mouseup", (e) => {
                start = false;
            })

            console.log("MouseDownDrag", evt, appRegion, app);
            if (appRegion === 'drag') {
                var data = {
                    Command: "MouseMove",
                    Data: {

                    }
                }
                evt.preventDefault();
                evt.stopPropagation();
            }
        });

        function onmousemove(e) {
            if (start) {
                console.log("MouseMove", e);
                var data = {
                    "Command": "MouseMove",
                    X: e.clientX - pageX,
                    Y: e.clientY - pageY
                }
                window.external.sendMessage(JSON.stringify(data));
            }

        }

    </script>
</body>

</html>

主要是添加了这个样式文件,注意的是这个相当于标记了哪个可以拖动我们的窗口的标记

    <style>
        #app .m-app-bar {
            -webkit-app-region: drag;
        }

        html {
            overflow: hidden;
        }
    </style>

下面的js的代码是为了传递窗口拖动参数实现实际的拖动


    <script>
        let start = false;
        let pageX = 0;
        let pageY = 0;
        document.body.addEventListener('mousedown', evt => {
            const { target } = evt;
            const appRegion = getComputedStyle(target)['-webkit-app-region'];
            const app = document.getElementById("m-app-bar");
            app.addEventListener('mousemove', onmousemove)

            app.addEventListener("mousedown", (e) => {
                console.log(e.pageX, e.pageY);
                pageX = e.pageX;
                pageY = e.pageY;
                start = true;
            })

            app.addEventListener("mouseup", (e) => {
                start = false;
            })

            console.log("MouseDownDrag", evt, appRegion, app);
            if (appRegion === 'drag') {
                var data = {
                    Command: "MouseMove",
                    Data: {

                    }
                }
                evt.preventDefault();
                evt.stopPropagation();
            }
        });
        function onmousemove(e) {
            if (start) {
                console.log("MouseMove", e);
                var data = {
                    "Command": "MouseMove",
                    X: e.clientX - pageX,
                    Y: e.clientY - pageY
                }
                window.external.sendMessage(JSON.stringify(data));
            }
        }

    </script>

修改Program.cs文件的代码支持拖动

using System.Diagnostics;
using Gotrays;
using Microsoft.Extensions.DependencyInjection;
using Photino.Blazor;
using PhotinoNET;
using System.Runtime.InteropServices;
using System.Text.Json;

internal class Program
{
    [STAThread]
    private static void Main(string[] args)
    {
        var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);

        appBuilder.RootComponents.Add<App>("#app");
        appBuilder.Services.AddMasaBlazor();

        var app = appBuilder.Build();

        app.MainWindow

            .SetTitle("Photino Blazor Sample")
            .SetChromeless(true)
            .RegisterWebMessageReceivedHandler(MessageReceived);

        AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
        {
        };

        app.Run();
    }

    private static void MessageReceived(object? sender, string message)
    {
        var window = sender as PhotinoWindow;
        if (message.StartsWith("{"))
        {
            var data = JsonSerializer.Deserialize<Message>(message);

            if (data == null || data.Command != "MouseMove") return;

            var left = window.Left + data.X;
            var top = window.Top + data.Y;
            if (left <= -window.Width / 2)
            {
                left = -window.Width / 2;
            }

            if (window.Top < 0)
            {
                window.Top = 0;
            }

            window.SetLeft((int)((int)left));
            window.SetTop((int)((int)top));
        }
    }

}

public class Message
{
    public string Command { get; set; }

    public double X { get; set; }

    public double Y { get; set; }
}

代码实现逻辑

  • 首先需要定义css样式,这个是相当于指定了哪个元素可以被拖动

    #app .m-app-bar {
                -webkit-app-region: drag;
            }
    
  • 然后定义js脚本,通过js去监听拖动的事件然后计算坐标,将计算好的坐标传递到c#的事件中完成实际的窗体拖动事件

            let start = false;
            let pageX = 0;
            let pageY = 0;
            document.body.addEventListener('mousedown', evt => {
                const { target } = evt;
                const appRegion = getComputedStyle(target)['-webkit-app-region'];
                const app = document.getElementById("m-app-bar");
                app.addEventListener('mousemove', onmousemove)
    
                app.addEventListener("mousedown", (e) => {
                    pageX = e.pageX;
                    pageY = e.pageY;
                    start = true;
                })
    
                app.addEventListener("mouseup", (e) => {
                    start = false;
                })
    
                if (appRegion === 'drag') {
                    var data = {
                        Command: "MouseMove",
                        Data: {
    
                        }
                    }
                    evt.preventDefault();
                    evt.stopPropagation();
                }
            });
            function onmousemove(e) {
                if (start) {
                    console.log("MouseMove", e);
                    var data = {
                        "Command": "MouseMove",
                        X: e.clientX - pageX,
                        Y: e.clientY - pageY
                    }
                    window.external.sendMessage(JSON.stringify(data));
                }
            }
    

    当id为m-app-bar的元素被鼠标按下的时候对于pageX = e.pageXpageY = e.pageYstart = true三个值赋值,start 表示鼠标按下并且启动拖动,pageXpageY则是鼠标首次按下坐标

    当元素被mousedown触发将拖动的坐标和首次点击的坐标相减,然后就可以通过window.external.sendMessage传递到c#的代码块中,先判断Message的数据是否为json,如果是则转换模型,然后计算设置实际窗体的位置即可

    
        private static void MessageReceived(object? sender, string message)
        {
            var window = sender as PhotinoWindow;
            if (message.StartsWith("{"))
            {
                var data = JsonSerializer.Deserialize<Message>(message);
    
                if (data == null || data.Command != "MouseMove") return;
    
                var left = window.Left + data.X;
                var top = window.Top + data.Y;
                if (left <= -window.Width / 2)
                {
                    left = -window.Width / 2;
                }
    
                if (window.Top < 0)
                {
                    window.Top = 0;
                }
    
                window.SetLeft((int)((int)left));
                window.SetTop((int)((int)top));
            }
        }
    
screenshots.gif

来着token的分享

技术交流群:737776595

本文作者:tokengo

本文链接:https://www.cnblogs.com/hejiale010426/p/17440603.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK