详解C#之WinForm版利用RichTextBox 制作文本编辑器【附源码】

在Windows应用程序开发中,刚刚介绍了WPF版的利用RichTextBox实现文本编辑器,今天继续推出WinForm版的利用RichTextBox实现文本编辑器。本文利用一个简单的小例子,简述如何在WinForm开发中,利用RichTextBox开发文本编辑器,以及RichTextBox的用法,仅供学习分享使用,如有不足之处,还请指正。

图片

Windows窗体中的RichTextBox控件用于显示,输入和操作格式化的文本,RichTextBox除了拥有TextBox控件的所有功能外,还可以显示字体,颜色,链接,从文件中读取和加载图像,以及查找指定的字符。RichTextBox控件通常用于提供类似字体处理程序(如Microsoft Word)的文本操作和显示功能。RichTextBox控件可以显示滚动条,且默认根据需要进行显示。

涉及知识点

在本示例中,涉及知识点如下所示:

  • SelectionFont 获取或设置当前选定文本或插入点的字体。

  • FontStyle 指定应用到文本的字形信息。

  • SelectionAlignment  获取或设置应用到当前选定内容或插入点的对齐方式。

  • SelectionIndent 获取或设置所选内容开始行的缩进距离(以像素为单位)。

  • SelectionCharOffset 获取或设置控件中的文本是显示在基线上、作为上标还是作为基线下方的下标。

  • SelectionColor 获取或设置当前选定文本或插入点的文本颜色。

  • SelectionBackColor   获取或设置在 System.Windows.Forms.RichTextBox 控件中选中文本时文本的颜色。

  • SelectionBullet 获取或设置一个值,通过该值指示项目符号样式是否应用到当前选定内容或插入点。

  • Clipboard Paste 粘贴指定剪贴板格式的剪贴板内容【插入图片时使用】。

  • Find 在对搜索应用特定选项的情况下,在 System.Windows.Forms.RichTextBox 控件的文本中搜索位于控件内特定位置的字符串。

核心代码

1. 定义接口

为了规范和统一,定义实现样式接口IRichFormat,如下所示:

namespace DemoRichText.Model
{
    /// <summary>
    /// 富文本框格式
    /// </summary>
    public interface IRichFormat
    {
        void SetFormat(RichTextBox rtbInfo);
    }
}

2. 实现样式基类

定义一个接口的默认实现基类BaseRichFormat,此基类是抽象类,如下所示:

namespace DemoRichText.Model
{
    public abstract class BaseRichFormat : IRichFormat
    {
        public abstract void SetFormat(RichTextBox rtbInfo);
    }
}

3. 具体实现方法

具体到每一个功能样式设置,均继承自BaseRichFormat,如下所示:

namespace DemoRichText.Model
{
    public class DefaultRickFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {

        }
    }

    /// <summary>
    /// 加粗格式
    /// </summary>
    public class BoldRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            Font oldFont = rtbInfo.SelectionFont;
            Font newFont;
            if (oldFont.Bold)
            {
                newFont = new Font(oldFont, oldFont.Style & ~FontStyle.Bold);//支持位于运算
            }
            else
            {
                newFont = new Font(oldFont, oldFont.Style | FontStyle.Bold);
            }
            rtbInfo.SelectionFont = newFont;
        }
    }

    /// <summary>
    /// 斜体
    /// </summary>
    public class ItalicRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            Font oldFont = rtbInfo.SelectionFont;
            Font newFont;
            if (oldFont.Italic)
            {
                newFont = new Font(oldFont, oldFont.Style & ~FontStyle.Italic);
            }
            else
            {
                newFont = new Font(oldFont, oldFont.Style | FontStyle.Italic);
            }
            rtbInfo.SelectionFont = newFont;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 下划线
    /// </summary>
    public class UnderLineRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            Font oldFont = rtbInfo.SelectionFont;
            Font newFont;
            if (oldFont.Underline)
            {
                newFont = new Font(oldFont, oldFont.Style & ~FontStyle.Underline);
            }
            else
            {
                newFont = new Font(oldFont, oldFont.Style | FontStyle.Underline);
            }
            rtbInfo.SelectionFont = newFont;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 删除线
    /// </summary>
    public class StrikeLineRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            Font oldFont = rtbInfo.SelectionFont;
            Font newFont;
            if (oldFont.Underline)
            {
                newFont = new Font(oldFont, oldFont.Style & ~FontStyle.Strikeout);
            }
            else
            {
                newFont = new Font(oldFont, oldFont.Style | FontStyle.Strikeout);
            }
            rtbInfo.SelectionFont = newFont;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 左对齐
    /// </summary>
    public class LeftRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            rtbInfo.SelectionAlignment = HorizontalAlignment.Left;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 居中对齐
    /// </summary>
    public class CenterRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            if (rtbInfo.SelectionAlignment == HorizontalAlignment.Center)
            {
                rtbInfo.SelectionAlignment = HorizontalAlignment.Left;
            }
            else
            {
                rtbInfo.SelectionAlignment = HorizontalAlignment.Center;
            }

            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 右对齐
    /// </summary>
    public class RightRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            if (rtbInfo.SelectionAlignment == HorizontalAlignment.Right)
            {
                rtbInfo.SelectionAlignment = HorizontalAlignment.Left;
            }
            else
            {
                rtbInfo.SelectionAlignment = HorizontalAlignment.Right;
            }

            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 缩进对齐
    /// </summary>
    public class IndentRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            //每次以10个像素进行缩进
            rtbInfo.SelectionIndent = rtbInfo.SelectionIndent + 10;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 缩进对齐
    /// </summary>
    public class OutIndentRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            //每次以10个像素进行缩进
            rtbInfo.SelectionIndent = rtbInfo.SelectionIndent - 10;
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 下标
    /// </summary>
    public class SubScriptRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            if (rtbInfo.SelectionCharOffset < 0)
            {
                rtbInfo.SelectionCharOffset = 0;
            }
            else {
                rtbInfo.SelectionCharOffset = -5;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 上标
    /// </summary>
    public class SuperScriptRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            if (rtbInfo.SelectionCharOffset > 0)
            {
                rtbInfo.SelectionCharOffset = 0;
            }
            else {
                rtbInfo.SelectionCharOffset = 5;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 字体
    /// </summary>
    public class FontRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            FontDialog f = new FontDialog();
            if (f.ShowDialog() == DialogResult.OK)
            {
                FontFamily family = f.Font.FontFamily;
                rtbInfo.SelectionFont = new Font(family, rtbInfo.SelectionFont.Size, rtbInfo.SelectionFont.Style);
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 文本颜色
    /// </summary>
    public class ForeColorRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            ColorDialog f = new ColorDialog();
            if (f.ShowDialog() == DialogResult.OK)
            {

                rtbInfo.SelectionColor = f.Color;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 文本背景颜色
    /// </summary>
    public class BgColorRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            ColorDialog f = new ColorDialog();
            if (f.ShowDialog() == DialogResult.OK)
            {

                rtbInfo.SelectionBackColor = f.Color;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// UL列表,项目符号样式
    /// </summary>
    public class UlRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            if (rtbInfo.SelectionBullet)
            {
                rtbInfo.SelectionBullet = false;
            }
            else {
                rtbInfo.SelectionBullet = true;
                rtbInfo.BulletIndent = 10;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 图片插入
    /// </summary>
    public class PicRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            OpenFileDialog o = new OpenFileDialog();
            o.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
            o.Title = "请选择图片";
            o.Filter = "jpeg|*.jpeg|jpg|*.jpg|png|*.png|gif|*.gif";
            if (o.ShowDialog() == DialogResult.OK) {
                string fileName = o.FileName;
                try
                {
                   Image bmp = Image.FromFile(fileName);
                   Clipboard.SetDataObject(bmp);

                    DataFormats.Format dataFormat = DataFormats.GetFormat(DataFormats.Bitmap);
                    if (rtbInfo.CanPaste(dataFormat))
                    {
                        rtbInfo.Paste(dataFormat);
                    }

                }
                catch (Exception exc)
                {
                    MessageBox.Show("图片插入失败。" + exc.Message, "提示",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 删除
    /// </summary>
    public class DelRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            rtbInfo.SelectedText = "";
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 查找
    /// </summary>
    public class SearchRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            string find = rtbInfo.Tag.ToString();
            int index=  rtbInfo.Find(find, 0,RichTextBoxFinds.None);
            int startPos = index;
            int nextIndex = 0;
            while (nextIndex != startPos)//循环查找字符串,并用蓝色加粗12号Times New Roman标记之
            {
                rtbInfo.SelectionStart = index;
                rtbInfo.SelectionLength = find.Length;
                rtbInfo.SelectionColor = Color.Blue;
                rtbInfo.SelectionFont = new Font("Times New Roman", (float)12, FontStyle.Bold);
                rtbInfo.Focus();
                nextIndex = rtbInfo.Find(find, index + find.Length, RichTextBoxFinds.None);
                if (nextIndex == -1)//若查到文件末尾,则充值nextIndex为初始位置的值,使其达到初始位置,顺利结束循环,否则会有异常。
                {
                    nextIndex = startPos;
                }
                index = nextIndex;
            }
            rtbInfo.Focus();
        }
    }

    /// <summary>
    /// 打印
    /// </summary>
    public class PrintRichFormat : BaseRichFormat
    {
        private RichTextBox richTextbox;

        public override void SetFormat(RichTextBox rtbInfo)
        {
            this.richTextbox = rtbInfo;
            PrintDocument pd = new PrintDocument();
            pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
            // 打印文档
            pd.Print();
        }

        private void pd_PrintPage(object sender, PrintPageEventArgs ev)
        {
            //ev.Graphics.DrawString(richTextbox.Text);
            //ev.HasMorePages = true;
        }
    }

    /// <summary>
    /// 字体大小
    /// </summary>
    public class FontSizeRichFormat : BaseRichFormat
    {
        public override void SetFormat(RichTextBox rtbInfo)
        {
            string fontSize = rtbInfo.Tag.ToString();
            float fsize = 0.0f;
            if (float.TryParse(fontSize, out fsize)) {
                rtbInfo.SelectionFont = new Font(rtbInfo.Font.FontFamily, fsize, rtbInfo.SelectionFont.Style);
            }
            rtbInfo.Focus();
        }
    }
}

4. 实现工厂模式

因为所有实现都基于同一个接口,所以进一步封装样式设置的实现类,如下所示:

​​​​​​​

namespace DemoRichText.Model
{
    public class RichFormatFactory
    {
        public static IRichFormat CreateRichFormat(BTNType btnType)
        {
            IRichFormat richFormat;
            switch (btnType)
            {
                case BTNType.Bold:
                    richFormat = new BoldRichFormat();
                    break;
                case BTNType.BGColor:
                    richFormat = new BgColorRichFormat();
                    break;
                case BTNType.Center:
                    richFormat = new CenterRichFormat();
                    break;
                case BTNType.Del:
                    richFormat = new DelRichFormat();
                    break;
                case BTNType.Font:
                    richFormat = new FontRichFormat();
                    break;
                case BTNType.ForeColor:
                    richFormat = new ForeColorRichFormat();
                    break;
                case BTNType.FontSize:
                    richFormat = new FontSizeRichFormat();
                    break;
                case BTNType.Indent:
                    richFormat = new IndentRichFormat();
                    break;
                case BTNType.Italic:
                    richFormat = new ItalicRichFormat();
                    break;
                case BTNType.Left:
                    richFormat = new LeftRichFormat();
                    break;
                case BTNType.OutIndent:
                    richFormat = new OutIndentRichFormat();
                    break;
                case BTNType.Pic:
                    richFormat = new PicRichFormat();
                    break;
                case BTNType.Print:
                    richFormat = new PrintRichFormat();
                    break;
                case BTNType.Right:
                    richFormat = new RightRichFormat();
                    break;
                case BTNType.Search:
                    richFormat = new SearchRichFormat();
                    break;
                case BTNType.StrikeLine:
                    richFormat = new StrikeLineRichFormat();
                    break;
                case BTNType.SubScript:
                    richFormat = new SubScriptRichFormat();
                    break;
                case BTNType.SuperScript:
                    richFormat = new SuperScriptRichFormat();
                    break;
                case BTNType.Ul:
                    richFormat = new UlRichFormat();
                    break;
                case BTNType.UnderLine:
                    richFormat = new UnderLineRichFormat();
                    break;
                default:
                    richFormat = new DefaultRickFormat();
                    break;

            }
            return richFormat;
        }
    }
}

5. UI页面代码

由于实现了代码封装,所有页面代码较少,如下所示:

namespace DemoRichText
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }


        public void btnButtonClick(object sender, EventArgs e) {
            Button btn = (Button)sender;
            BTNType btnType;
            if (Enum.TryParse<BTNType>(btn.Tag.ToString(), out btnType)) {
                if (btnType == BTNType.Search) {
                    if (!string.IsNullOrEmpty(this.txtSearch.Text.Trim()))
                    {
                        this.rtbInfo.Tag = this.txtSearch.Text.Trim();
                    }
                    else {
                        return;
                    }

                }
                IRichFormat richFomat = RichFormatFactory.CreateRichFormat(btnType);
                richFomat.SetFormat(this.rtbInfo);
            }
        }

        private void combFontSize_SelectedIndexChanged(object sender, EventArgs e)
        {
            float fsize = 12.0f;
            if (combFontSize.SelectedIndex > -1) {
                if (float.TryParse(combFontSize.SelectedItem.ToString(), out fsize)) {
                    rtbInfo.Tag = fsize.ToString();
                    IRichFormat richFomat = RichFormatFactory.CreateRichFormat(BTNType.FontSize);
                    richFomat.SetFormat(this.rtbInfo);
                }
                return;
            }
        }
    }
}

示例效果图

设置文本对应的格式,具体如下所示:

图片

源码下载

关于源码下载,可关注公众号,并回复关键字WINRICH即可,如下所示:

图片

以上就是【详解C#之WinForm版利用RichTextBox 制作文本编辑器】的全部内容,关于更多详细内容,可参考官方文档。希望能够一起学习,共同进步。

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

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

相关文章

Spring中@import注解终极揭秘!

技术概念 它能干啥 Import注解在Spring框架中主要用于解决模块化和配置管理方面的技术问题&#xff0c;它可以帮助开发者实现以下几个目标&#xff1a; 模块化配置&#xff1a;在大型项目中&#xff0c;通常需要将配置信息分散到多个配置类中&#xff0c;以便更好地组织和管…

C++面试干货---带你梳理常考的面试题(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 1.struct 和 class 区别 1.默认访问权限&#xff1a;struct中的成员默认为public&#xff0c;而class中的成员默认为priv…

力扣404 左叶子之和 Java版本

文章目录 题目描述解题思路代码 题目描述 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 2…

二手手机管理系统|基于Springboot的二手手机管理系统设计与实现(源码+数据库+文档)

二手手机管理系统目录 目录 基于Springboot的二手手机管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户管理功能的实现界面 2、用户中心管理功能的实现界面 3、新闻信息管理功能的实现界面 4、商品收藏管理功能的实现界面 5、订单管理功能的实现界…

2024年3月6日 十二生肖 今日运势

小运播报&#xff1a;2024年3月6日&#xff0c;星期三&#xff0c;农历正月廿六 &#xff08;甲辰年丁卯月己巳日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;牛、猴、鸡 需要注意&#xff1a;鼠、虎、猪 喜神方位&#xff1a;东北方 财神方位&#xff1a;正…

【pyinstaller打包记录】Windows系统打包exe后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件&#xff08;可执行程序&#xff09;的工具。它能够将 Python 代码和其相关的依赖项&#xff08;包括 Python 解释器、依赖的模块、库文件等&#xff09;打包成一个独立的可执行文件&#xff0c;方便在不同环境中运行…

【Java设计模式】五、建造者模式

文章目录 1、建造者模式2、案例&#xff1a;共享单车的创建3、其他用途 1、建造者模式 某个对象的构建复杂将复杂的对象的创建 和 属性赋值所分离&#xff0c;使得同样的构建过程可以创建不同的表示建造的过程和细节调用者不需要知道&#xff0c;只需要通过构建者去进行操作 …

【SpringBoot3.x教程 01】SpringBoot简介及工程搭建

前言&#xff1a;什么是SpringBoot&#xff1f; SpringBoot是一个开源的Java基础框架&#xff0c;它被设计来简化Spring应用的初始搭建以及开发过程。这个框架利用了“约定优于配置”的理念&#xff0c;提供了一系列大型项目中常用的默认配置&#xff0c;让开发者可以快速启动和…

kafka查看消息两种方式(命令行和软件)+另附发送消息方式

1、命令行方式 ①找到kafka安装文件夹 ②执行命令 #指定offset为指定时间作为消息起始位置 kafka-consumer-groups.sh \ --bootstrap-server 20.2.246.116:9092 \ --group group_1 \ --topic lanxin_qiao \ --reset-offsets \ --to-datetime 2023-07-19T01:00:00.000 \ -exe…

解决Maven项目中的依赖冲突

1. 排查依赖冲突 在IDEA中下载插件 Maven Helper用于排查依赖版本冲突。 打开项目的pom.xml文件&#xff0c;点击下方的【Dependency Analyzer】按钮切换到依赖解析页面。 2. 解决版本依赖 在依赖解析页面进行依赖冲突排查操作&#xff1a; 点击 【Exclude】 后会在爆红处所对…

Java多线程实现发布和订阅

目录 简介 步骤 1: 定义消息类 步骤 2: 创建发布者 步骤 3: 创建订阅者 步骤 4: 实现发布-订阅模型 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡…

Claude 3正式发布,超越GPT-4,一口气读15万单词,OpenAI最强的大对手!

目录 多模态AI大模型Claude 3&#xff08;https://www.anthropic.com/news/claude-3-family&#xff09;Claude 3 的三个版本新增功能&#xff0c;chatgpt没有的使用成本总结 多模态AI大模型Claude 3&#xff08;https://www.anthropic.com/news/claude-3-family&#xff09; …

Stable Diffusion 3报告

报告链接&#xff1a;https://stability.ai/news/stable-diffusion-3-research-paper 文章目录 要点表现架构细节通过重新加权改善整流流量Scaling Rectified Flow Transformer Models灵活的文本编码器RF相关论文 要点 发布研究论文&#xff0c;深入探讨Stable Diffuison 3的…

Sora到底有多强?

北京时间2月16日凌晨&#xff0c;OpenAI发布文本生成视频的AI模型Sora&#xff0c;瞬时刷屏科技圈&#xff0c;成为2024年开年“顶流”。 官方称&#xff0c;Sora只需文本就能自动生成高度逼真和高质量的视频&#xff0c;且时长突破1分钟。这是继文本模型ChatGPT和图片模型Dal…

三整数排序问题的解题逻辑

【题目描述】 输入3个整数&#xff0c;从小到大排序后输出。 【样例输入】 20 7 33 【样例输出】 7 20 33 【解析】 本题解法大概有3种&#xff1a; 1、穷举条件法。 此方法先判断a、b、c大小的所有可能&#xff0c;再根据各种可能性输出不同的排序。 思路是先判断a、…

3Dmax最全快捷键大全,赶紧收藏起来练习起来吧

3Dmax做为一款专业的建模软件&#xff0c;有很多快捷键能帮助我们更好地学习&#xff0c;提升自己的能力。 废话不多说&#xff0c;我们一起来看看。 以上就是3dmax最全快捷键大全&#xff0c;看着容易&#xff0c;但是想要掌握好还需要我们多多练习。 本地max跑图太慢的朋友可…

数据链路层----滑动窗口协议的相关计算

目录 1.窗口大小的相关计算 •停等协议&#xff1a; •后退N帧协议&#xff1a; •选择重传协议&#xff1a; 2.信道利用率相关计算 •停等协议的信道利用率&#xff1a; •连续ARQ&#xff08;后退N帧协议&#xff0c;选择重传协议&#xff09;的信道利用率&#xff1a;…

SAP PP学习笔记04 - BOM2 -通过Serial来做简单的BOM变式配置,副明细,BOM状态,BOM明细状态,项目种类,递归BOM

本章继续讲BOM。 本章讲通过Serial来做简单的BOM变式配置。还讲了BOM的相关概念&#xff1a;副明细&#xff0c;BOM状态&#xff0c;BOM明细状态&#xff0c;项目种类&#xff0c;递归BOM 等。 1&#xff0c;通过Serial&#xff08;序列号&#xff09;来做简单的 VC&#xff0…

软考信息系统项目管理师零基础怎么学习?

软考考信息系统项目管理师&#xff0c;零基础怎么入手高项&#xff1f; 要我说对于没有基础的人群来说零基础考信息系统项目管理师还是有一定的难度的&#xff0c;难就难在需要时间去了解基础&#xff0c;而相对于系统分析师、系统构架设计师、网络规划设计师、系统规划与管理…

C++多态详解

文章目录 多态概念定义及实现构成条件虚函数虚函数的重写override 和 final重载、覆盖、隐藏 抽象类纯虚函数接口继承与实现继承 多态的原理虚函数表原理动态绑定与静态绑定 多继承的虚函数表多继承中的虚函数表 多态 概念 多态是面向对象三大特性中相对复杂的一个&#xff0…