C# 背景 透明 抗锯齿 (效果完美)

news2025/2/21 14:36:12

主要是通过 P/Invoke 技术调用 Windows API 函数 gdi32.dll/user32.dll,同时定义了一些结构体来配合这些 API 函数的使用,常用于处理图形绘制、窗口显示等操作。

运行查看效果

局部放大,抗锯齿效果很不错,尾巴毛毛清晰可见。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsFormsApp7.Resources;
using static System.Net.Mime.MediaTypeNames;

namespace WindowsFormsApp1
{
    public partial class Form1: Form
    {
        private const int WS_EX_LAYERED = 0x00080000;
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= WS_EX_LAYERED;
                return cp;
            }
        }


        public Form1()
        {
            InitializeComponent();
        }
     
        private void Form1_Load(object sender, EventArgs e)
        {
            InitializeComponent();

            var bitmap = Properties.Resources.index00;
            byte opacity = 255;//0-255 透明度调整
            double scalePercentage = 70; // 背景图片按70%缩放
            SetBitmap(bitmap, opacity, scalePercentage);

             CenterWindow(); //窗口 绝对 居中
        }
        public void SetBitmap(Bitmap bitmap, byte opacity, double scalePercentage)
        {
            // 检查传入的位图的像素格式是否为 32 位包含 alpha 通道
            if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
                // 如果不是 32 位包含 alpha 通道的格式,抛出一个应用程序异常
                throw new ApplicationException("位图必须是 32 位包含 alpha 通道");

            // 计算缩放后的宽度和高度
            int newWidth = (int)(bitmap.Width * scalePercentage / 100);
            int newHeight = (int)(bitmap.Height * scalePercentage / 100);

            // 更新窗口的大小
            this.Size = new Size(newWidth, newHeight);

            // 缩放位图
            Bitmap resizedBitmap = new Bitmap(bitmap, newWidth, newHeight);

            // 获取屏幕设备上下文的句柄。设备上下文(DC)是一个包含图形对象及其属性、影响输出的图形模式的结构
            IntPtr screenDc = APIAliasing.GetDC(IntPtr.Zero);
            // 创建一个与指定设备上下文(这里是屏幕设备上下文)兼容的内存设备上下文
            IntPtr memDc = APIAliasing.CreateCompatibleDC(screenDc);
            // 初始化一个 IntPtr 类型的变量,用于存储位图的句柄,初始值为 IntPtr.Zero 表示空句柄
            IntPtr hBitmap = IntPtr.Zero;
            // 初始化一个 IntPtr 类型的变量,用于存储之前选入内存设备上下文的对象的句柄,初始值为 IntPtr.Zero 表示空句柄
            IntPtr oldBitmap = IntPtr.Zero;

            try
            {
                // 将 Bitmap 对象转换为 GDI 位图,并返回该位图的句柄。Color.FromArgb(0) 表示使用透明颜色
                hBitmap = resizedBitmap.GetHbitmap(Color.FromArgb(0));

                // 将指定的位图选入指定的设备上下文,并返回之前选入该设备上下文的对象的句柄
                oldBitmap = APIAliasing.SelectObject(memDc, hBitmap);

                // 创建一个 APIAliasing.Size 结构体的实例,用于表示位图的宽度和高度
                APIAliasing.Size size = new APIAliasing.Size(newWidth, newHeight);
                // 创建一个 APIAliasing.Point 结构体的实例,用于表示位图的源点(这里是左上角,坐标为 (0, 0))
                APIAliasing.Point pointSource = new APIAliasing.Point(0, 0);
                // 创建一个 APIAliasing.Point 结构体的实例,用于表示要绘制位图的目标位置,Left 和 Top 应该是类的属性,表示控件的左上角坐标
                APIAliasing.Point topPos = new APIAliasing.Point(Left, Top);
                // 创建一个 APIAliasing.BLENDFUNCTION 结构体的实例,用于指定混合操作的参数
                APIAliasing.BLENDFUNCTION blend = new APIAliasing.BLENDFUNCTION();
                // 设置混合操作的模式为 AC_SRC_OVER,表示源位图覆盖目标位图
                blend.BlendOp = APIAliasing.AC_SRC_OVER;
                // 混合标志,这里设置为 0 表示没有特殊的混合标志
                blend.BlendFlags = 0;
                // 设置源位图的常量 alpha 值,取值范围是 0 - 255,由传入的 opacity 参数决定
                blend.SourceConstantAlpha = opacity;
                // 设置 alpha 通道的格式为 AC_SRC_ALPHA,表示使用源位图的 alpha 通道
                blend.AlphaFormat = APIAliasing.AC_SRC_ALPHA;

                // 更新分层窗口的内容,将位图绘制到指定的窗口上。
                // Handle 是窗口的句柄,screenDc 是屏幕设备上下文,topPos 是目标位置,size 是位图大小,
                // memDc 是内存设备上下文,pointSource 是源点,0 是颜色键(这里不使用),blend 是混合参数,
                // APIAliasing.ULW_ALPHA 表示使用 alpha 混合模式
                APIAliasing.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, APIAliasing.ULW_ALPHA);
            }
            finally
            {
                // 释放之前获取的屏幕设备上下文,将其返回给系统
                APIAliasing.ReleaseDC(IntPtr.Zero, screenDc);
                // 检查位图句柄是否不为空
                if (hBitmap != IntPtr.Zero)
                {
                    // 将之前选入内存设备上下文的对象重新选入,恢复设备上下文的状态
                    APIAliasing.SelectObject(memDc, oldBitmap);

                    // 删除之前创建的 GDI 位图对象,释放相关的系统资源
                    APIAliasing.DeleteObject(hBitmap);
                }
                // 删除之前创建的内存设备上下文,释放相关的系统资源
                APIAliasing.DeleteDC(memDc);

                // 释放缩放后的位图资源
                resizedBitmap.Dispose();
            }
        }

        public void CenterWindow()
        {
            // 获取屏幕的工作区域(不包括任务栏)
            Rectangle screenBounds = Screen.PrimaryScreen.WorkingArea;

            // 计算窗口居中时的左上角坐标
            int left = (screenBounds.Width - Width) / 2 + screenBounds.Left;
            int top = (screenBounds.Height - Height) / 2 + screenBounds.Top;

            // 设置窗口的位置
            Location = new Point(left, top);
        }

    }
}

添加类 类名:APIAliasing

// 定义一个公共类 APIAliasing,用于封装一些 Windows API 相关的辅助功能
class APIAliasing
{
    // 使用 StructLayout 属性指定结构体在内存中的布局方式为顺序布局
    // 顺序布局意味着结构体的字段在内存中按照声明的顺序依次排列
    [StructLayout(LayoutKind.Sequential)]
    // 定义一个公共结构体 Size,用于表示二维平面上的大小,通常包含宽度和高度信息
    public struct Size
    {
        // 定义一个 32 位有符号整数类型的字段 cx,用于表示宽度
        public Int32 cx;
        // 定义一个 32 位有符号整数类型的字段 cy,用于表示高度
        public Int32 cy;

        // 定义结构体的构造函数,用于初始化结构体的字段
        // 参数 x 用于初始化 cx 字段,参数 y 用于初始化 cy 字段
        public Size(Int32 x, Int32 y)
        {
            // 将参数 x 的值赋给字段 cx
            cx = x;
            // 将参数 y 的值赋给字段 cy
            cy = y;
        }
    }

    // 使用 StructLayout 属性指定结构体在内存中的布局方式为顺序布局,并且设置字节对齐方式为 1 字节
    // 这样可以确保结构体的字段在内存中紧密排列,没有额外的填充字节
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    // 定义一个公共结构体 BLENDFUNCTION,用于表示混合操作的相关参数
    public struct BLENDFUNCTION
    {
        // 定义一个字节类型的字段 BlendOp,用于指定混合操作的类型
        public byte BlendOp;
        // 定义一个字节类型的字段 BlendFlags,用于指定混合操作的标志位
        public byte BlendFlags;
        // 定义一个字节类型的字段 SourceConstantAlpha,用于指定源图像的常量透明度值
        public byte SourceConstantAlpha;
        // 定义一个字节类型的字段 AlphaFormat,用于指定源图像的透明度格式
        public byte AlphaFormat;
    }

    // 使用 StructLayout 属性指定结构体在内存中的布局方式为顺序布局
    [StructLayout(LayoutKind.Sequential)]
    // 定义一个公共结构体 Point,用于表示二维平面上的一个点,通常包含 x 和 y 坐标信息
    public struct Point
    {
        // 定义一个 32 位有符号整数类型的字段 x,用于表示点的 x 坐标
        public Int32 x;
        // 定义一个 32 位有符号整数类型的字段 y,用于表示点的 y 坐标
        public Int32 y;

        // 定义结构体的构造函数,用于初始化结构体的字段
        // 参数 x 用于初始化字段 x,参数 y 用于初始化字段 y
        public Point(Int32 x, Int32 y)
        {
            // 将参数 x 的值赋给字段 x
            this.x = x;
            // 将参数 y 的值赋给字段 y
            this.y = y;
        }
    }

    // 定义一个公共常量 AC_SRC_OVER,值为 0
    // 该常量通常用于指定混合操作的模式,表示源图像覆盖目标图像
    public const byte AC_SRC_OVER = 0;
    // 定义一个公共常量 ULW_ALPHA,值为 2
    // 该常量通常用于 UpdateLayeredWindow 函数,表示使用 alpha 混合
    public const Int32 ULW_ALPHA = 2;
    // 定义一个公共常量 AC_SRC_ALPHA,值为 1
    // 该常量通常用于指定源图像包含 alpha 通道信息
    public const byte AC_SRC_ALPHA = 1;

    // 使用 DllImport 属性引入 gdi32.dll 动态链接库中的 CreateCompatibleDC 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于创建一个与指定设备上下文兼容的内存设备上下文
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 CreateCompatibleDC,用于调用 Windows API 中的同名函数
    // 参数 hDC 表示要创建兼容设备上下文的源设备上下文句柄
    // 返回值为创建的兼容设备上下文的句柄
    public static extern IntPtr CreateCompatibleDC(IntPtr hDC);

    // 使用 DllImport 属性引入 user32.dll 动态链接库中的 GetDC 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于获取指定窗口的设备上下文句柄
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 GetDC,用于调用 Windows API 中的同名函数
    // 参数 hWnd 表示要获取设备上下文的窗口句柄
    // 返回值为获取的设备上下文的句柄
    public static extern IntPtr GetDC(IntPtr hWnd);

    // 使用 DllImport 属性引入 gdi32.dll 动态链接库中的 SelectObject 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // 该函数用于将指定的对象(如位图、画笔等)选入指定的设备上下文中
    [DllImport("gdi32.dll", ExactSpelling = true)]
    // 定义一个公共静态外部方法 SelectObject,用于调用 Windows API 中的同名函数
    // 参数 hDC 表示要选入对象的设备上下文句柄
    // 参数 hObj 表示要选入设备上下文的对象句柄
    // 返回值为之前选入该设备上下文的对象句柄
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);

    // 使用 DllImport 属性引入 user32.dll 动态链接库中的 ReleaseDC 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // 该函数用于释放之前通过 GetDC 函数获取的设备上下文
    [DllImport("user32.dll", ExactSpelling = true)]
    // 定义一个公共静态外部方法 ReleaseDC,用于调用 Windows API 中的同名函数
    // 参数 hWnd 表示之前获取设备上下文的窗口句柄
    // 参数 hDC 表示要释放的设备上下文句柄
    // 返回值为操作结果,非零表示成功,零表示失败
    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    // 使用 DllImport 属性引入 gdi32.dll 动态链接库中的 DeleteDC 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于删除指定的设备上下文
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 DeleteDC,用于调用 Windows API 中的同名函数
    // 参数 hDC 表示要删除的设备上下文句柄
    // 返回值为操作结果,非零表示成功,零表示失败
    public static extern int DeleteDC(IntPtr hDC);

    // 使用 DllImport 属性引入 gdi32.dll 动态链接库中的 DeleteObject 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于删除指定的图形对象(如位图、画笔等)
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 DeleteObject,用于调用 Windows API 中的同名函数
    // 参数 hObj 表示要删除的图形对象句柄
    // 返回值为操作结果,非零表示成功,零表示失败
    public static extern int DeleteObject(IntPtr hObj);

    // 使用 DllImport 属性引入 user32.dll 动态链接库中的 UpdateLayeredWindow 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于更新分层窗口的内容,支持 alpha 混合等效果
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 UpdateLayeredWindow,用于调用 Windows API 中的同名函数
    // 参数 hwnd 表示要更新的分层窗口句柄
    // 参数 hdcDst 表示目标设备上下文句柄
    // 参数 pptDst 表示目标窗口的左上角坐标,使用 Point 结构体
    // 参数 psize 表示要更新的区域大小,使用 Size 结构体
    // 参数 hdcSrc 表示源设备上下文句柄
    // 参数 pptSrc 表示源图像的左上角坐标,使用 Point 结构体
    // 参数 crKey 表示颜色键,用于指定透明颜色
    // 参数 pblend 表示混合操作的参数,使用 BLENDFUNCTION 结构体
    // 参数 dwFlags 表示更新操作的标志位
    // 返回值为操作结果,非零表示成功,零表示失败
    public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

    // 使用 DllImport 属性引入 gdi32.dll 动态链接库中的 ExtCreateRegion 函数
    // ExactSpelling = true 表示使用精确的函数名进行查找
    // SetLastError = true 表示在调用函数失败时可以通过 GetLastError 函数获取错误代码
    // 该函数用于创建一个复杂的区域对象
    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    // 定义一个公共静态外部方法 ExtCreateRegion,用于调用 Windows API 中的同名函数
    // 参数 lpXform 表示可选的变换矩阵指针
    // 参数 nCount 表示区域数据的数量
    // 参数 rgnData 表示区域数据的指针
    // 返回值为创建的区域对象的句柄
    public static extern IntPtr ExtCreateRegion(IntPtr lpXform, uint nCount, IntPtr rgnData);
}


 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于uniApp的面试题及其答案解析

我的血液里流淌着战意!力量与智慧指引着我! 文章目录 1. 什么是uniApp?2. uniApp与原生小程序开发有什么区别?3. 如何使用uniApp实现条件编译?4. uniApp支持哪些平台,各有什么特点?5. 在uniApp中…

【Java场景题】MySQL死锁排查

大家好,今天XiXi给大家分享一个MySQL死锁排查的实验,文章主要有: 通过show engine innodb status,查看最近一次死锁信息开启innodb_print_all_deadlocks,在错误日志中能够记录所有死锁信息通过解析binlog日志定位死锁…

LabVIEW心音信号采集与分析系统

基于LabVIEW软件的心音信号采集与分析系统能够实现心音的采集、去噪和分析。系统利用LabVIEW的强大功能和灵活性,通过模块化设计,实现了心音信号的高效处理和分析,具备深度学习和身份识别的实验能力,适用于医学和生物工程领域的研…

【Scrapy】Scrapy教程7——存储数据

上一节我们对爬虫程序的默认回调函数parse做了改写,提取的数据可以在Scrapy的日志中打印出来了,光打印肯定是不行的,还需要把数据存储,数据可以存到文件,也可以存到数据库,我们一一来看。 存储数据到文件 首先我们看看如何将数据存储到文件,在讲[[【Scrapy】Scrapy教程…

基础入门-算法解密散列对称非对称字典碰撞前后端逆向MD5AESDESRSA

知识点: 0、算法类型-单向散列&对称性&非对称性 1、算法识别加解密-MD5&AES&DES&RSA 2、解密条件寻找-逻辑特征&源码中&JS分析 应用场景: 1、发送数据的时候自动将数据加密发送(只需加密即可) 安全…

在UBUNTU下搭建Deepseek

在UBUNTU下搭建Deepseek 一、安装UBUNTU 这个就不多说了,无外乎下载UBUNTU的iso,然后用UltraIso制作U盘,然后重启设置启动盘,安装… 二、安装Ollama curl -sSfL https://ollama.com/install.sh | sh这里可能需要你先安装curl工…

O1 Embedder:让检索器思考后再行动

25年2月来自中科大和北京智源研究院的论文“O1 Embedder: Let Retrievers Think Before Action”。 大语言模型 (LLM) 的功能日益强大,彻底改变人们获取和利用信息的方式。值得注意的是,LLM 擅长执行细粒度数据表示,这有助于精确检索信息。它…

Ubuntu系统3分钟本地部署DeepSeek-R1蒸馏模型,支持联网

本文提供Ubuntu ollama Page Assist,3步快速安装DeepSeek-R1蒸馏模型,支持联网,支持API。 目录 DeepSeek-R1安装分3步: Step 1, 安装ollama(已安装可忽略) Step 2, 下载DeepSeek-R1模型 Step 3, 从…

谷粒商城—分布式高级②.md

认证服务 1. 环境搭建 创建gulimall-auth-server模块,导依赖,引入login.html和reg.html,并把静态资源放到nginx的static目录下 2. 注册功能 (1) 验证码倒计时 //点击发送验证码按钮触发下面函数 $("#sendCode").click(function () {//如果有disabled,说明最近…

C语言-----操作符的分类

1. 操作符的分类 •算术操作符&#xff1a; 、- 、 * 、/、% 移位操作符:<< >> 位操作符: & | ^ 赋值操作符: / 、 % 、 、- 、 *、/、 %、 <<、 >>、&、| 、 ^ 单⽬操作符&#xff1a;&#xff01;、 、- 、 & 、 * 、 、 …

PWM(脉宽调制)技术详解:从基础到应用实践示例

PWM&#xff08;脉宽调制&#xff09;技术详解&#xff1a;从基础到应用实践示例 目录 PWM&#xff08;脉宽调制&#xff09;技术详解&#xff1a;从基础到应用实践示例学前思考&#xff1a;一、PWM概述二、PWM的基本原理三、PWM的应用场景四、PWM的硬件配置与使用五、PWM的编程…

AI智能成长系统 | 应用探讨研究

研究背景 在现代家庭中&#xff0c;三岁宝宝的成长环境日益复杂。由于宝宝每天接触的人群多样&#xff0c;包括家庭成员、同龄小朋友以及可能的陌生人&#xff0c;其语言环境也相应地变得复杂多变。这种环境下&#xff0c;宝宝很容易接触到一些不适宜的语言&#xff0c;即俗称…

java 网络安全感知 网络安全学java

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 实验五 java网络编程及安全 实验内容 1&#xff0e;掌握Socket程序的编写&#xff1b;2&#xff0e;掌握密码技术的使用&#xff1b;3&#xff0e;设计安全传输…

VisionMaster4.4 python脚本 图像处理 转换函数 爱之初体验

最近有接触过一丢丢VM4.3的模块开发. 一直有把python图像处理部分模块移植进来的打算 不过时间不够没来得及折腾.偶尔发现4.4支持py脚本 于是拿来折腾.一下午. 发现4.4支持python脚本,好开心. 首先安装VM4.4 注意一定要是4.4 打开后拖了一个模块. 但是发现import numpy imp…

python-leetcode 40.二叉树的层序遍历

题目&#xff1a; 给定二叉树的根节点root,返回其节点值得层序遍历&#xff08;即逐层从左到右访问所有节点&#xff09; 方法&#xff1a;广度优先搜索 # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, val0, leftNone, rightNon…

蓝桥杯学习大纲

&#xff08;致酷德与热爱算法、编程的小伙伴们&#xff09; 在查阅了相当多的资料后&#xff0c;发现没有那篇博客、文章很符合我们备战蓝桥杯的学习路径。所以&#xff0c;干脆自己整理一篇&#xff0c;欢迎大家补充&#xff01; 一、蓝桥必备高频考点 我们以此为重点学习…

小米AX3000T 路由器如何开启 SSH 安装 OpenWRT 系统,不需要降级 v1.0.91 (2025)

小米AX3000T 路由器如何开启 SSH 安装 OpenWRT 系统&#xff0c;不需要降级 v1.0.91 &#xff08;2025&#xff09; 本文内容需要你有一定的 Linux 操作基础&#xff0c;最好是程序员那种&#xff0c;英文水平足够用才行。一般人不需要使用这么复杂的路由器操作系统&#xff0c…

水基试剂,湿式化学,清水,干式化学,干粉,卤烃清洁剂,二氧化碳灭火器UL8检测报告标准讲解:

水基试剂&#xff0c;湿式化学&#xff0c;清水&#xff0c;干式化学&#xff0c;干粉&#xff0c;卤烃清洁剂&#xff0c;二氧化碳灭火器UL检测报告标准讲解&#xff1a; 本政策涵盖的灭火器 水基试剂灭火器 水基试剂灭火器使用水基试剂带走燃烧三要素中的热量要素&#xf…

汽车免拆诊断案例 | 2010 款路虎揽胜车空调偶尔出风异常

故障现象  一辆2010款路虎揽胜车&#xff0c;搭载5.0 L发动机&#xff0c;累计行驶里程约为16万km。车主反映&#xff0c;接通空调开关后&#xff0c;有时出风忽大忽小&#xff0c;有时不出风&#xff0c;有时要等2 min左右才出风&#xff1b;有时两三天出现一次&#xff0c;…

Mac arm架构使用 Yarn 全局安装 Vue CLI

dgqdgqdeMacBook-Pro spid-admin % vue --version zsh: command not found: vue要使用 Yarn 安装 Vue CLI&#xff0c;你可以执行以下命令&#xff1a; yarn global add vue/cli这个命令会全局安装 Vue CLI&#xff0c;让你可以使用 vue 命令创建、管理 Vue.js 项目。以下是一…