在我认真研究内部世界和 VB6 设备之前,我和许多人一样,脑子里可能有以下想法:VB 是主要产品,而 VBA 是副产品,是削减功能方面的主要产品,并附加到 Excel、Word 等 Office 应用程序。但经常发生的是,外行人对事物结构的看法,建立在试图预测这种结构的基础上,可能与真实结构截然不同。在这种情况下,这正是我们的情况:事实上,一切都完全相反,不是 VBA 是创建 VB 的副产品,而是 VB 是 VBA 出现的副产品.
本文将阐明 Visual Basic 由什么两大部分组成,其思想背景是什么,以及它们各自出现的背后是什么样的人。
正如您可能从上面猜到的那样,有两个重要组成部分。这些是Ruby和EB。关于这一切也许最恰当的说法是: Visual Basic 是Ruby和EB “联姻”的结果——这两种技术彼此独立出现,但又非常适合彼此。
Ruby在我们继续之前要注意的一个非常重要的注意事项:在这里和下面,“Ruby”这个词与Ruby
编程语言和框架无关。轨道上的红宝石。毕竟“红宝石”这个词简单翻译成“红宝石”。
(图:Alan Couper)
如果您曾经搜索过有关 Visual Basic 是如何诞生的信息,您可能会偶然发现维基百科或其他地方有这样的词:
1991 年 5 月 - 用于 Microsoft Windows 的 Visual Basic 1.0 发布。以QBasic语法作为语言的基础,而使语言大受欢迎的创新是语言与图形界面之间的通信原理。该原则由 Alan Cooper开发并在原型 Tripod(也称为 Ruby)中实现。第一个 Visual Basic 是一个解释器。
从一篇关于Alan Cooper本人的文章中,您可以了解到他尤其被称为“Visual Basic 之父”。这篇文章的英文版提供了更多信息。
事实上,Alan Cooper 并没有在微软工作,也没有加入 VB 开发团队——他的功绩在别处。Alan Cooper 提出了轻松创建视觉皮肤的概念,并与同事一起创建了一个用于构建视觉皮肤的工具。提醒一下,我们说的是80年代,那个时候图形界面的操作系统刚刚普及,主流是DOS等文字界面的操作系统。
Alan Cooper 的团队做的产品叫做 Ruby,最有趣的是它不是程序员的工具。- 它是为没有特殊技能的普通用户提供的工具,根据 Cooper 的想法,这使他们能够快速关闭视觉外壳,从而促进某种工作。一种面向广泛人群的视觉界面设计师。哦,这是浪漫主义者的时代,他们相信给人们一台电脑是值得的——每个人都会学习并开始亲手编写程序,使电脑完全按照主人的需要去做。Ruby 既不是一种编程语言,也不是现代意义上的集成开发环境 (IDE)。
据 Cooper 说,当他看到 Windows 1.0 时,他意识到这个平台有着美好的未来。他对两件事感到惊喜:图形界面和 DLL 的概念,它允许您创建动态配置的可扩展系统,但与此同时,当时的 Windows 外壳(Explorer 和现代意义上的桌面还没有存在)在他看来简直太可怕了。然后他决定为 Windows 编写他理想的 shell。与他的客户交谈并试图找出理想的外壳应该是什么时,艾伦库珀意识到完美的外壳并不存在。而且你需要给用户一个工具,允许他们每个人设计自己的 shell,根据他们的需要和他们的任务量身定制,而不是试图向他们推销一些理想的 shell,同时试图向他们解释它的理想是什么。
后来,Alan Cooper 向 Bill Gates 展示了他的发展。盖茨喜欢这样的概念,即用户可以绘制可视控件,将它们放置在工作区的任何位置、拖放、调整大小,最重要的是,将某些操作与控件相关联,他非常喜欢,因此决定购买 Ruby。从此,微软成为了Ruby的主人,决定了产品未来的命运。
微软决定改变 Ruby 的本质:将易于构建可视化界面的概念(“在必要时绘制一个按钮并快速附加一些动作”)从一个用于创建具有目标的可视化外壳(在现有程序之上)的工具由普通用户组成的受众,将其转变为创建具有可视化界面的新程序的工具,其目标受众将只是程序员。提醒一下,最初 Ruby 除了可视化设计原则外,没有任何编程语言(只有一个简单的命令系统,由插件 DLL 扩展的一组命令,以及一组控件调色板(Cooper 称它们为“gizmo”,翻译成俄语为“thingy”,这个术语也保留在 VB6 中),由于第三方 DLL,它也得到了扩展),并且有必要决定哪种语言将构成新工具的基础。但是微软已经有了QBASIC,你可以猜到比尔·盖茨在决定购买像Ruby这样有前途的资产时,脑子里萌生了什么样的计划。
在历史的这一点上,构建可视化界面的概念和机制,完全没有背后的任何编程语言,必须满足一种编程语言和提供其执行的机制,完全没有可视化组件。
EB
您是否看过 VB 运行时导出了多少种不同的未记录函数?
您肯定听说过EbExecuteLine函数,它允许您解释和执行任意代码行(尽管仅在 IDE 下工作时)。您有没有想过所有这些函数名称中的“Eb”前缀是什么意思?它是如何解密的?
现在我们来处理这个。
我不确定这两种可能的解密版本中哪一个更正确,但显然,这两个版本都与事实相差不远。让我们从第一个版本开始,然后转向臭名昭著的Joel Spolsky的一篇文章。
这篇文章叫做“ My First BillG Review ”(“我的第一张支票由 Bill G.”,有俄语翻译)。
简单复述一下历史:
- 1991 年夏天,乔尔在 Microsoft 的 Excel 开发部门找到了一份工作。当时 Excel 的实际问题之一是 Excel 有自己糟糕的宏编程语言,其中没有全局变量和局部变量,没有过程,有 goto,但没有标签。该语言没有自己的名字,有条件地称为“Excel 宏”。
乔尔的任务就是解决这个问题。有人认为问题的解决方案应该以某种方式与 Basic 语言联系起来。在另一个部门(在 Microsoft 内部)已经有一个运行时间来创建一个代号为“Silver”的面向对象的 BASIC。Silver 团队经理只看到了他的技术的一个用途——Excel。Joel 说服了 BASIC 团队的人,Excel 团队需要类似BASIC for Excel 的东西。. 与此同时,他设法坚持认为该语言应添加 4 个特性:- 添加可以存储任何其他类型的值的 Variant 变量,否则无法将 Excel 表格单元格的值存储在变量中(至少不诉诸Select Case)。
- 添加后期绑定(通过 IDispatch),因为原始的 Silver 架构需要对类型系统有深入的了解,而 Excel 宏编写者不想了解这一点。
- 添加从csh借用的For Each构造。
- 添加一个With ... End With构造,从 Pascal 借来的。
之后,Joel 坐下来为未来的语言Excel Basic写了一份规范,大约有 500 页,然后发给 Bill Gates 审查/验证。文章的其余部分描述了随后与 B. Gates 的会面,会上他根据 Gates 在阅读规范时留下的边注向 Joel 提问。
文章的最后一部分说,随着时间的推移,情况有了很大的进步,Excel Basic被称为Visual Basic for Applications ,盖茨曾经记得在Excel团队中聘请那个聪明的经理是多么困难,他做了这一切。
因此,正如您从文章的文本中看到的那样,在某些时候需要用更高级的东西替换 Excel 中糟糕的宏语言,这导致了一个事实,即押注于类似基本的语言,并基于开发在另一个用于创建面向对象的基本类语言的部门, )EB(缩写为Excel Basic——一种面向对象的通用语言,适用于几乎任何东西的自动化,因此在适用性方面很快超越了纯 Excel。由于该语言不仅允许为 Excel 编写宏/扩展/自动化,而且还允许为任何东西编写宏/扩展/自动化,因此该技术不仅开始用于 Word / Access - Microsoft 设法将其出售给 AutoCAD 和 SolidWorkds的创建者、Corel 绘图、ArcGIS。范围如此广泛的技术不能再称为Excel Basic而改名为Visual Basic for Applications是可以理解的,尤其是当你考虑到除了 Office 中包含的程序和第三方程序之外,这项技术已经成为不可或缺的一部分简称Visual Basic的一部分。与此同时,缩写“EB”扎根于许多与技术相关的功能和结构的名称中,并一直沿用至今。
第二版译名EB不是 Excel Basic,而是 Embedded Basic。根据 Scott Ferguson(他开玩笑地称自己为“Visual Basic 之母”)的说法,在 80 年代和 90 年代之交,微软正在开发 Omega 数据库,该项目最终被放弃。Omega DBMS 包括 Embedded Basic (EB) 引擎。开发发生在一个名为“业务编程语言部”的部门,该部门也参与了 QuickBASIC 的开发。但是“商业编程语言”部门的主要资源集中在创建一种新的、面向对象的、为 Windows 量身定制的类 BASIC 编程语言上,它被称为Silver(我们已经在 Joel Spolsky 的故事中看到了这个名字和这个产品)。比尔盖茨在某个时候向“商业编程语言”部门发送了一个请求,询问是否可以以某种方式交叉使用 Ruby 和 EB。John Fine(当时的项目经理)受命与 Scott Ferguson 一起回答这个请求。
创建了一个团队,将他们的 EB 与他们刚从侧面购买的 Ruby 进行了非常困难的整合:(
照片中的两个人,他们的脸被涂上了,是摄影师从侧面邀请来改善构图的框架,与VB的发展无关)新产品,由EB和Ruby
合并而成,被命名为Thunder(此名称的痕迹在许多内部函数的名称(例如ThunderMsgLoop)或窗口类的名称(例如ThunderRT6FormDC)中一直保留到 VB6)。Scott Ferguson 回忆说,早在 1989 年 1 月,John Fine 写道(可能是为了他的上司,可能是盖茨本人)提出了关于创建一种名为“Visual BASIC”的编程语言的提议。这是在 Ruby 被引入 Microsoft 之前很久,也就是在Thunder产品发布之前很久。这个名字与许多其他被认为是产品正式名称的候选名称一起从遗忘中复活。事实上,很多人不喜欢它。大多数人喜欢名称“Thunder”(翻译为“Thunder”)以及当时的口号“The Power to Crack Windows ”(翻译为“Power to open Windows”或者“Power to make Windows tremble”)。无论哪种方式, EB代表Excel Basic还是Embedded Basic
都无关紧要。从 Joel 关于他对引入EB的 4项重要创新的贡献到今天仍然保留在 VB / VBA 中的话来看,他的历史眼光和对 VB 和 VBA 形成的发展的贡献也应该被考虑在内帐户。
显然,有最初为 Omega DBMS 创建的 Silver 技术和 EB 引擎。
EB 本身,并非没有 Joel 的参与,成为 Excel 的一部分,并成为现在称为 VBA 的东西。
EB 与受 Silver 影响的 Cooper 的 Ruby 合并,成为现在众所周知的 VB。
包含 EB 的 Omega 项目据说转世为 Access/MS Jet,其中 EB 仍然是重要的组成部分。
State of the Art到产品的最新版本 - 到 VB6, Ruby和EB
的分界线没有溶解,这两种成分都没有融合到无法区分的程度。它们之间仍然有明确的界限,每个组件都做自己的事情,可以说有自己的职责范围和要解决的任务范围。
即使在源代码级别也保留了分离(有关编译 VB 的源的信息可以从带有调试符号的文件中获得)。从源码包的角度来看,VB6 由两个文件夹组成:ruby/和vbadev/
第一个包含所有Ruby源,第二个包含所有EB源(从 Joel 的文章中我们知道,它被重命名为VBA在某些时候)。对于 Ruby 中的许多函数和变量,我们会将前缀视为前缀Rby 中,我们会看到许多函数、变量和结构体的前缀Eb EB。EB - 包括什么,它做什么以及它负责什么:
- EB / VBA作为一个整体被安排为一种可以与任何东西连接的技术 - 任何外部应用程序(术语“主机”/“主机”用于此类应用程序)。EB/VBA依附于主机,允许您编写可以与主机交互的代码,管理主机对象模型,最终使您可以随心所欲地扩展主机的操作逻辑,并为任何使用 EB 的主机应用程序编写自动化。附上. /VBA。
- EB/VBA不依赖于特定主机 - 该主机依赖于EB/VBA,并且EB/VBA可以“拧”到任何东西上。
EB + Excel 为我们提供了 Excel 中的 VBA。
EB + Word 为我们提供了 Word 中的 VBA。
EB + AutoCAD 为我们提供了 AutoCAD 中的 VBA。
EB + Ruby 给了我们所谓的“独立VB”(standalone VB,VB1-VB6)。
也就是说,Ruby只是EB主机的一个特例。Ruby不能没有EB,但EB可以与任何其他主机一起使用。 - 具有语法突出显示、自动完成和 IntelliSense 的代码编辑器是EB/VBA的一部分。我们说的是文本域本身,代码写在里面,不包括工具栏、工具栏、菜单。正是由于这个原因,代码编辑器在 VBA 和 VB 中是相同的。
- 执行 P 代码的虚拟机是EB/VBA的一部分。
- 用于解析 VB 代码并将其转换为 P 代码的即时编译机制是EB/VBA的一部分。因此,该语言的语法也是EB的一部分,与Ruby无关,因此在EB附加的所有主机中,该语言将具有相同的语法规则和特性(例如, Not Not bug Arr会到处出现)。
- 语言支持的基本类型集和运算符集(And、Xor、Like、&)是EB/VBA的一部分,因此无论EB/VBA附加到哪个宿主,它在任何地方都是相同的。如果您是主机开发人员并且您可以完全控制主机源,但 EB 对您来说是一个黑盒子,那么您无法在代码中获得对新运算符的支持(例如,移位运算符,这不是本地的)。
- 错误处理的概念是 EB/VBA 的一部分,所以无论EB/VBA哪里搞砸了,到处都是一样的。
- 万物皆分项目,项目由模块(更准确地说,项目项)组成的概念来自EB/VBA。同时,EB 对任何表单和 UserControl 都一无所知——从 EB 的角度来看,只有两种类型的模块(普通和对象)。宿主可以为对象模块设置自己的亚种。在 VB6 中,这些是类、窗体、用户控件。在 Excel 中,这些是类、用户表单、工作表(工作表)和书籍(工作簿)。其他一些主机可能有自己的模块亚种。但是项目和模块的一般概念将存在于任何主机中。
- 包含对第三方类型库的引用的概念是EB/VBA引擎的一个特性,因此存在于 VB 和所有 VBA 使用中。连接到EB内项目的 TLB-shku 的链接名称为EBREF,并由同名结构描述。
- 所有被大多数人称为“运行时函数”的函数,例如MsgBox、InputBox、Rnd、Beep、CreateObject、DateDiff、RGB、StrReverse、MkDir都是EB/VBA的一部分,因此所有这些函数都必然存在,不仅在纯 VB 中,但也在 VBA 中:在 Excel、Word、AutoCAD 和任何其他主机中。
- Collection和ErrObject类是EB/VBA的一部分,同样可以在纯VB、Microsoft Office 应用程序和其他主机中找到。
- 诸如表达式服务器和 VBA 事件监视系统之类未记录且因此鲜为人知的机制也是EB的一部分。
- 在程序执行期间以某种方式与用户界面和一些视觉表现形式相关的所有内容 - 原则上不属于EB的一部分。例如,作为EB (VBA) 的一部分并显示带有消息的对话框的 MsgBox 函数不会直接显示该框 - EB不知道消息应该如何显示以及可以通过什么方式显示。相反,EB调用它的主机并从主机调用一个特殊的回调函数,该函数负责显示消息的视觉部分。EB之间并且宿主有这样一个交互接口作为宿主提供的回调的指针数组。当主机初始化EB时,它调用EB函数EbInitHost并将此数组传递给它。EB记住一个指向这个数组的指针,当它需要显示一条消息时,它会取数组的相应元素(这个地址对应回调函数)并调用所需的函数。并且是主机代码决定了消息将如何显示,是否是一个窗口,它是一个什么样的窗口,它会有什么样的设计。在这方面, EB变得如此多才多艺,以至于EB的宿主例如,可以提供使用 DirectX 的全屏游戏。并且在这个游戏中,调用MsgBox不会出现通常的windows对话框,会破坏全屏模式——游戏主机实现的显示消息的回调函数会以游戏风格显示消息,通过渲染显示使用 DirectX,就像所有其他游戏 UI 一样。
Ruby - 包括什么,它做什么以及它负责什么:
- 首先,必须要说的是,Ruby不知道(也不关心)管理基础设施的代码背后是什么语言——Ruby 提供的语言。在 VB 的情况下,EB与Ruby一起使用,但纯粹是假设,可能有裸露的 C / C ++ 代码,或者某种脚本引擎,或者像Scratch这样的可视化编程系统,其中没有写代码,而是以流程图和图表的形式画出来的。顺便说一句,根据 Alan Cooper 最初的想法,这正是 Ruby 的工作方式:当用户绘制一对小发明时,比如一个按钮和一个列表框,然后为了使列表框在按钮时消失被点击时,用户在第二个小工具的“隐藏”方法之前直接绘制了一个来自第一个小工具的“点击”事件的箭头。所以...
- VB内置的所有控件(controls),如CommandButton、ListBox、Drive、Circle、PictureBox、ScrollBar都是Ruby的一部分。
- App 、Clipboard 、 Forms集合、Printers 、 Screen对象、 Load和Unload方法、 LoadPicture / SavePicture方法都是Ruby的一部分。因此,在 Excel 中打开 VBA 后,您将无法在那里编写App.Path或Screen.ActiveForm - 根本不会有任何 App 和 Screen,因为这是Ruby的一部分,而不是EB。
- Windows 所基于的表单引擎是Ruby。
- 所有窗口消息的处理,过滤,转发和把窗口消息变成控件中的事件都是Ruby。
- 与开发环境 (IDE) 以及如何在设计时绘制表单有关的大部分内容都是Ruby。例如,项目树、组件面板、属性面板、项目属性对话框、环境对话框、插件支持机制——所有这些都是Ruby。
- 运行独立 EXE 文件所需的所有供应机制,以及运行编译为形成 DLL/OCX 文件的项目和 ActiveX EXE 项目,都是Ruby . 例如,任何 ActiveX DLL 都必须有一个DllGetClassObject函数,该函数返回所请求类的类工厂。DllGetClassObject和类工厂都在作为Ruby一部分的源文件中实现。
- 与 OLE、DDE 和数据绑定机制相关的一切(这是当表单上的控件(例如,文本字段)绑定到记录集的字段并在遍历记录集中的行并更改值时更改自身在控件中导致 DB 中的值发生变化 - 所有这些都无需从 VB 程序员一侧编写额外的内容,而只需在表单控件和数据库之间建立连接) - 所有这些都是红宝石。
这就是分离的原理。假设您手头有完整的 VB 源代码,并且需要修复按钮行为中的某些内容或向表单添加新属性,请转到 Ruby 源代码。如果您想修复内置 Collection 类中的某些内容,或者想在 VB 中添加新的运算符,请转到EB资源。
Ruby 和 EB 的划分不仅在源代码级别可见。如果你去 Project→References,我们会看到有几个连接的类型库不能被禁用。其中一个匹配EB带来的一切,另外两个对应Ruby带来的一切:
EB/VBA有自己的类型库,你可以在其中找到所有内置的运行时函数,以及两个单独的类——Collection 和ErrObject :如果
我们在 Excel 中打开 Visual Basic,我们将在 References 和 Object 中看到相同的类型库浏览器 - 所有功能都将到位。
Ruby有自己的类型库,您可以在其中找到所有内置控件和对象,例如App、Printers、Screen:
VB6.EXE、VBA6.DLL 和 MSVBVM60.DLL 的剖析
众所周知,编译的 VB 项目将不可避免地依赖于MSVBVM60。动态链接库- 一旦调用此库(运行时和 VB 虚拟机)。虽然项目以源码的形式存在,在IDE下调试,但其工作是由IDE本身提供的,主要由两个二进制文件组成:
- VB6.EXE
- VBA6.DLL(VB6.EXE 依赖它)
一个事实可能会让某些人感到惊讶: msvbvm60.dll的内部是VB6.EXE内部的一半, VBA6.DLL内部的一半。
其实VB6.EXE是编译Ruby源码的结果,VBA6.DLL是编译EB源码的结果。MSVBVM60.DLL
运行时大约一半是Ruby一半是EB。两组来源(ruby/和vbadev/
), 代表该产品的两个主要组件,由于使用不同的密钥和选项进行编译和链接,它们产生了 3 个可执行文件。
也就是说,没有“MSVBVM60.DLL 源代码”和“VB IDE 源代码”之类的东西——它们都是从相同的源代码编译和构建的!但是使用不同的编译选项和开关,使用不同的条件编译标志。
构建IDE(VB6.EXE + VBA6.DLL)的过程如下:
构建MSVBVM60.DLL运行时库的过程几乎相同:相同的源文件被编译(编译开关略有不同)为目标文件(obj),然后所有这一切都链接到一个最终的 DLL 文件中:
正如人类遗传密码与黑猩猩遗传密码的 98% 相同一样, msvbvm60.dll中的绝大多数二进制代码重复vb6.exe或vba6.dll中的代码。几乎任何属于msvbvm60.dll一部分的过程都是Ruby的一部分或EB的一部分,因此可以发现它们作为vb6.exe的一部分或作为vba6.dll的一部分未更改或稍作修改。
反之则不然:vb6.exe (1.80 Mb) 和vba6.dll (1.61 Mb) 代码的总大小大于msvbvm60.dll (1.32 Mb) 的大小。
显然,Ruby包含实现例如表单编辑器或项目属性对话框的代码 - 所有这些都属于vb6.exe,但不属于msvbvm60.dll(那里不需要)。
显然,EB包括实现解析、分析、将 VB 代码编译为 P 代码的代码——所有这些都进入vba6.dll,但不进入msvbvm60.dll(那里不需要)。
如果我们做一些简化,并没有给自己设定严格保持规模的目标,那么下图完美地展示了构成IDE(环境)的可执行文件和作为运行时的可执行文件实际上是如何组成的一个共同的代码:
上面已经列出了一些属于Ruby和EB的东西,虽然不完整,但已经足够了。如果我们进一步简化,去掉多余的,只留下 VB 中最突出和经常被记住的组件,那么我们就可以将它们应用到这个插图中。再次想说:这是一个基于高度简化的文本的强简化图像。它的目的不是创建构成Ruby和EB 的子组件的完整列表。. 完整列表放不下这么小的图片,图片至少要放大 20 倍。目标只是简单地看一下插图,理解和感受这个想法,分离的原则。粗略了解哪些子组件(负责某些事情)是 Ruby 的一部分,哪些是 EB 的一部分,以及这些子组件如何分布在可执行文件(VB6.EXE、VBA6.DLL 和 MSVBVM60.DLL)中。这是修改后的插图:
在接下来的文章中,我们将更详细地讨论 EB 和 Ruby 的组成,我们将更详细地考虑构成一个可用的 VB IDE 的组件集(毕竟,除了 VB6. EXE和VBA6.DLL,还有LINK.EXE、C2.EXE、MSO98RT.DLL ip)。
http://bbs.vbstreets.ru/viewtopic.php?f=101&t=56551