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

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

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

安装模板

安装Masa Blazor提供的rc2的模板

dotnet new install Masa.Template::1.0.0-rc.2 

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

创建项目

  • 打开VS2022 => 新建项目
  • 搜索到一下类别!
    .NET 创建无边框的跨平台应用
  • 然后创建Gotrays名称的项目

项目结构

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

无边框处理

修改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();     } } 

启动以后的效果:
.NET 创建无边框的跨平台应用
这样就完成了我们的无边框,但是也并不是直接可以使用,你会发现它无法拖动!下面我们将让他可以被拖动

完善无边框拖动

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

下面开始修改代码实现这个逻辑
.NET 创建无边框的跨平台应用

我们的标题栏的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/font@7.1.96/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));         }     } 

    效果

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

结尾

来着token的分享

技术交流群:737776595

发表评论

相关文章