WPF程序中导入、导出、运行Lua脚本

1、NLua下载安装

  手动离线下载NLua

  KeraLua.dll、NLua.dll文件添加到程序引用

  lua54.dll添加到程序的输出文件夹中

2、主要程序源代码

  代码处建议将最后运行效果图给到豆包、千问来实现效果杠杠的

        <DockPanel>
            <!-- 1. 顶部工具栏 -->
            <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Background="#F0F0F0" Margin="20">
                <Button Content="📂 导入脚本" Command="{Binding OpenCommand}" 
                    Margin="0,0,10,0" Padding="10,5" />

                <Button Content="💾 导出脚本" Command="{Binding SaveCommand}" 
                    Padding="10,5" />

                <!-- 运行脚本按钮 (新添加) -->
                <Button Content="▶ 运行脚本" Command="{Binding RunScriptCommand}" Margin="10,0"
                        Background="LightGreen" FontWeight="Bold" Padding="10,5"/>
                <!-- 状态显示区域 -->
                <TextBlock Text="{Binding ExecutionStatus}" 
                   Margin="10,10,0,0" 
                   Foreground="DarkBlue" 
                   FontWeight="Bold"
                   TextWrapping="Wrap"/>
            </StackPanel>

            <!-- 2. 脚本编辑区域 -->
                <TextBox Text="{Binding ScriptContent, UpdateSourceTrigger=PropertyChanged}"
         AcceptsReturn="True"
         VerticalScrollBarVisibility="Auto"
         HorizontalScrollBarVisibility="Auto"
         TextWrapping="NoWrap"
         FontFamily="Consolas" 
         FontSize="14"
         Padding="10"
         Background="#1E1E1E" 
         Foreground="White"/>
</DockPanel>
   

MainViewModel.cs文件

    public class MainViewModel : INotifyPropertyChanged
    {
        private string _scriptContent;
        private string _currentFilePath;

        // 1. 用于绑定 TextBox 的文本内容
        public string ScriptContent
        {
            get => _scriptContent;
            set
            {
                _scriptContent = value;
                OnPropertyChanged();
            }
        }

        private string _executionStatus;
        public string ExecutionStatus
        {
            get => _executionStatus;
            set
            {
                _executionStatus = value;
                OnPropertyChanged(); // 通知界面更新
            }
        }

        // 2. 打开文件命令
        public ICommand OpenCommand { get; set; }
        // 3. 保存文件命令
        public ICommand SaveCommand { get; set; }

        // 4. 运行脚本命令
        private ICommand _runScriptCommand;
    public ICommand RunScriptCommand
    {
        get
        {
            if (_runScriptCommand == null)
            {
                _runScriptCommand = new RelayCommand(param => this.ExecuteLua());
            }
            return _runScriptCommand;
        }
    }

    // 执行 Lua 的具体逻辑
    private void ExecuteLua()
    {
        try
        {
            // 方式 A:直接使用 NLua 的 Lua 类
            using (Lua lua = new Lua())
            {
                object[] results = lua.DoString(ScriptContent);

                // 2. 判断是否成功获取结果
                if (results != null && results.Length > 0)
                {
                    // 3. 将结果转换为 C# 数字
                    // Lua 的数字默认映射为 double
                    double sum = Convert.ToDouble(results[0]);

                                  ExecutionStatus = $"✅ 计算成功!结果: {sum}";
            }
            else
            {
                ExecutionStatus = "⚠️ 脚本未返回任何值";
            }
        }

        // 方式 B:如果你使用了之前提到的 LuaManager 单例
        // LuaManager.Instance.LuaState.DoString(ScriptContent);
    }
    catch (LuaException ex)
    {
        // 捕获 Lua 语法错误或运行时错误
        ExecutionStatus = $"❌ 脚本错误: {ex.Message}";
    }
    catch (Exception ex)
    {
        // 捕获其他 .NET 错误
        ExecutionStatus = $"❌ 脚本错误: {ex.Message}";
    }
}

        public MainViewModel()
        {
            // 初始化命令
            OpenCommand = new RelayCommand(OpenFile);
            SaveCommand = new RelayCommand(SaveFile);

            // 默认内容
            ScriptContent = "-- 在此输入 Lua 脚本\nprint('Hello WPF')";
        }

        // --- 逻辑实现 ---

        private void OpenFile(object parameter)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Lua 脚本文件 (*.lua)|*.lua|所有文件 (*.*)|*.*";
            openFileDialog.Title = "导入 Lua 脚本";

            if (openFileDialog.ShowDialog() == true)
            {
                try
                {
                    // 读取文件内容
                    ScriptContent = File.ReadAllText(openFileDialog.FileName);
                    _currentFilePath = openFileDialog.FileName;
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show("读取文件失败: " + ex.Message);
        }
    }
}

private void SaveFile(object parameter)
{
    // 如果是新文件或原文件不存在,则弹出保存对话框
    if (string.IsNullOrEmpty(_currentFilePath))
    {
        SaveFileDialog saveFileDialog = new SaveFileDialog();
        saveFileDialog.Filter = "Lua 脚本文件 (*.lua)|*.lua|所有文件 (*.*)|*.*";
        saveFileDialog.Title = "导出 Lua 脚本";

        if (saveFileDialog.ShowDialog() == true)
        {
            _currentFilePath = saveFileDialog.FileName;
        }
        else
        {
            return; // 用户取消了保存
        }
    }

    try
    {
        // 写入文件内容
        File.WriteAllText(_currentFilePath, ScriptContent);
        System.Windows.MessageBox.Show("脚本保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
    }
    catch (Exception ex)
    {
        System.Windows.MessageBox.Show("保存文件失败: " + ex.Message);
    }
    }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
        public void Execute(object parameter) => _execute(parameter);
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
    }

 

 

3、运算后效果

image

 

posted @ 2026-04-15 14:50  echo-efun  阅读(7)  评论(0)    收藏  举报