.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. Lodash常用函数(二)

    数组/对象方法 1.remove(元素筛选,分到两个数组) 2.sortedUniq (去重,排序) 3.takeRightWhile ( 从array数组的最后一个元素开始提取元素,直到 predi ...

  2. FreeSWITCH的originate命令解析及示例

    FreeSWITCH版本:1.10.9 操作系统:CentOS 7.6.1810 originate经常用于发起呼叫,在实际工作过程中用到的也比较多,今天总结下基本用法,也方便我以后查阅. 一.wik ...

  3. 使用 Istioctl 安装 istio

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

  4. [网络/Java EE/Web]Tomcat/Nginx中配置全局的安全响应头(header)——X-Frame-Options / X-XSS-Protection / X-Content-Options

    Step1 配置Tomcat step1.1 查看是否已配置目标的HTTP网络安全头 方式1 – Tomcat / conf/web.xml cat /opt/myTomcat/conf/web.xm ...

  5. resnet18训练自定义数据集

    目录结构 dogsData.py import json import torch import os, glob import random, csv from PIL import Image f ...

  6. Spring @Profile注解使用和源码解析

    介绍 在之前的文章中,写了一篇使用Spring @Profile实现开发环境,测试环境,生产环境的切换,之前的文章是使用SpringBoot项目搭建,实现了不同环境数据源的切换,在我们实际开发中,会分 ...

  7. ASTAR机台(win7 p'rofessional)使用python tool中文显示异常问题解决

    1.双击"computer"打开界面如下,再单击"open control panel"打开控制面板. 2.在控制面板中点击"Clock,Langua ...

  8. 基于Canal实现MySQL 8.0 数据库数据同步

    前言 服务器说明 主机名称 操作系统 说明 192.168.11.82 Ubuntu 22.04 主库所在服务器 192.168.11.28 Oracle Linux Server 8.7 从库所在服 ...

  9. .net使用nacos配置,手把手教你分布式配置中心

    .net使用nacos配置,手把手教你分布式配置中心 Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. 这么优秀的分布式服务管理平台,怎么能不接入呢? nacos的安装和使 ...

  10. 在Linux上安装redis7

    1.检测虚拟机环境 1.1 bit检测命令:getconf LONG_BIT(建议使用64bit做开发) 1.2 gcc环境检测:gcc -v 如果不具备gcc环境,则使用yum -y install ...