C#和WPF实现图形化编程

C#和WPF实现图形化编程

图形化编程在很多领域都应用很多,比如儿童编程、硬件控制,目前最火的两个引擎肯定应该是scratch和google blocky,很多图形化编程软件都是基于这两个引擎,比如国内编程猫使用了scratch,makecode使用了google blocky。

使用其他引擎必然会收到很大的限制,不如要实现比如局部变量等基本功能时候,使用scratch就没法实现了,而且scratch和blocky都是基于javascript,如果要控制某些硬件,就要做很多javascript和其他硬件的通信模块,不是很方便,所以我们也许要自己写一个图形化编程工具。我工作一直用图形化工具控制硬件,但是老外的软件做的很一般,有天突然想是否自己也能写一个图形化编程工具,就花了点时间,用C#和WPF写了一个图形化工具,代码已经放在github下开源

代码地址 https://github.com/weihuajiang/WPF-Blocky

也在代码中实现了一个代码编辑器,和scratch一样的编辑器
代码编辑器
Scratch编辑器

程序语法树AST的实现

图形化程序也是程序,要显示和运行,我们必须要知道程序语法树(abstract syntax tree)的概念。语法树可以分为表达式Expression、语句Statement和声明Declaration。比如简单的一个语句a+b,就是一个BinaryExpression,而a+b;虽然多了分号,不过就编程了一个Statement语句,这个是个ExpressionStatement,其中的表达式就是BinaryExpression。更多AST的信
息大家可以看esprima解释的很详细。在我们程序中,我们定义了AST基类Node和三个基本的语法树结构Expression、Statement和Decaration(主要就是函数定义),与之对应基本控件也就只有三个控件,Expression控件、Statement控件和Function控件。WPF的数据绑定,让控件编写简化了很多。

程序的运行

程序的运行,简单来说就是各个语法树节点的运行,比如a+5;可以转换成以下结构:

            "type": "ExpressionStatement",
            "expression": {
                "type": "BinaryExpression",
                "operator": "+",
                "left": {
                    "type": "Identifier",
                    "name": "a"
                },
                "right": {
                    "type": "Literal",
                    "value": 5,
                    "raw": "5"
                }
            }

执行顺序是ExpressionStatement->BinaryExpression->left, right,返回left+right,left是Identifier是变量,需要从运行环境获得变量的值,right是Literal是整数5,这样就能获得运行的结果。

程序跳转的实现

break、continue和return,还有异常都会导致程序运行顺序发生跳转,我们通过程序返回值类型来实现程序的跳转。返回值总共有五种类型,分别对应五种可能情况,如果执行过程中出现异常,则应返回Exception,如果正确执行返回Value类型,循环会处理continue和break,函数处理return,如果执行过程中返回非Value,则应该把改返回类型返回,这样就解决了程序跳转的问题。

    public enum CompletionType
    {
        Value,
        Continue,
        Break,
        Return,
        Exception
    }
    public class Completion
    {
        public static Completion Void = new Completion();
        public Node Location { get; internal set; } = null;
        public CompletionType Type { get; internal set; } = CompletionType.Value;
        public object ReturnValue { get; internal set; } = null;

        public bool IsValue
        {
            get
            {
                return Type == CompletionType.Value;
            }
        }
        public bool IsException
        {
            get
            {
                return Type == CompletionType.Exception;
            }
        }
    }

运行环境的实现

我们使用Dictionary来保存运行运行环境的变量值,当前变量就保存在当前的Dictionary中,运行到一个位置,比如需要一个新的运行环境时,就生成一个新的环境,这样在这个环境中定义的变量在parent环境就无法访问,也就实现了局部变量的操作,同时当前环境可以访问前边所有parent环境的数据,也就是访问其他作用域的变量。

    public class ExecutionEnvironment
    {
        ExecutionEnvironment _parent=null;
        Dictionary<string, object> currentVariables = new Dictionary<string, object>();
        public ExecutionEnvironment()
        {
            _parent = null;
        }
        public ExecutionEnvironment(ExecutionEnvironment parent)
        {
            _parent = parent;
        }
        public bool HasValue(string variable)
        {
            if (currentVariables.ContainsKey(variable))
                return true;
            if (_parent != null)
                return _parent.HasValue(variable);
            return false;
        }
        public void RegisterValue(string variable, object value)
        {
            if (currentVariables.ContainsKey(variable))
                throw new Exception(Variable was defined already");
            currentVariables.Add(variable, value);
        }
        public object GetValue(string variable)
        {
            if (currentVariables.ContainsKey(variable))
            {
                return currentVariables[variable];
            }
            if (_parent != null)
                return _parent.GetValue(variable);
            throw new KeyNotFoundException();
        }
        public void SetValue(string variable, object value)
        {
            if (currentVariables.ContainsKey(variable))
            {
                currentVariables[variable] = value;
                return;
            }
            else if (_parent != null)
            {
                _parent.SetValue(variable, value);
                return;
            }
            else
                throw new KeyNotFoundException();
        }
    }

具体实现的例子

我们下边以if语句为例,看看具体如何实现语句的运行,if语句包含三部分,条件判断表达式Test,true时候运行的Consequent语句,false时候运行的Alternate语句,运行时候,我们先执行Test.ExecuteImpl语句,如果为true,则运行Consequent,false时候运行Alternate,不过在Consequent和Alternate运行时候,都产生了一个新的变量作用域,我们需要新建一个运行环境。


    public class IfStatement : Statement
    {
        public IfStatement()
        {
            Consequent = new BlockStatement();
        }
        public Expression Test { get; set; }
        public BlockStatement Consequent {get; set;}
        public BlockStatement Alternate {get; set;}
        protected override Completion ExecuteImpl(ExecutionEnvironment enviroment)
        {
            if (Test == null)
                return Completion.Void;
            var t = Test.Execute(enviroment);
            if (!t.Type.IsValue)
                return t;
            if (t.ReturnValue is bool)
            {
                if ((bool)t.ReturnValue)
                {
                    if (Consequent == null)
                        return Completion.Void;
                    ExecutionEnvironment current = new ExecutionEnvironment(enviroment);
                    return Consequent.Execute(current);
                }
                else
                {
                    if (Alternate == null)
                        return Completion.Void;
                    ExecutionEnvironment current = new ExecutionEnvironment(enviroment);
                    return Alternate.Execute(current);
                }
            }
            else
                return Completion.Exception("Not a boolean value", Test);
        }
    }

结语

githup上开源了编辑器的代码,大家可以下载看看,同时这个编辑器放在了微软商店里,链接是Visual Code Editor,如果想用微软商店直接安装,可以点击下边连接,
ms-windows-store://pdp/?productid=9NG2QVSXT34H
里边除了基本的语法功能,增加了更多类库和多语言等功能,比如python turtle一样的画板、翻译、语音、数学、数据结构等
在这里插入图片描述

  • 15
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
WPF编程宝典》是一本经典的WPFWindows Presentation Foundation)编程指南。WPF是一种用于创建窗口应用程序和用户界面的微软技术,它提供了丰富的图形、动画和交互功能,使开发人员能够创建出现代化的应用程序。 这本书按照从基础到高级的顺序,详细介绍了WPF的各个方面。首先,它解释了WPF的基本概念和架构,包括XAML(可扩展应用程序标记语言)和MVVM(模型-视图-视图模型)模式。它还介绍了如何创建和布局控件、处理事件和命令,并利用数据绑定和样式来实现可扩展的用户界面。 此外,书中还深入讨论了WPF的图形和动画特性。读者将学习如何使用绘图对象、渲染效果和3D图形来创建各种视觉效果。它还介绍了如何使用动画和转换来创建流畅的用户界面过渡和交互效果。 《WPF编程宝典》还包含了一些高级的主题,如使用WCF(Windows Communication Foundation)进行数据通信、使用数据库和Web服务,以及集成其他技术和框架,如Entity Framework和Prism。 这本书以清晰的语言、实用的示例和详细的代码解释,帮助读者理解WPF编程的核心概念和技术,从而能够独立地开发高品质的WPF应用程序。 总的来说,《WPF编程宝典》是一本权威且实用的WPF编程指南,对于想要掌握WPF技术的开发人员来说是一本必读的书籍。无论是初学者还是有经验的开发者,都可以从中获得宝贵的知识和技巧,提升自己在WPF编程领域的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值