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

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

安装模板

安装Masa Blazor提供的rc2的模板

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

创建项目

  • 打开VS2022 => 新建项目
  • 搜索到一下类别!

  • 然后创建Gotrays名称的项目

项目结构

无边框处理

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

启动以后的效果:



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

完善无边框拖动

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

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

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

    效果

结尾

来着token的分享

技术交流群:737776595

.NET 创建无边框的跨平台应用的更多相关文章

  1. WPF 创建无边框的圆角窗口

    原文:WPF 创建无边框的圆角窗口 如题所述,在WPF中要创建一个没有边框且为圆角的窗体,有如下几步工作要进行: 第一步:去掉窗体默认样式的边框 首先将窗体的背景设为透明,将允许透明的属性设置为Tru ...

  2. 使用WPF创建无边框窗体

    一.无边框窗口添加窗口阴影 实际上在WPF中添加无边框窗口的窗口阴影十分简单. 首先,设置WindowStyle="None"以及AllowsTransparency=" ...

  3. CreateWindow创建无边框 可拉伸窗体

    createwindow 定义 HWND WINAPI CreateWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowNam ...

  4. qt 5 小练习 创建无边框界面

    我们大家都知道QT5 自带的界面不是那么美观,并且每个软件我们都发现他们的边框是自定义的,所以我决定写一篇这样的博文,也许已经有许许多多篇大牛写的论文了,但我还是想写一篇记录自己的学习QT的历程 首先 ...

  5. OpenCV 学习笔记(16)open创建无边框的显示窗口

    https://blog.csdn.net/weixin_41794771/article/details/93198098 讲解地址 // 1获取窗口句柄 winName 窗口名字 HWND win ...

  6. javaScript创建无边框iframe兼容ie

    <script>var m_iframe=document.createElement("iframe");m_iframe.scrolling="no&qu ...

  7. Qt 创建圆角、无边框、有阴影、可拖动的窗口 good

    程序窗口的边框,标题栏等是系统管理的,Qt 不能对其进行定制,为了实现定制的边框.标题栏.关闭按钮等,需要把系统默认的边框.标题栏去掉,然后使用 Widget 来模拟它们.这里介绍使用 QSS + Q ...

  8. WPF无边框可拖动窗体

    下面主要记录下创建无边框窗体,并且可以拖动.这种窗体主要用于弹出小窗体时. <Window x:Class="WpfApplication1.MainWindow" xmln ...

  9. electron关于无边框窗口无法拖拽移动以及点击事件失效的问题

    为了使窗口无边框,使得在某些时候让项目看起来更美观,所以在创建窗口的时候通过设置 frame 属性的值为 false 来创建无边框窗口.但是无边框窗口会产生无法移动的问题,对于这个问题我们可以在渲染进 ...

  10. 利用WPF创建含多种交互特性的无边框窗体

    咳咳,标题一口气读下来确实有点累,让我先解释一下.另外文章底部有演示程序的下载. 本文介绍利用WPF创建一个含有以下特性的窗口: 有窗口阴影,比如QQ窗口外围只有几像素的阴影: 支持透明且无边框,为了 ...

随机推荐

  1. 非常小的一个东西,Spring依赖注入Bean类型的8种情况

    大家好,我是三友~~ 今天来讲一个可能看似没有用但是实际又有点用的一个小东西,那就是@Autowired支持注入哪些Bean的类型. 为啥要讲这个呢? 故事说起来可能就比较长了. 不过长话可以短说,仅 ...

  2. React的组件化/工程化开发(脚手架)

    脚手架: create-react-app 安装脚手架: $ npm i create-react-app -g 检查安装: $ npm create-react-app --version 新建项目 ...

  3. 机器学习(三):朴素贝叶斯+贝叶斯估计+BP人工神经网络习题手算|手工推导与习题计算

    1.有 1000 个水果样例. 它们可能是香蕉,橙子或其它水果,已知每个水果的 3 种特性:是否偏长.是否甜.颜色是否是黄色 类型 长 不长 甜 不甜 黄色 非黄 Total 香蕉 400 100 3 ...

  4. 面对AI的兴起,从人类发展到个人发展,普通人应当如何抉择?

    这一周被各种 AI 卷的不行,从 ChatGPT 4.0 上线到百度文心一言发布会,再到微软的 Microsoft 365 Copilot. 网上有很多人.公众号吐嘈百度,而晓衡接触到的圈子还有一些不 ...

  5. 使用 Istioctl 安装 istio

    使用 Istioctl 安装 istio 下载 Istio 转到 Istio 发布 页面,下载针对你操作系统的安装文件, 或用自动化工具下载并提取最新版本(Linux 或 macOS): [root@ ...

  6. win32api中文在线文档

    中文文档http://www.yfvb.com/help/win32sdk/ 英文手册https://www.jb51.net/books/724576.html

  7. [MYSQL/JDBC]mysql-connector-java与MySQL、JDK对应的兼容版本[转载]

    1 文由 MYSQL 数据库版本 与 驱动版本之间的兼容性,可能会涉及到 部分数据库特性(函数.语法)等是否能够正常使用的问题. 2 兼容性: mysql-connector-java VS Mysq ...

  8. 扒一扒Nacos、OpenFeign、Ribbon、loadbalancer组件协调工作的原理

    大家好,我是三友~~ 前几天有个大兄弟问了我一个问题,注册中心要集成SpringCloud,想实现SpringCloud的负载均衡,需要实现哪些接口和规范. 既然这个兄弟问到我了,而我又刚好知道,这不 ...

  9. git撤销某一次commit提交

    一.使用git rebase命令 如果您想彻底删除 Git 中的某次提交的内容,可以使用 git rebase 命令并将该提交删除. 以下是删除 Git 提交内容的步骤: 找到要删除的提交的哈希值.可 ...

  10. 万字长文,带你彻底搞懂 HTTPS(文末附实战)

    大家好,我是满天星,欢迎来到我的技术角落,本期我将带你一起来了解 HTTPS. 前言 其实网上写 HTTPS 的文章也不少了,但是不少文章都是从原理上泛泛而谈,只讲概念,没有讲原因,作为小白,看完还是 ...