使用 ElementUI 组件构建无边框 Window 桌面应用(WinForm/WPF)

生活不可能像你想象得那么好,但也不会像你想象得那么糟。 我觉得人的脆弱和坚强都超乎自己的想象。 有时,我可能脆弱得一句话就泪流满面;有时,也发现自己咬着牙走了很长的路。

——莫泊桑 《一生》

一、技术栈

Vite + Vue3 + TS + ElementUI(plus) + .NET Framework 4.7.2,开发环境为 Win10,VS2019,VS Code。 

二、实现原理

1、WinForm 窗口无边框

设置属性 FormBorderStyle 为 None ,

FormBorderStyle = FormBorderStyle.None;

2、WPF 窗口无边框

设置属性 WindowStyle ="None" ,

WindowStyle = WindowStyle.None;
<Window x:Class="SerialDevTool.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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"  
        Title="MainWindow" 
        WindowStyle ="None"
        AllowsTransparency="True"
        WindowState="Normal"
        WindowStartupLocation="CenterScreen">
    <Grid>
    </Grid>
</Window> 

3、user32.dll 库

该库包含了一些与用户界面交互相关的函数,其中,ReleaseCapture 函数用于释放鼠标捕获,SendMessage 函数用于向指定的窗口发送消息。

// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-releasecapture?redirectedfrom=MSDN
// 从当前线程中的窗口释放鼠标捕获,并还原正常鼠标输入处理。 捕获鼠标的窗口接收所有鼠标输入,而不考虑光标的位置,但当光标热点位于另一个线程的窗口中时单击鼠标按钮除外。
BOOL ReleaseCapture();

// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendmessage
// 将指定的消息发送到一个或多个窗口。 SendMessage 函数调用指定窗口的窗口过程,在窗口过程处理消息之前不会返回。
LRESULT SendMessage(
  [in] HWND   hWnd,
  [in] UINT   Msg,
  [in] WPARAM wParam,
  [in] LPARAM lParam
);

4、自定义窗口拖拽实现

引入 user32.dll 库,监听界面上某区域的鼠标事件,触发鼠标事件后,通过 ReleaseCapture 函数释放当前鼠标捕获并还原正常鼠标输入处理,由 SendMessage 函数实现当前窗口的移动过程。

5、Chromium Embedded Framework

通过 CefSharp 库内嵌一个浏览器控件到 DotNet 窗口应用中。

6、接收 Javascript 信息

ChromiumWebBrowser 类提供了 JavascriptMessageReceived 方法,

//
// 摘要:
//     Event handler that will get called when the message that originates from CefSharp.PostMessage
public event EventHandler<JavascriptMessageReceivedEventArgs> JavascriptMessageReceived;

三、TitleBar 样式设计与实现

1、布局

左边三个按钮分别触发最小化、最大/正常化、关闭窗口,标题居中,

2、代码实现

// app\src\components\TitleBarSimple.vue
<template>
  <div class="common grid-content">
    <div class="common my-button">
      <el-button id="minimizedButton" @click="minimizedWindow" type="danger" circle />
      <el-button id="normalizedButton" @click="normalizedWindow" type="primary" circle />
      <el-button id="closeButton" @click="closeWindow" type="default" circle />
    </div>
    <div @mousedown="handleMouseDown" class="common my-title-bar" id="my-title">
      <div> <el-text tag="b">{{mytitle}}</el-text> </div>
    </div>
  </div>
</template>

<script lang="ts" setup>

const mytitle:string = 'Awesome Application 版本 1.0.0.0(开发版本) (64 位)'

/**最小化窗口 */
const minimizedWindow = () => {
  const ret = { type: 'minimized' };
  CefSharp.PostMessage(ret);
}

/**关闭窗口 */
const closeWindow = () => {
  const ret = { type: 'close' };
  CefSharp.PostMessage(ret);
}

/**最大/正常窗口 */
const normalizedWindow = () => {
  const ret = { type: 'normalized' };
  CefSharp.PostMessage(ret);
}


/**鼠标左键点击事件 */
const handleMouseDown = (event: any) => {
  // 检查是否是鼠标左键点击事件
  if (event.button === 0) {
    const ret = { type: 'mousedown' };
    CefSharp.PostMessage(ret);
  }
}

</script>

<style lang="scss">
/* cnpm install -D sass */

.el-row {
  margin-bottom: 20px;
}

.el-row:last-child {
  margin-bottom: 0;
}

.el-col {
  border-radius: 4px;
}

.el-button.is-circle {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  padding: 8px;
}

.common {
  display: flex;
  /* 水平居中 */
  justify-content: center; 
  /* 垂直居中 */
  align-items: center; 
}

.grid-content {
  min-height: 30px;
  margin-bottom: 5px;
  background: #FAFAFA;
}

.my-button {
  padding-left: 5px;
  width: 105px;
}

.my-title-bar {
  width: calc(100% - 105px);
}

</style>

四、WinForm 无边框实现

1、新建一个窗口项目

将默认的 Form1 重命名为 MainForm,安装 CefSharp 库 ,这里使用的版本是 119.1.20,

CefSharp.WinForms

2、初始化窗口配置


        /// <summary>
        /// 设置基础样式
        /// </summary>
        private void InitWinFormStyle()
        {
            // 无边框
            FormBorderStyle = FormBorderStyle.None;
            // 窗口大小
            Size = new Size(1280, 720);
            // 启动位置
            StartPosition = FormStartPosition.CenterScreen;
        }

3、在 UI 线程上异步执行 Action

using System;
using System.Windows.Forms;

namespace MyWinFormApp.Controls
{
    public static class ControlExtensions
    {
        /// <summary>
        /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
        /// </summary>
        /// <param name="control">the control for which the update is required</param>
        /// <param name="action">action to be performed on the control</param>
        public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
        {
            //If you are planning on using a similar function in your own code then please be sure to
            //have a quick read over https://stackoverflow.com/questions/1874728/avoid-calling-invoke-when-the-control-is-disposed
            //No action
            if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
            {
                return;
            }

            if (control.InvokeRequired)
            {
                control.BeginInvoke(action);
            }
            else
            {
                action.Invoke();
            }
        }
    }
}

4、窗口拖拽实现

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();
        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int IParam);
        /// <summary>
        /// 系统命令
        /// </summary>
        public const int WM_SYSCOMMAND = 0x0112;
        /// <summary>
        /// 移动窗口的系统命令
        /// </summary>
        public const int SC_MOVE = 0xF010;
        /// <summary>
        /// 鼠标位于窗口的标题栏上
        /// </summary>
        public const int HTCAPTION = 0x0002;

        /// <summary>
        /// 无边框窗口拖拽
        /// SC_MOVE + HTCAPTION 是将移动窗口的命令与标题栏的点击组合起来,以便在拖动标题栏时移动窗口
        /// 当用户在当前窗口按住鼠标左键并拖动时,鼠标位置会被识别为位于标题栏上,从而触发移动窗口的操作
        /// </summary>
        private void DragNoneBorderWindows()
        {
            this.InvokeOnUiThreadIfRequired(() => {
                ReleaseCapture();
                SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
            });
        }

5、接收并处理 Javascript 信息

        private void MouseDownJavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
        {
            if (e.Message != null)
            {
                dynamic ret = e.Message;
                switch (ret.type)
                {
                    case "mousedown":
                        {

                            DragNoneBorderWindows();
                            break;
                        }
                    case "minimized":
                        {
                            ChangeWindowState("minimized");
                            break;
                        }
                    case "close":
                        {
                            ChangeWindowState("close");
                            break;
                        }
                    case "normalized":
                        {
                            ChangeWindowState("normalized");
                            break;
                        }
                    default: break;
                }
            };
        }

        /// <summary>
        /// 处理窗口状态:最大化/正常化/最小化/关闭
        /// </summary>
        /// <param name="type"></param>
        private void ChangeWindowState(string type)
        {
            this.InvokeOnUiThreadIfRequired(() => {

                if (type.Equals("minimized"))
                {
                    this.WindowState = FormWindowState.Minimized;
                    return;
                }
                if (type.Equals("maximized"))
                {
                    this.WindowState = FormWindowState.Maximized;
                    return;
                }
                if (type.Equals("normalized"))
                {
                    if(this.WindowState == FormWindowState.Normal)
                    {
                        this.WindowState = FormWindowState.Maximized;
                        return;
                    }

                    this.WindowState = FormWindowState.Normal;
                    return;
                }
                if (type.Equals("close"))
                {
                    this.DoCloseWindows();
                    return;
                }
            });
        }
        /// <summary>
        /// 关闭窗口
        /// </summary>
        public void DoCloseWindows()
        {
            this.InvokeOnUiThreadIfRequired(() =>
            {
                browser.Dispose();
                Cef.Shutdown();
                Close();
            });
        }

6、添加浏览器控件

        /// <summary>
        /// Create a new instance in code or add via the designer
        /// </summary>
        private void AddChromiumWebBrowser()
        {
            browser = new ChromiumWebBrowser("http://localhost:5173/");
            // 消息接收事件
            browser.JavascriptMessageReceived += MouseDownJavascriptMessageReceived;
            this.Controls.Add(browser);
        }

7、配置 CEF

using CefSharp;
using CefSharp.WinForms;
using System;
using System.IO;
using System.Windows.Forms;

namespace MyWinFormApp
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            InitCefSettings();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }

        private static void InitCefSettings()
        {

#if ANYCPU
            CefRuntime.SubscribeAnyCpuAssemblyResolver();
#endif

            // Pseudo code; you probably need more in your CefSettings also.
            var settings = new CefSettings()
            {
                //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
                CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
            };

            //Example of setting a command line argument
            //Enables WebRTC
            // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access
            // - CEF Doesn't currently support displaying a UI for media access permissions
            //
            //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart
            settings.CefCommandLineArgs.Add("enable-media-stream");
            //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
            settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
            //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
            settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");

            //Perform dependency check to make sure all relevant resources are in our output directory.
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
        }

    }
}

8、运行效果

五、WPF 无边框实现

1、新建一个窗口项目

安装 CefSharp 库 ,这里使用的版本是 119.1.20,

2、初始化窗口配置

<Window x:Class="MyWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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"
        xmlns:local="clr-namespace:MyWpfApp"
        WindowStyle ="None"
        Width="960"
        Height="540"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d"
        Title="MainWindow">
    <Grid>
        <Grid x:Name="ContentGrid"></Grid>
    </Grid>
</Window>
        /// <summary>
        /// 设置基础样式
        /// </summary>
        private void InitWindowsStyle()
        {
            // 无边框
            WindowStyle = WindowStyle.None;
            // 窗口大小
            Width = 960;
            Height = 540;
            // 启动位置
            WindowStartupLocation = WindowStartupLocation.CenterScreen;
        }

3、在 UI 线程上异步执行 Action

using System;
using System.Windows.Threading;

namespace MyWpfApp.Dispatchers
{
    public static class DispatcherExtensions
    {
        /// <summary>
        /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
        /// </summary>
        /// <param name="dispatcher">the dispatcher for which the update is required</param>
        /// <param name="action">action to be performed on the dispatcher</param>
        public static void InvokeOnUiThreadIfRequired(this Dispatcher dispatcher, Action action)
        {
            if (dispatcher.CheckAccess())
            {
                action.Invoke();
            }
            else
            {
                dispatcher.BeginInvoke(action);
            }
        }
    }
}

4、窗口拖拽实现

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();
        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int IParam);
        /// <summary>
        /// 系统指令
        /// </summary>
        public const int WM_SYSCOMMAND = 0x0112;
        /// <summary>
        /// 鼠标移动
        /// </summary>
        public const int SC_MOVE = 0xF010;
        public const int HTCAPTION = 0x0002;

        /// <summary>
        /// 无边框窗口拖拽
        /// </summary>
        private void DragNoneBorderWindows()
        {
            Application.Current.Dispatcher.InvokeOnUiThreadIfRequired(() => {
                ReleaseCapture();
                SendMessage(new WindowInteropHelper(this).Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
            });
        }

5、接收并处理 Javascript 信息


        private void MouseDownJavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
        {
            if (e.Message != null)
            {
                dynamic ret = e.Message;
                switch (ret.type)
                {
                    case "mousedown":
                        {

                            DragNoneBorderWindows();
                            break;
                        }
                    case "minimized":
                        {
                            ChangeWindowState("minimized");
                            break;
                        }
                    case "close":
                        {
                            ChangeWindowState("close");
                            break;
                        }
                    case "normalized":
                        {
                            ChangeWindowState("normalized");
                            break;
                        }
                    default: break;
                }
            };
        }

        /// <summary>
        /// 处理窗口状态:最大化/正常化/最小化/关闭
        /// </summary>
        /// <param name="type"></param>
        private void ChangeWindowState(string type)
        {
            Application.Current.Dispatcher.InvokeOnUiThreadIfRequired(() => {

                if (type.Equals("minimized"))
                {
                    this.WindowState = WindowState.Minimized;
                    return;
                }
                if (type.Equals("maximized"))
                {
                    this.WindowState = WindowState.Maximized;
                    return;
                }
                if (type.Equals("normalized"))
                {
                    if (this.WindowState == WindowState.Normal)
                    {
                        this.WindowState = WindowState.Maximized;
                        return;
                    }

                    this.WindowState = WindowState.Normal;
                    return;
                }
                if (type.Equals("close"))
                {
                    this.DoCloseWindows();
                    return;
                }
            });
        }
        /// <summary>
        /// 关闭窗口
        /// </summary>
        public void DoCloseWindows()
        {
            Application.Current.Dispatcher.InvokeOnUiThreadIfRequired(() =>
            {
                browser.Dispose();
                Close();
            });
        }

6、添加浏览器控件

        /// <summary>
        /// Create a new instance in code or add via the designer
        /// </summary>
        private void AddChromiumWebBrowser()
        {
            // browser = new ChromiumWebBrowser("http://localhost:5173/");
            browser = new ChromiumWebBrowser("http://http://mywpf.test");
            // 消息接收事件
            browser.JavascriptMessageReceived += MouseDownJavascriptMessageReceived;
            this.ContentGrid.Children.Add(browser);
        }

7、打包前端

npm run build

将打包后的 dist 文件夹下所有文件复制到 Fontend 文件夹,

8、配置 CEF

using CefSharp;
using CefSharp.SchemeHandler;
using CefSharp.Wpf;
using System;
using System.IO;
using System.Windows;

namespace MyWpfApp
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {

        /// <summary>
        /// 重写退出方法
        /// </summary>
        /// <param name="e"></param>
        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);

            // 关闭 CefSharp
            Cef.Shutdown();
        }

        /// <summary>
        /// 重写启动方法
        /// </summary>
        /// <param name="e"></param>
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            // 初始化 CEF
            InitCefSettings();
        }

        /// <summary>
        /// 初始化 CEF 配置
        /// </summary>
        private static void InitCefSettings()
        {

#if ANYCPU
            CefRuntime.SubscribeAnyCpuAssemblyResolver();
#endif

            // Pseudo code; you probably need more in your CefSettings also.
            var settings = new CefSettings()
            {
                //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
                CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
            };

            //Example of setting a command line argument
            //Enables WebRTC
            // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access
            // - CEF Doesn't currently support displaying a UI for media access permissions
            //
            //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart
            settings.CefCommandLineArgs.Add("enable-media-stream");
            //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
            settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
            //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
            settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");

            // 本地代理域
            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "http",
                DomainName = "mywpf.test",
                SchemeHandlerFactory = new FolderSchemeHandlerFactory(rootFolder: @"..\..\..\MyWpfApp\Frontend",
                            hostName: "mywpf.test", //Optional param no hostname/domain checking if null
                            defaultPage: "index.html") //Optional param will default to index.html
            });

            //Perform dependency check to make sure all relevant resources are in our output directory.
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
        }


    }
}

9、运行效果

参考资料

基于.Net CEF 实现 Vue 等前端技术栈构建 Windows 窗体应用-CSDN博客文章浏览阅读493次。基于 .Net CEF 库,能够使用 Vue 等前端技术栈构建 Windows 窗体应用https://blog.csdn.net/weixin_47560078/article/details/133974513一个 Vue 3 UI 框架 | Element PlusA Vue 3 based component library for designers and developersicon-default.png?t=N7T8https://element-plus.gitee.io/zh-CN/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/262506.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VS Code+MinGW 搭建Windows C++开发环境

官方文档是最香香的&#xff1a;https://code.visualstudio.com/docs/cpp/config-mingw 文章目录 1、一些非常不友好的名词1.1 什么TMD是 GNU、MinGW、GCC、gcc、g&#xff1f;1.2 MSVC 2、获取g编译器3、VS Code单文件编译和调试流程3.1 安装插件3.2 单个源文件编译运行3.3 ta…

(1)(1.10) SiK Radio v1

文章目录 前言 1 概述 2 连接无线电台 3 参数说明 前言 本文介绍了如何将 3DR Radio v1 连接到飞行控制器。你还应阅读 SiK Radio v2&#xff0c;其中包含更详细的用户指南和功能列表。 1 概述 3DR 无线电设备是在自动驾驶仪和地面站之间建立遥测连接的最简单方法。 3DR…

HarmonyOS应用事件打点开发指导

简介 传统的日志系统里汇聚了整个设备上所有程序运行的过程流水日志&#xff0c;难以识别其中的关键信息。因此&#xff0c;应用开发者需要一种数据打点机制&#xff0c;用来评估如访问数、日活、用户操作习惯以及影响用户使用的关键因素等关键信息。 HiAppEvent 是在系统层面…

宋仕强论道之华强北存在的价值(二十九)

华强北特点是小快灵&#xff0c;主要服务散布在世界各地游离态的小体量硬件研发生产企业&#xff0c;这种企业也很难找到大一点的供应商来配套&#xff0c;以前覆盖珠三角长三角&#xff0c;现在是辐射世界各地。华强北是一个大集散地&#xff0c;据华强电子网统计&#xff0c;…

ubuntu 18.04 共享屏幕

用于windows远程ubuntu 1. sudo apt install xrdp 2. 配置 sudo vim /etc/xrdp/startwm.sh 把最下面的test和exec两行注释掉&#xff0c;添加一行 gnome-session 3.安装dconf-editor : sudo apt-get install dconf-editor 关闭require encrytion org->gnome->desktop…

【数据结构】五、数组与广义表

目录 一、定义 二、计算数组元素地址 三、稀疏矩阵快速转置 稀疏矩阵的表示 稀疏矩阵快速转置 四、广义表 一、定义 我们所熟知的一维、二维数组的元素是原子类型。广义表中的元素除了原子类型还可以是另一个线性表。当然所有的数据元素仍然属于同一类型。 这里的数组可…

深圳市城市更新区域关注程度分析数据,tiff格式,附数据可视化,精细到区县

基本信息. 数据名称: 深圳市城市更新区域关注程度分析数据 数据格式: tiff 时间版本&#xff1a;2022年 数据几何类型: 无 数据精度&#xff1a;区县 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据 数据可视化. www.bajidata.com

微信小程序-textarea组件字数实时更新

一、前言 本文实现的是在小程序中&#xff0c;textarea文本框输入文字后&#xff0c;实时显示文字的字数&#xff0c;获取更好的用户输入体验以及提示。 下图是实现的效果 二、代码实现 2-1、wxml代码 <view style"padding: 30rpx;"><view style"…

【已解决】解决Springboot项目访问本地图片等静态资源无法访问的问题

今天在开发一个招聘系统的时候&#xff0c;有投递简历功能&#xff0c;有投递就会有随之而来的查看简历对吧&#xff0c;我投递过的简历&#xff0c;另存为一个文件夹&#xff0c;就是说本地磁盘(或者服务器)有一个专门存放投递过的简历的文件夹&#xff0c;用于存放PDF&#x…

Java最全面试题专题---5、Spring面试题(1)

Spring概述&#xff08;10&#xff09; 什么是spring? Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack&#xff08;一站式&#xff…

【jvm从入门到实战】(十) 实战篇-内存调优

内存溢出和内存泄漏&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内存泄漏。内存泄漏绝大多数情况都是由堆内存泄漏引起的。少量的内存泄漏可以容忍&#x…

基于Linphone android sdk开发Android软话机

1.Linphone简介 1.1 简介 LinPhone是一个遵循GPL协议的开源网络电话或者IP语音电话&#xff08;VOIP&#xff09;系统&#xff0c;其主要如下。使用linphone&#xff0c;开发者可以在互联网上随意的通信&#xff0c;包括语音、视频、即时文本消息。linphone使用SIP协议&#…

云原生系列3-Kubernetes

1、Kubernetes概述 k8s缩写是因为k和s之间有八个字符。k8s是基于容器技术的分布式架构方案。官网&#xff1a;https://kubernetes.io/zh-cn/ Google在 2014年开源了Kubernetes项目&#xff0c;Kubernetes是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。同样类似的…

拥抱鸿蒙 - 在展讯T606平台上的探索与实践

前 言 自OpenHarmony 问世后受到了社会各界的广泛关注&#xff0c;OpenHarmony 的生态系统在如火如荼的发展。 酷派作为一家积极拥抱变化的公司&#xff0c;经过一段时间的探索与实践&#xff0c;成功实现将OpenHarmony 系统接入到展讯平台上&#xff0c;我们相信这是一个重要…

华为麒麟系统与鸿蒙系统:发展历程、问题解决与未来展望

导言 华为作为全球领先的科技企业&#xff0c;其自主研发的麒麟系统和鸿蒙系统备受瞩目。本文将深入研究这两者的发展历程、遇到的问题、解决过程&#xff0c;探讨未来的可用范围以及在全球的应用和研究趋势&#xff0c;进一步探讨在哪些方面能取胜&#xff0c;并在哪些领域发力…

芯知识 | WT2003HP8-32N语音芯片采用QFN32形式小体积封装的应用优势介绍

唯创知音WT2003HP8-32N高品质MP3音频语音芯片&#xff0c;以其QFN32&#xff08;44毫米&#xff09;封装的应用优势&#xff0c;在音频处理领域独树一帜。这款芯片不仅体积小巧&#xff0c;而且功能强大&#xff0c;适用于多种应用场景。 一、高品质音频处理 唯创知音WT2003HP…

阿里云ECS配置IPv6后,如果无法访问该服务器上的网站,可检查如下配置

1、域名解析到这个IPv6地址,同一个子域名可以同时解析到IPv4和IPv6两个地址&#xff0c;这样就可以给网站配置ip4和ipv6双栈&#xff1b; 2、在安全组规则开通端口可访问&#xff0c;设定端口后注意授权对象要特殊设置“源:::/0” 3、到服务器nginx配置处&#xff0c;增加端口…

pip 常用指令 pip download 命令用法介绍

pip download 是一个用于从Python包索引(PyPI)下载Python包的命令行工具。它可以下载特定版本的包&#xff0c;或者下载满足特定条件的所有包。 命令 pip download 的参数包括 -d 或 --dest&#xff1a;指定下载文件的保存路径。-r 或 --requirement&#xff1a;从一个需求文…

百度侯震宇详解:大模型将如何重构云计算?

12月20日&#xff0c;在2023百度云智大会智算大会上&#xff0c;百度集团副总裁侯震宇以“大模型重构云计算”为主题发表演讲。他强调&#xff0c;AI原生时代&#xff0c;面向大模型的基础设施体系需要全面重构&#xff0c;为构建繁荣的AI原生生态筑牢底座。 侯震宇表示&…

Java|IDEA 中添加编译参数 --add-exports

方法1 File > Settings > Build, Execution, Deployment > Compiler > Java Compiler > Javac Options > Override compiler parameters per-module 点击&#xff1a; 点击OK 双击Compliation options&#xff0c;输入后回车&#xff1a; 方法2 找到出错…