自制CANTool_根据DBC自动化生成代码“on signal”(五)

27 篇文章 0 订阅
7 篇文章 0 订阅

自动化生成代码工具界面

在汽车电子开发中,DBC(Database Container)文件对于定义和描述CAN(Controller Area Network)通信协议至关重要。随着项目的迭代和功能的扩展,手动管理和比较多个版本的DBC文件变得愈加复杂且容易出错。为了解决这一问题,本文将详细介绍如何使用自制的DBC读取工具实现拖放导入DBC文件,并根据DBC中的信号特性自动化生成代码。通过结合C# Windows Forms应用程序的TreeView控件、拖放功能和自动代码生成方法,我们将构建一个高效且用户友好的DBC工具。

目录

  1. 工具概述
  2. 用户界面设计
    • 拖放导入DBC文件
    • 双击生成代码
  3. 核心代码解析
    • 构造函数
    • 拖放事件处理
    • 双击生成代码事件处理
    • 自动化生成代码方法
    • 将生成的代码设置到TextBox
  4. 完整代码示例
  5. 总结与展望

工具概述

本工具旨在简化DBC文件的管理和代码生成过程。通过以下关键功能,用户可以轻松导入DBC文件,浏览其中的节点和信号,并根据需求生成相应的代码模板:

  1. 拖放导入DBC文件:用户可以通过拖放方式将.dbc文件导入到TreeView控件中,工具将自动解析并展示文件内容。
  2. 双击生成代码:用户在TreeView中双击特定信号时,工具将自动生成对应的代码模板并显示在TextBox控件中。

用户界面设计

拖放导入DBC文件

为了提升用户体验,TreeView控件被赋予了拖放功能,使用户可以轻松地将.dbc文件拖放到控件上进行导入和解析。以下为实现步骤和相关代码解析。

启用拖放功能

在构造函数中,初始化必要的控件和类,并启用TreeView的拖放功能。

#region 构造函数
public CAPLAutoCodeForm()
{
    InitializeComponent();
    dbcReader = new DBCReader();
    dBCCompareLib = new DBCCompareLib();
    dBC_CAPLAutoCode_DAL = new DBC_CAPLAutoCode_DAL();

    // 启用拖放功能
    treeView_DBC.AllowDrop = true;

    // 绑定拖放事件
    treeView_DBC.DragEnter += treeView_DBC_DragEnter;
    treeView_DBC.DragDrop += treeView_DBC_DragDrop;
}
DBCReader dbcReader;
DBCCompareLib dBCCompareLib;
DBC_CAPLAutoCode_DAL dBC_CAPLAutoCode_DAL;
#endregion

解析:

  • InitializeComponent():初始化窗体上的所有控件,通常由设计器自动生成。
  • 实例化类DBCReader用于读取和解析DBC文件,DBCCompareLib可能用于比较DBC文件差异,DBC_CAPLAutoCode_DAL用于自动生成代码。
  • 启用拖放:设置AllowDrop属性为true,使TreeView控件能够接受拖放操作。
  • 绑定事件:将DragEnterDragDrop事件绑定到相应的处理方法。
处理拖放事件

实现DragEnterDragDrop事件的处理方法,以确保仅接受单个.dbc文件并正确加载。

#region 拖拽获取DBC
private void treeView_DBC_DragEnter(object sender, DragEventArgs e)
{
    // 检查是否是文件拖入
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

        // 仅接受单个文件
        if (files.Length == 1)
        {
            string file = files[0];
            // 检查文件扩展名是否为 .dbc
            if (Path.GetExtension(file).Equals(".dbc", StringComparison.OrdinalIgnoreCase))
            {
                e.Effect = DragDropEffects.Copy;
                return;
            }
        }
    }

    // 不接受其他情况
    e.Effect = DragDropEffects.None;
}

private void treeView_DBC_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

        // 确保仅处理一个文件
        if (files.Length == 1)
        {
            string file = files[0];
            if (Path.GetExtension(file).Equals(".dbc", StringComparison))
            {
                // 获取文件的完整路径
                string fullPath = Path.GetFullPath(file);

                // 在 TreeView 中显示文件名作为根节点
                LoadDbcFile(file);

                // 显示文件路径(可选)
                MessageBox.Show($"已加载 DBC 文件:\n{fullPath}", "文件已导入", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("仅支持拖放 .dbc 文件。", "无效文件", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        else
        {
            MessageBox.Show("请仅拖拽一个 .dbc 文件。", "无效操作", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }
}

/// <summary>
/// 加载 DBC 文件并初始化 TreeView
/// </summary>
private void LoadDbcFile(string filePath)
{
    try
    {
        //读取DBC
        dbcReader.LoadDbc(filePath);
        //初始化List
        List<Model_Nodes_RxTx> model_Nodes_RxTxes_02 = dbcReader.GetModel_Nodes_RxTxes();
        List<Model_Message_Signal> model_Message_Signals_02 = new List<Model_Message_Signal>();
        //初始化窗体
        dBCCompareLib.InitNodes_Child(model_Nodes_RxTxes_02, treeView_DBC);
        dBCCompareLib.InitMessage_Child(dbcReader.dbc, treeView_DBC, ref model_Message_Signals_02);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"加载 DBC 文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
#endregion

解析:

  • DragEnter

    • 检查拖入的数据是否为文件。
    • 验证是否仅有一个文件被拖入,并且文件扩展名为.dbc
    • 如果满足条件,设置拖放效果为Copy,否则拒绝拖放。
  • DragDrop

    • 再次验证拖入的数据是否为文件,并且为单个.dbc文件。
    • 调用LoadDbcFile方法加载并解析DBC文件。
    • 显示加载成功的消息框或相应的警告信息。
  • LoadDbcFile

    • 使用自制的DBCReader类加载并解析DBC文件。
    • 获取节点和消息信号列表。
    • 使用DBCCompareLib将解析后的数据初始化到TreeView控件中。
    • 更新窗体标题以显示已加载的DBC文件路径。

双击生成代码

用户可以通过双击TreeView中的节点(信号)来自动生成对应的代码模板,并显示在TextBox控件中。以下为相关实现和代码解析。

处理双击事件

实现DoubleClick事件的处理方法,以便在用户双击节点时生成并展示代码。

#region 双击生成代码
private void treeView_DBC_DoubleClick(object sender, EventArgs e)
{
    try
    {
        // 获取当前触发事件的 TreeView 控件
        TreeView treeView = sender as TreeView;
        if (treeView == null)
        {
            MessageBox.Show("无法识别 TreeView 控件。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        // 获取选中的节点
        TreeNode selectedNode = treeView.SelectedNode;

        Code01(signalKey);

    }
    catch (Exception ex)
    {
        // 捕获所有异常并向用户显示
        MessageBox.Show($"执行过程中发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void Code01(string signalKey)
{
    if (checkBox_ThreeFrameCode.Checked)
    {
        List<string> codeList = dBC_CAPLAutoCode_DAL.AutoCode_ThreeFrame_01(signalKey);
        bool success = dBC_CAPLAutoCode_DAL.SetCodeText(codeList, ref textBoxCode);
    }
}
#endregion

解析:

  • treeView_DBC_DoubleClick

    • 获取双击事件的TreeView控件和选中的节点。
    • 验证节点是否有效,并提取节点的文本作为信号关键字。
    • 调用Code01方法生成代码。
  • Code01

    • 判断复选框checkBox_ThreeFrameCode是否选中。
    • 如果选中,调用AutoCode_ThreeFrame_01方法根据signalKey生成代码行列表。
    • 调用SetCodeText方法将生成的代码设置到文本框textBoxCode中。
    • 显示成功消息(注释掉,因为SetCodeText内部已经处理失败情况)。

核心代码解析

构造函数

构造函数CAPLAutoCodeForm负责初始化窗体、实例化必要的类以及启用拖放功能。

#region 构造函数
public CAPLAutoCodeForm()
{
    InitializeComponent();
    dbcReader = new DBCReader();
    dBCCompareLib = new DBCCompareLib();
    dBC_CAPLAutoCode_DAL = new DBC_CAPLAutoCode_DAL();

    // 启用拖放功能
    treeView_DBC.AllowDrop = true;
}
DBCReader dbcReader;
DBCCompareLib dBCCompareLib;
DBC_CAPLAutoCode_DAL dBC_CAPLAutoCode_DAL;
#endregion

关键点:

  • 实例化类DBCReader用于解析DBC文件,DBCCompareLib可能处理文件比较相关功能,DBC_CAPLAutoCode_DAL负责代码生成和文本设置。
  • 启用拖放:设置AllowDroptrue,使TreeView控件支持拖放操作。

拖放事件处理

拖放功能的核心在于正确处理拖入的数据并加载DBC文件。

treeView_DBC_DragEnter

判断拖入的数据是否为单个.dbc文件,并设置拖放效果。

private void treeView_DBC_DragEnter(object sender, DragEventArgs e)
{
    // 检查是否是文件拖入
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

        // 仅接受单个文件
        if (files.Length == 1)
        {
            string file = files[0];
            // 检查文件扩展名是否为 .dbc
            if (Path.GetExtension(file).Equals(".dbc", StringComparison.OrdinalIgnoreCase))
            {
                e.Effect = DragDropEffects.Copy;
                return;
            }
        }
    }

    // 不接受其他情况
    e.Effect = DragDropEffects.None;
}
treeView_DBC_DragDrop

在验证通过后,调用LoadDbcFile方法加载并展示DBC文件内容。

private void treeView_DBC_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

        // 确保仅处理一个文件
        if (files.Length == 1)
        {
            string file = files[0];
            if (Path.GetExtension(file).Equals(".dbc", StringComparison))
            {
                // 获取文件的完整路径
                string fullPath = Path.GetFullPath(file);

                // 在 TreeView 中显示文件名作为根节点
                //treeView1.Nodes.Clear();
                LoadDbcFile(file);

                // 显示文件路径(可选)
                MessageBox.Show($"已加载 DBC 文件:\n{fullPath}", "文件已导入", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("仅支持拖放 .dbc 文件。", "无效文件", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        else
        {
            MessageBox.Show("请仅拖拽一个 .dbc 文件。", "无效操作", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }
}
LoadDbcFile

加载DBC文件,解析内容并初始化TreeView控件。

/// <summary>
/// 加载 DBC 文件并初始化 TreeView
/// </summary>
private void LoadDbcFile(string filePath)
{
    try
    {
        //读取DBC
        dbcReader.LoadDbc(filePath);
        //初始化List
        List<Model_Nodes_RxTx> model_Nodes_RxTxes_02 = dbcReader.GetModel_Nodes_RxTxes();
        List<Model_Message_Signal> model_Message_Signals_02 = new List<Model_Message_Signal>();
        //初始化窗体
        dBCCompareLib.InitNodes_Child(model_Nodes_RxTxes_02, treeView_DBC);
        dBCCompareLib.InitMessage_Child(dbcReader.dbc, treeView_DBC, ref model_Message_Signals_02);
        //窗体赋值
        this.Text = "DBC_CAPLAutoCode_Form " + filePath;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"加载 DBC 文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

关键点:

  • 读取DBC文件:使用DBCReader类加载并解析DBC文件。
  • 初始化列表:获取节点和消息信号列表,用于初始化TreeView。
  • 初始化TreeView:通过DBCCompareLib类将解析后的数据展示在TreeView控件中。
  • 更新窗体标题:显示已加载的DBC文件路径,便于用户识别。

双击生成代码事件处理

用户双击TreeView中的节点时,将触发代码生成和展示。

#region 双击生成代码
private void treeView_DBC_DoubleClick(object sender, EventArgs e)
{
    try
    {
        // 获取当前触发事件的 TreeView 控件
        TreeView treeView = sender as TreeView;
        if (treeView == null)
        {
            MessageBox.Show("无法识别 TreeView 控件。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        // 获取选中的节点
        TreeNode selectedNode = treeView.SelectedNode;

        Code01(signalKey);

    }
    catch (Exception ex)
    {
        // 捕获所有异常并向用户显示
        MessageBox.Show($"执行过程中发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void Code01(string signalKey)
{
    if (checkBox_ThreeFrameCode.Checked)
    {
        // 生成代码
        List<string> codeList = dBC_CAPLAutoCode_DAL.AutoCode_ThreeFrame_01(signalKey);

        // 设置代码到 TextBox
        bool success = dBC_CAPLAutoCode_DAL.SetCodeText(codeList, ref textBoxCode);

        //if (success)
        //{
        //    MessageBox.Show("代码已成功生成并设置到文本框。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
        //}
        // SetCodeText 方法内部已经处理了失败的情况
    }
}
#endregion

解析:

  • 获取信号关键字:从选中的节点获取信号名称,用于代码生成。
  • 复选框判断:只有当checkBox_ThreeFrameCode被勾选时,才执行代码生成逻辑。
  • 生成并设置代码
    • 调用AutoCode_ThreeFrame_01方法生成代码行列表。
    • 调用SetCodeText方法将生成的代码设置到textBoxCode中。
    • 成功与否的提示信息由SetCodeText方法内部处理,因此不在此处重复。

自动化生成代码方法

AutoCode_ThreeFrame_01方法根据提供的信号关键字生成特定的代码模板。

public List<string> AutoCode_ThreeFrame_01(string signal_Key)
{
    return codeLines;
}

解析:

  • 使用字符串插值将signal_Key动态插入到代码模板中。
  • 生成的代码包括信号更新触发器、计数逻辑以及条件判断,确保在三次满足条件后执行特定操作。

将生成的代码设置到TextBox

SetCodeText方法将生成的代码行列表拼接成一个完整的字符串,并设置到TextBox控件中。

public bool SetCodeText(List<string> code, ref TextBox textBox)
{
        // 将代码行拼接成一个字符串,使用适当的换行符
        string codeText = string.Join(Environment.NewLine, code);

        // 设置 TextBox 的文本
        textBox.Text = codeText;

        return true;
}

解析:

  • 参数验证:确保传入的代码列表和TextBox控件不为null
  • 代码拼接:使用string.JoinList<string>中的代码行合并为一个完整的字符串,行与行之间使用系统换行符。
  • 设置TextBox内容:将拼接后的代码字符串赋值给TextBox的Text属性。
  • 异常处理:在发生任何异常时,通过消息框向用户显示错误信息,并返回false表示失败。

关键点:

  • 双击事件绑定:在构造函数中将DoubleClick事件绑定到treeView_DBC_DoubleClick方法。
  • 初始化TreeView:可选方法InitializeTreeView用于添加初始节点,方便测试。
  • Error Handling:在所有关键操作中均包含异常处理,确保用户在操作失败时能够得到明确的反馈。
  • DAL类DBC_CAPLAutoCode_DAL类负责编写具体的代码生成逻辑和设置TextBox文本的方法,保持代码模块化和职责分离。

总结与展望

本文详细介绍了如何使用自制的DBC读取工具,在C# Windows Forms应用程序中实现拖放导入DBC文件,并根据DBC中的信号特性自动生成代码。通过结合TreeView控件的拖放和双击事件处理,用户可以高效地管理DBC文件,并快速生成所需的代码模板。

关键成果:

  • 拖放导入功能:允许用户通过拖放方式轻松导入.dbc文件,自动解析并展示文件内容。
  • 双击生成代码:用户通过双击TreeView中的信号节点,可以自动生成对应的代码模板并显示在TextBox中。
  • 模块化设计:通过分离数据访问层(DAL)和逻辑处理层,保持代码的清晰和可维护性。
  • 用户友好的界面:通过直观的拖放和双击操作,提升了用户体验,减少了手动操作的复杂性。

未来展望:

  1. 代码高亮和格式化:可以将TextBox替换为RichTextBox或其他支持代码高亮的控件,提升生成代码的可读性。
  2. 多种代码模板支持:扩展DBC_CAPLAutoCode_DAL类,支持多种代码模板和生成规则,以适应不同的项目需求。
  3. 添加代码校验:在生成代码后,增加语法校验和测试,确保生成的代码符合预期的语法和逻辑。
  4. 集成版本控制:结合Git等版本控制系统,管理DBC文件的不同版本和代码生成记录,提升团队协作效率。
  5. 用户自定义模板:允许用户自定义代码模板和生成规则,增强工具的灵活性和适用性。

通过持续优化和扩展,本工具能够更好地满足汽车电子开发中对DBC文件管理和代码生成的需求,提高开发效率,确保系统通信的可靠性和一致性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

99乘法口诀万物皆可变

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值