使用回调接口实现ActiveX控件和它的容器程序的通讯
什么是ActiveX插件?
什么是ActiveX插件?自从Microsoft公司于1996年推出ActiveX技术以来, ActiveX技术已得到了许多软件公司的支持和响应, 并纷纷在其产品中融入ActiveX技术。
而作为ActiveX技术之一的ActiveX控件也得到了迅猛的发展, 不但各大软件公司推出了不少ActiveX 控件, ActiveX控件更是得到一般开发者的喜爱。
那么, 什么是ActiveX控件呢? ActiveX控件是一个动态链接库, 是作为基于COM服务器进行操作的, 并且可以嵌入在包容器宿主应用程序中, ActiveX控件的前身就是OLE控件。
由于ActiveX控件与开发平台无关, 因此, 在一种编程语言上开发的ActiveX控件可以无须任何修改, 即可在另一种编程语言中使用, 其效果如同使用Windows通用控件一样。
如: 在VC++中开发的ActiveX控件, 不作任何修改即可应用于VB中。
由此可见, 通过使用ActiveX控件即可实现快速小型的组件重用、实现代码共享, 从而提升编程效率。
从上面亦可看出为何ActiveX控件如此广泛地受到开发者的欢迎。
因为ActiveX控件的可重用性, 加上Internet的普及, ActiveX控件得到了极大的发展, 目前, 从Internet上可以得到相当多的ActiveX控件, 而且品种繁多, 所完成的任务几乎无所不包。
对一般开发者来说, 只要有耐心, 都能从Internet上找到符合自己要求的ActiveX控件。
从Internet下载的ActiveX控件,或从其他途径得到的ActiveX控件,用户应该怎样做才能正确使用ActiveX控件或将其应用于自己的程序中呢?一般来说,一个外来ActiveX控件要在Windows中被正确使用,首先必必需将控件文件〔*.OCX〕复制到硬盘中,然后将其在Windows中注册,未在Windows中注册过的ActiveX控件是不能使用的。
delphi实现websocket的一款非常强势的控件----sgcWebsocket
delphi实现websocket的⼀款⾮常强势的控件----sgcWebsocket 最近⼿头有个项⽬需要⽤到websocket,⾃⼰写⼀个显然不⼤可能,时间与精⼒也不允许,别⼈我不知道,我是⼀个⽐较懒的⼈,选择delphi编程就是因为他能偷懒,编程是体⼒活,⼀个好的项⽬是基于⼀个好的创新idea上的,别⼈想不到的创意,你想到了并⽤程序实现了,这是⼀个很厉害的⾏为。
于是在⽹上搜下看有没有开源的第三⽅控件。
您别说还真搜到⼏个,经过筛选,最后锁定sgcWebsocket。
选择它的原因很简单,⽹络协议⼀直在发展,只有他⽐较新,可能满⾜我们的需求。
⾸先找到是sgcWebsocket 4.1.0源码版本,尝试编译失败,因为sgcWebsocket是基于indy上⾯实现的,由于delphi7是9.0版本太旧了,需要更新到indy10。
更新完成之后尝试编译发现有个inherit;⽆法编译,不管他注释掉再说,安装成功后尝试了部分ws://与wss://的websocket发现可以成功通信,但是我的项⽬使⽤的是wss://的⾼版本的协议来通信的,⽆法通信成功。
不想对⽼版本做修改,这太累了,不死⼼看看有没有新的版本,您别说还真找到了sgcWebsocket 4.4.4 源码版,这时我才知道这个第三⽅控件作者⼀直是在维护的,差不多⼀个⽉左右会更新⼀次,并且是收费的,试⽤版提供的是dcu⽂件,看了下收费版源码的价格,好像也不贵,以后真的要长期⽤这个控件的话,可以出钱买⼀份,毕竟算是⽤⾦钱换时间吧,⽽且作者也⼀直在更新修复BUG。
好,⾔归正传,直接编译这个版本很顺利,⾼版本就是不⼀样,这个版本多了协议版本可以选择,选择了1.2版本,简单的配置下连接,发现与服务器wss://xxxxxx/socket.io/?transport=websocket通信成功。
成功是成功了,可是发现中⽂返回的是问好????,不显⽰中⽂,⽐较苦恼,最后折腾了⼀天,⼜是OD调试,⼜是搜索,最后发⾏居然还是indy版本的原因。
actxserver用法 -回复
actxserver用法-回复ActXServer是一种用于创建和管理Microsoft ActiveX服务器组件的工具。
它提供了一种简单而有效的方法来开发和部署可重用的代码,以增加应用程序的功能和灵活性。
本文将逐步介绍ActXServer的用法,并提供使用该工具的基本步骤供读者参考。
第一步:了解ActXServer的基本概念和功能ActXServer是一个用于创建和管理ActiveX服务器组件的工具。
ActiveX是一种微软开发的技术,用于创建可移植的、可重用的软件组件。
这些组件可以用于各种应用程序开发环境,如Visual Basic、Visual C++和JavaScript等。
ActXServer允许开发人员使用多种编程语言,如C++、Delphi和Java等来创建ActiveX组件。
ActXServer的主要功能包括:1. 创建和管理ActiveX服务器组件。
2. 提供简单而强大的编程接口,用于与组件进行交互。
3. 支持多种编程语言和开发环境。
4. 提供强大的调试和部署工具,用于测试和发布组件。
第二步:安装ActXServer在开始使用ActXServer之前,需要先安装该工具。
ActXServer通常作为集成开发环境(IDE)的一部分提供。
例如,如果你使用的是VisualStudio,则可以在安装过程中选择安装ActXServer工具。
安装完成后,你将能够在IDE中访问和使用ActXServer。
第三步:创建一个新的ActiveX组件接下来,我们将介绍如何使用ActXServer创建一个新的ActiveX组件。
请按照以下步骤操作:1. 打开IDE,并选择创建一个新的项目。
2. 选择ActiveX组件项目类型,并指定名称和保存位置。
3. 在项目中添加所需的代码文件,并编写组件的功能逻辑。
4. 在项目属性中配置组件的属性,如版本信息、注册表设置等。
5. 编译和构建项目,生成ActiveX组件文件。
利用Delphi编写Socket通信程序
利用Delphi编写Socket通信程序一、前言随着计算机技术的不断发展,网络应用得到了越来越广泛的应用,而Socket编程作为网络编程中最基础、最重要的部分,具有非常重要的意义。
Delphi是一种构建Windows应用程序的高级集成开发工具,支持对象化设计、事件驱动、可视化编程等多种编程方式。
Delphi具有非常强大的GUI设计、数据访问、组件开发等特点,可以方便地应用到Socket编程中,实现Socket通信程序的开发。
本文就介绍利用Delphi编写Socket通信程序相关的知识。
二、Socket编程基础Socket是一种用于网络通信的编程接口,它把网络通信抽象成发送和接收数据的过程。
Socket编程分为客户端和服务器两部分,客户端负责向服务器发起连接请求,服务器则负责接收客户端的连接请求,并根据请求提供相应的服务。
Socket编程中,通常使用TCP/IP协议进行数据传输。
TCP协议是一种可靠的、面向连接的协议,它通过三次握手建立连接,保证数据的可靠性、完整性和顺序性。
而UDP协议则是一种不可靠的、无连接的协议,它不保证数据的可靠性和完整性,但具有数据传递速度快等特点。
通常,TCP协议适用于对数据可靠性要求较高的应用场景,如文件传输、邮件系统、即时通信等;而UDP协议适用于对数据传输速度要求较高的应用场景,如视频直播、网络游戏等。
三、利用Delphi编写Socket通信程序1. 创建Socket使用Delphi进行Socket编程,可通过TServerSocket和TClientSocket组件来实现。
TServerSocket组件用于创建服务器Socket,TClientSocket组件用于创建客户端Socket。
在Delphi中,可以通过在组件面板中拖拽TServerSocket或TClientSocket组件来创建Socket。
使用TServerSocket组件创建服务器Socket的示例代码如下:```delphiprocedure TMyForm.FormCreate(Sender: TObject);begin ServerSocket1.Port := 8888;ServerSocket1.Active := True;end;procedure TMyForm.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);beginMemo1.Lines.Add(Socket.RemoteAddress + ' connected.');end;```上述代码中,将ServerSocket1的Port属性设置为8888,表示该服务器监听8888端口的连接请求。
如何在WPF中使用ACTIVEX
如何在WPF中使用ACTIVEX在WPF(Windows Presentation Foundation)中使用ActiveX控件涉及以下几个步骤:1. 添加对ActiveX控件的引用:在Visual Studio中打开WPF项目,右键单击项目名称,选择“添加→引用”。
在打开的对话框中,选择“COM”选项卡,然后浏览选择要添加的ActiveX控件的.dll文件。
点击“确定”按钮进行引用添加。
2. 在XAML中添加WindowsFormsHost控件:在WPF的XAML文件中引入WindowsFormsIntegration命名空间,并添加一个名为WindowsFormsHost的控件。
这个控件将用作ActiveX控件的容器。
```xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"xmlns:wfIntegration="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsForms Integration"...<wfIntegration:WindowsFormsHost Name="windowsFormsHost"><Grid><!-- ActiveX控件将被放置在此 --></Grid></wfIntegration:WindowsFormsHost>```3. 创建和设置ActiveX控件:在项目的代码文件中,使用ActiveX 控件的类创建一个实例,并将其添加到WindowsFormsHost控件中。
```using System.Windows.Forms;...// 在适当的位置创建ActiveX控件实例var activeXControl = new SomeActiveXControl(;// 设置ActiveX控件的属性activeXControl.SomeProperty = value;// 将ActiveX控件添加到WindowsFormsHost控件中windowsFormsHost.Child = activeXControl;```4. 处理ActiveX控件的事件:如果需要处理ActiveX控件的事件,可以为其添加事件处理程序。
delphi form中调用frame窗体内的控件 -回复
delphi form中调用frame窗体内的控件-回复Delphi是一种高级编程语言,专门用于Windows平台的软件开发。
以Delphi语言为基础的应用程序通常是通过创建窗体(Form)来构建用户界面。
窗体是一个可视化的容器,可以包含各种控件,例如按钮(Button)、菜单(Menu)和文本框(Edit)等。
除了窗体,Delphi还支持使用帧(Frame)来创建可重用的用户界面组件。
帧是一种特殊类型的窗体,可以包含自己的界面控件和代码逻辑,而且可以在其他窗体或帧中重复使用。
在大型项目中,使用帧有助于提高代码的可维护性和可扩展性。
在Delphi中,要在窗体中调用帧窗体内的控件,可以遵循以下步骤:步骤1:创建帧窗体首先,需要创建一个帧窗体,并在其上放置所需的控件。
可以通过选择“File”-> “New”-> “Other”-> “Delphi Files”-> “Frame”来创建一个新的帧窗体。
在帧窗体上,可以放置各种控件,例如按钮、标签和文本框等。
在设计时,可以使用Delphi的可视化界面编辑器来设置控件的属性和事件。
通过在帧窗体上点击控件,可以选择“Properties”窗口来查看和修改控件的属性。
步骤2:将帧窗体添加到主窗体一旦帧窗体完成设计,就可以将其添加到主窗体中。
可以通过选择“Project”-> “Add to Project”-> “Frames”来添加现有的帧窗体文件。
在添加帧窗体后,可以在主窗体上看到帧窗体的外观和控件。
可以通过在主窗体上选择帧窗体,然后在“Object Inspector”中设置其属性。
步骤3:在主窗体中调用帧窗体控件要在主窗体中调用帧窗体内的控件,可以使用以下方法:方法一:通过属性访问在主窗体的代码中,可以通过直接访问帧窗体的属性来获取或设置控件的属性。
例如,如果帧窗体上有一个名为“Button1”的按钮控件,并且已将其Visible属性设置为True,则可以使用以下代码在主窗体上隐藏该按钮:Frame1.Button1.Visible := False;方法二:通过事件处理程序如果帧窗体上的控件具有与其关联的事件(例如,按钮的OnClick事件),则可以在主窗体上创建相应的事件处理程序方法。
VB1
过RS-422口或RS-232C口进行的,信息交换的方式为字符串方式,运用RS-232C或RS-422通道,容易配置一个与计算机进行通信的系统,将所有软元件的数据和状态用可编程控制器送入计算机,由计算机采集这些数据,进行分析及运行状态监测。
用计算机改变可编程控制器设备的初始值和设定值,从而实现计算机与可编程控制器的直接控制,一旦确定了可编程控制器的控制指令,就能很方便地与计算机连接。
2 S7-200的自由口通讯模式S7-200支持多种通讯模式,如点点接口(PPI)、多点接口(MPI)、Rrofibus DP等。
PPI等通讯协议主要用于西门子系列产品之间的通讯以及对PLC编程。
在自由口模式下,可由用户控制串行通讯接口,实现用户自定义的通讯协议。
用户可以用梯形图程序调用接收中断、发送中断、发送指令(XMT)、接受指令(RCV)来控制通信操作。
在自由口模式下,通信协议完全由梯形图程序控制。
S7-200CPU上的通信口是与RS-485兼容的9针D型连接器,PLC还提供了实现 RS-485与 PC机上RS-232C相连接的PC/PPI电缆,利用它可以方便地实现S7-200系列PLC与PC之间的硬件连接。
S7-200的编程软件为STEP7-Micro/WIN32,该软件有STL、FBD和Ladder三种编程模式,有SIMATIC 指令和IEC131-3指令两种指令。
本文所给出的范例是使用SIMATIC指令的STL编程。
3 S7-200 PLC端的通讯程序实现PLC程序分为主程序和中断程序。
主程序完成初始化通信口、开中断、判断、发送数据等功能,中断程序完成接收和发送数据的功能。
接收指令(RCV)启动或终止接收信息功能,必须为接收操作指定开始和结束条件。
发送指令(XMT)在自由口模式下依靠通讯口发送数据。
3.1 控制字的选取反映CPU工作方式的模式开关当前位置的特殊存储器位为SM0.7,它控制自由端口模式的进入。
npactivex原理 -回复
npactivex原理-回复NPActiveX原理一文NPActiveX(Netscape Plugin ActiveX)是一种技术,允许在Netscape Navigator 浏览器中嵌入Microsoft ActiveX 控件。
它的出现为在Netscape Navigator 浏览器中使用基于Windows 平台的ActiveX控件提供了解决方案。
本文将详细解释NPActiveX 的原理,从基本概念到工作流程,逐步回答读者关于NPActiveX 的问题。
1. NPAPI 框架要理解NPActiveX 的原理,首先需要了解NPAPI(Netscape Plugin Application Programming Interface)框架。
NPAPI 是Netscape Navigator 浏览器提供的插件架构,允许开发者为浏览器添加自定义功能。
这个框架旨在通过使用插件来扩展浏览器的功能,并允许插件与浏览器进行通信。
2. ActiveX 控件ActiveX 控件是一种可重用的软件组件,目的是在不同的应用程序中共享代码和功能。
它们最初由微软开发,用于在Windows 平台上开发跨应用程序的功能。
ActiveX 控件可以通过使用COM(Component Object Model)接口,提供一组预定义的功能和方法供应用程序调用。
3. NPActiveX 的工作原理NPActiveX 的原理是通过在Netscape Navigator 浏览器中嵌入ActiveX 控件,实现在非Windows 环境下的ActiveX 控件的调用。
该技术是复杂而底层的,需要开发者将ActiveX 控件封装在一个特定的插件中,并使用NPAPI 进行通信。
4. NPActiveX 插件开发开发NPActiveX 插件涉及以下步骤:a. 创建一个基于NPAPI 的插件项目,并定义插件和插件实例的结构。
b. 实现插件的基本功能,例如初始化、销毁和绘制等。
LabVIEW中MSComm实现串口通信编程学习
LabVIEW中MSComm实现串口通信编程学习问题描述:对于一般的应用,LabVIEW 中直接用VISA 串口API 函数就可以实现,方便快捷,但是对于需要使用中断方式进行串口通信的,就得使用MSComm 控件来实现了。
MSComm 控件:操作ActiveX 控件,最主要的就是要使用好它的属性、方法函数,并做好中断事件的回调处理。
LabVIEW 针对ActiveX 设置的控件在互连接口的ActiveX 中提供了8 个功能函数:Automation Open, Close Reference, To Variant, Variant to Data, Invoke Node, Property Node, Register Event Callback, UnRegister Event Callback。
在LabVIEW 中使用MSComm 控件:首先需要在LabVIEW 中加入MSComm,在工具--导入-- ActiveX 至选板中将MSComm 添加到LabVIEW 环境,选择默认路径。
然后可以在前面板的”.Net与ActiveX”中找到mscomm 然后拖拽到前面板中。
也可以先在前面板放置ActiveX 容器,然后右键选择mscomm 控件:调用ActiveX 控件创建客户端应用程序:主要用到互连接口--ActiveX 中的8 个函数:ActiveX 事件注册相关:即使用事件回调处理中断事件等,编程注意事项:对于MSComm 控件,编程时使用的都是其自动化引用,即LabVIEW将ActiveX 控件作为对象来处理。
连接属性节点到控件,可以查看所有属性,连接调用节点时,MSComm 没有提供方法,所以会显示没有方法。
以下是LabVIEW 中看到的MSComm 的属性:另外,回调事件注册首先要确定好需要传输什么样的数据,如果包含多种数据类型,可以使用簇来解决,回调函数中会自动创建与该数据类型相同的事件参数,并提供ActiveX 控件的引用。
12.事件结构
事件结构阮奇桢Event Structure 也是一种选择结构,程序根据发生的事件决定执行哪一个页面的程序。
此时,LabVIEW 的界面编写与Visual Basic 的界面程序有些类似。
一. 按照产出源来区分事件的种类按照事件的产生源来区分,LabVIEW有以下几种事件:图1:配置事件1.应用程序事件(<Application>),这类事件主要反映整个应用程序状态的变化,例如:程序是否关闭,是否超时等。
2.VI事件(<This VI>),这类事件反映当前VI状态的改变。
例如:当前VI是否被关闭,是否选择了菜单中的某一项等等。
3.动态事件(Dynamic),用于处理用户自己定义的或在程序中临时生成的事件。
4.区域事件(Pane)和分割线事件(Splitter)是LabVIEW 8中新添加的特性。
LabVIEW 8中,用户可以把一个VI的前面板分割成几份,这两类事件用来处理用户对某个区域或区域分割线的状态的改变。
图2:面板上划分区域5.控件事件(Control)是最常用的一种事件,用于处理某个控件状态的改变。
例如,控件值的改变,或者鼠标键盘的操作。
打开上述的“edit events”框,只要选定了某一个事件产生源,其相应的所有事件均排列在右侧events框中。
有时候,多个事件产生源会对同一个用户操作分别产生相应事件。
比如在某一控件上按下鼠标,区域事件和控件事件都会发出鼠标按下(Mouse Down)事件。
LabVIEW 按以下规则顺序产生不同的事件:键盘相关的事件(Key Down, Key Up, etc.)只在当前选中(Key Focused)的控件上产生;鼠标相关的事件(Mouse Down, etc.)按照从外向里的顺序发出。
例如,区域的鼠标按下事件先于控件的鼠标按下事件发出;结构的鼠标按下事件先于先于结构内控件的鼠标按下事件发出。
值改变事件按照从内向外的顺序发出。
调用ocxActiveX控件详解(做一个简单的ocx控件)
调⽤ocxActiveX控件详解(做⼀个简单的ocx控件)最近做的项⽬都和插件有关,就是在页⾯中调⽤插件的⽅法,然后进⾏操作。
插件就是ocx ActiveX控件,具体的说明可以⾃⼰去了解⼀下,在这⾥就不做赘述。
具体调⽤⽅式很简单:1、在页⾯中写⼀个object标签,标签中定义⼀个classid属性,这个属性是获取到插件的关键<object id="ocx" classid="clsid:c998ae90-5ffc-4a58-97d2-490a414bd6e5"></object>2、直接在js中获取到这个dom,然后就可以调⽤插件中的⽅法let ocx = document.getElementById("ocx");let sum = ocx.Add(1,2);在使⽤过程中遇到了很多问题,于是⾃⼰去摸索了⼀下如何制作⼀个ocx插件,也能够帮助⾃⼰加深⼀些使⽤⽅⾯的了解。
这⾥使⽤Visual Studio Community 2019,先下载必须的组件和依赖包。
使⽤C++的桌⾯开发和Visual Studio扩展开发这两项必须要勾选。
然后桌⾯开发中还需要勾选与MFC相关的库,如果不勾选的话⽆法新建MFC项⽬勾选完成后就开始下载相关的包,这个过程需要等待⼀会。
下载完成后就可以开始新建⼀个项⽬,在这⾥选择MFC ActiveX控件,命名为MyMFCActiveXControl然后就会⽣成⼀系列控件名,头⽂件等等的⽂件名,这⾥基本上不⽤做什么操作,直接完成就好。
唯⼀需要注意的是⼀个控件类型ID,这个ID我们后⾯会⽤到。
点击完成后,就会⽣成⼀系列与插件相关的⽂件,这些⽂件⾥⾯包含了插件的类,头⽂件,描述等信息。
因为不是专门学习C++的,不对⾥⾯的原理和结构进⾏探究,就取我需要的内容就⾏。
来找⼀找那个神奇的classid。
利用DELPHI多线程机制实现PC机与PLC之间的串行通信
利用DELPHI多线程机制实现PC机与PLC之间的串行通信在Delphi中实现PC机与PLC之间的串行通信可以利用Delphi的多线程机制来实现。
下面将介绍详细的步骤。
2. 将TIdSerialPort组件添加到窗体上。
TIdSerialPort是Delphi 中处理串行通信的组件,可以通过Indy控件库进行获取和使用。
3. 在窗体上添加一个Label控件,用于显示接收到的数据。
4. 在窗体上添加一个Edit控件,用于输入要发送的数据。
5. 添加一个Button控件,用于发送数据。
6. 双击Button控件,在OnClick事件中添加以下代码:```delphiprocedure TForm1.Button1Click(Sender: TObject);vardata: string;begindata := Edit1.Text;TThread.CreateAnonymousThreadprocedurebeginIdSerialPort1.WriteLn(data);.Startend;```上述代码创建了一个匿名线程,在线程中使用IdSerialPort1.WriteLn方法向串口发送数据。
7. 双击TIdSerialPort1的OnRxChar事件,在事件处理程序中添加以下代码:```delphiprocedure TForm1.IdSerialPort1RxChar(Sender: TObject; Count: Integer);vardata: string;begindata := IdSerialPort1.ReadLn;TThread.Queue(nil,procedurebeginLabel1.Caption := data;end```上述代码在串口接收到数据时,使用IdSerialPort1.ReadLn方法将接收到的数据读取到data变量中,并使用TThread.Queue方法将显示更新的代码放到主线程中执行,以避免主线程阻塞。
CVI简介
CVI简介随着电子技术、计算机技术的高速发展及其在电子测量技术与仪器领域的应用,新的测试理论、测试方法、测试领域以及仪器结构不断出现,电子测量仪器的功能和作用也发生了质的变化,仪器与计算机技术的深层次结合产生了全新的仪器结构概念——虚拟仪器。
它的出现使测试仪器与计算机之间的界限消失,从此开始了测量仪器的新时代。
虚拟仪器强调软件的作用,提出了“软件就是仪器”的概念。
1、虚拟仪器技术随着计算机技术、大规模集成电路技术和通信技术的飞速发展,仪器技术领域发生了巨大的变化,美国国家仪器公司(National Instruments,简称NI)于20世纪80年代中期首先提出基于计算机技术的虚拟仪器的概念,把虚拟测试技术带入新的发展时期,随后研制和推出了基于多种总线系统的虚拟仪器。
经过十几年的发展,虚拟仪器技术将高速发展的计算机技术、电子技术、通信技术和测试技术结合起来,开创了个人计算机仪器时代,是测量仪器工业发展的一个里程碑。
1.1虚拟仪器概念1.虚拟仪器概念所谓虚拟仪器,就是在以个人计算机为核心的硬件平台上,由用户设计定义、具有虚拟面板、测试功能由测试软件实现的一种计算机仪器系统。
操作者用鼠标或键盘操作虚拟面板,就如同使用一台专用测量仪器,虚拟仪器的出现使测量仪器与个人计算机的界限模糊了。
虚拟仪器的实质是利用计算机显示器的显示功能来模拟传统仪器的控制面板,以多种形式表达输出检测结果,利用计算机强大的软件功能实现数据信号的运算、分析和处理,利用I/O 接口设备完成信号的采集、测量和处理,从而完成各种测试功能的一种计算机仪器系统。
“虚拟”主要包含以下两方面的含义。
1)新能源强的面板虚拟仪器面板上的各种“控件”与传统仪器面板上的各种“器件”所完成的功能是相同的。
如由各种开关按键显示器等实现仪器电源的“通”、“断”,被测信号“输入通道”、“放大倍数”等参数设置,测量结果“数值显示”、“波形显示”等。
传统仪器面板上的器件都是实物,而且都通过手动和触摸完成操作的,而虚拟仪器面板控件是外形与实物相似的图表,“通”、“断”、“放大”等对应着相应的软件程序,这些软件已经设计好了,用户只需选用代表该种软件程序的图形控件即可,用计算机的鼠标对其进行操作。
delphi form中调用frame窗体内的控件 -回复
delphi form中调用frame窗体内的控件-回复Delphi是一种基于对象的Pascal编程语言,用于开发Windows平台上的可视化应用程序。
其提供了许多方便的功能和组件,使开发者能够快速构建强大和复杂的界面。
在Delphi中,可以使用form窗体和frame窗体来组织和管理界面控件。
在Delphi中,form窗体和frame窗体都可以包含各种控件,例如按钮、标签和输入框等。
当我们需要在form窗体中调用frame窗体内的控件时,可以通过以下步骤完成。
第一步,创建一个新的Delphi应用程序项目。
在Delphi IDE中,选择“文件”菜单,然后选择“新建”->“项目”命令。
在弹出的对话框中,选择“应用程序”模板,然后点击“确定”按钮。
第二步,创建一个新的form窗体。
在项目资源管理器中,右键单击“项目名.dpr”文件(通常为项目名称后缀为.dpr的文件),然后选择“附加”->“新建”->“窗体”命令。
选择“窗体”模板,点击“确定”按钮。
第三步,创建一个新的frame窗体。
在项目资源管理器中,右键单击“项目名.dpr”文件,选择“附加”->“新建”->“框架”命令。
选择“框架”模板,点击“确定”按钮。
第四步,将frame窗体嵌入到form窗体中。
在form窗体的设计视图中,选择“项目”菜单,然后选择“附加”->“窗体”命令。
在弹出的对话框中,选择要嵌入的frame窗体,点击“确定”按钮。
第五步,在form窗体中调用frame窗体内的控件。
在form窗体的代码视图中,找到frame窗体的实例化代码。
通常情况下,Delphi会自动生成一个以“TFrame名”为名字的变量。
例如,如果frame窗体的名称为“Frame1”,则会生成一个名为“Frame1: TFrame1”的变量。
使用这个变量,可以通过以下方式访问frame窗体内的控件:delphiFrame1.控件名.属性:= 值;例如,假设frame窗体内有一个名为“Button1”的按钮,我们可以使用以下代码在form窗体中设置该按钮的可见性:delphiFrame1.Button1.Visible := False;当然,还可以调用按钮的其他属性和方法,例如单击事件。
mfc调用active控件
mfc调用active控件
MFC(Microsoft Foundation Class)是一种用于开发Windows 应用程序的C++类库,而ActiveX控件是一种可重用的软件组件,通常用于在Web浏览器或其他容器应用程序中显示交互式内容。
在MFC中调用ActiveX控件可以通过以下步骤实现:
1. 首先,你需要在MFC应用程序中创建一个对话框或视图来容纳ActiveX控件。
你可以在资源编辑器中添加一个ActiveX控件,或者在代码中动态创建和添加ActiveX控件。
2. 然后,你需要在MFC应用程序中使用类向导来生成ActiveX 控件的包装类。
在Visual Studio中,你可以使用“添加类”对话框来生成包装类。
3. 生成包装类后,你可以在对话框或视图类的代码中实例化ActiveX控件的包装类对象,并调用其方法或设置其属性。
例如,你可以使用Create函数创建ActiveX控件的实例,并使用其提供的方法来实现所需的功能。
4. 最后,在MFC应用程序的消息映射函数中处理ActiveX控件
的事件,例如按钮点击事件或文本框内容改变事件。
你可以通过包装类提供的事件映射功能来实现对ActiveX控件事件的处理。
总的来说,MFC调用ActiveX控件涉及到创建包装类、实例化控件对象、调用控件方法和处理控件事件等步骤。
通过这些步骤,你可以在MFC应用程序中有效地使用ActiveX控件实现丰富的交互式功能。
delphi 代码中设置控件的方法 -回复
delphi 代码中设置控件的方法-回复Delphi代码中设置控件的方法在Delphi中,设置控件是编写桌面应用程序的基本任务之一。
通过设置控件的属性,可以实现对其外观、大小、位置、行为和其他一些与用户交互相关的方面进行控制。
本文将一步一步地解释Delphi中设置控件的方法。
第一步:添加控件到窗体首先,在Delphi中,我们需要在窗体上添加控件。
这可以通过拖放控件到窗体设计视图上或者通过编程方式创建控件来实现。
拖放方式是最常用的方法。
在Delphi的窗体设计视图中,从工具箱中选择所需的控件,将鼠标拖动到窗体上,并释放鼠标按钮。
这将在窗体上创建一个新的控件实例。
编程方式创建控件需要用到Delphi的组件对象模型(Component Object Model, COM)。
首先,需要选择所需的控件类型,然后使用代码创建该控件的实例。
第二步:设置控件属性添加控件到窗体后,可以开始设置控件的属性。
在Delphi中,可以通过属性编辑器或代码来设置控件的属性。
使用属性编辑器属性编辑器是Delphi中设置控件属性的常用方法。
可以在组件面板中选中相应的控件,然后在对象检查器面板中查看和编辑控件的属性。
属性可以按字母顺序或按类别进行排序,以便更轻松地找到所需的属性。
使用代码通过编程方式设置控件属性可以使用Delphi的对象模型。
可以在代码中使用控件实例的属性或方法来设置相应的属性。
以下是一个示例,演示了如何以代码方式设置一个编辑框的背景颜色:pascalEdit1.Color := clYellow;本示例将编辑框(Edit1)的背景颜色设置为黄色。
以此方式,通过为控件实例调用属性和方法,可以对控件的各个属性进行设置。
例如,可以设置控件的字体、大小、位置、可见性等等。
第三步:设置控件事件处理程序除了设置控件的属性外,还可以为其添加事件处理程序,以响应用户的交互。
Delphi中的事件处理程序是一个特殊的方法,用于处理控件与用户之间的交互。
delphi clientsocket 用法
delphi clientsocket 用法Delphi的ClientSocket组件是一个非常有用的网络通信组件,它允许你创建一个TCP/IP客户端,与远程服务器进行通信。
以下是使用Delphi的ClientSocket组件的基本步骤:1. 首先,在你的Delphi项目中添加一个TClientSocket组件。
你可以在工具箱中找到ClientSocket组件,然后将它拖放到你的窗体上。
2. 在TClientSocket的属性中,设置好连接的服务器地址和端口号。
你可以通过修改`Host`和`Port`属性来实现。
3. 添加事件处理程序来处理连接和通信过程中的事件。
TClientSocket有一些重要的事件,比如`OnConnect`,`OnDisconnect`,`OnRead`等等。
你可以在这些事件中编写你自己的代码来实现特定的功能。
例如,当连接成功建立时,`OnConnect`事件会触发,你可以在事件中执行相关操作。
下面是一个简单的示例代码,展示了如何使用Delphi的ClientSocket组件来连接服务器并进行通信:```delphiunit Unit1;interfaceuses// 导入所需的单元typeTForm1 = class(TForm)ClientSocket1: TClientSocket;Button1: TButton;Memo1: TMemo;procedure ClientSocket1Connect(Sender: TObject;Socket: TCustomWinSocket);procedure ClientSocket1Disconnect(Sender: TObject;Socket: TCustomWinSocket);procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);procedure Button1Click(Sender: TObject);private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;implementation{$R *.dfm}procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);beginMemo1.Lines.Add('Connected to server.');end;procedure TForm1.ClientSocket1Disconnect(Sender: TObject;Socket: TCustomWinSocket);beginMemo1.Lines.Add('Disconnected from server.');end;procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);beginMemo1.Lines.Add('Received: ' + Socket.ReceiveText);end;procedure TForm1.Button1Click(Sender: TObject);beginif not ClientSocket1.Active thenClientSocket1.Open; // 打开与服务器的连接end;end.```在上面的示例中,当点击Button1按钮时,会尝试与在TClientSocket的属性中指定的服务器建立连接。
java调用activex控件
成功了高兴中先谢谢上面各位了小嵩我用的是jni调用的c++作的嵌入了一个浏览器:)把代码发上来大家分享------------------------------------------------------//MyW indow.javaimpo rt ja va.aw t.*;impor t jav ax.sw ing.*;imp ort j ava.a wt.ev ent.*;imp ort j ava.a wt.pe er.*;impo rt su n.awt.*;publi c cla ss My Windo w ext endsCanva s{ st atic{// Lo ad th e lib rarythatconta ins t he JN I cod e. Syst em.lo adLib rary("MyWi ndow"); }// nat ive e ntrypoint foriniti alizi ng th e IEcontr ol. pu blicnativ e sta tic v oid i nitia lize(int h wnd,Strin g str URL); // n ative entr y poi nt fo r res izingpubli c nat ive s tatic void resi zeCon trol(int h wnd,int n Width, int nHei ght);publi c nat ive s tatic intgetNa tiveW indow Handl e(Can vas c anvas); pub lic v oid a ddNot ify(){super.addN otify(); m_h Wnd = getN ative Windo wHand le(th is); in itial ize(m_hWnd, m_s trURL); }S tring m_st rURL= "ht tp://www.163.co m"; in t m_hWn d = 0;p ublic stat ic vo id ma in( S tring[] ar gv ){F ramef = n ew Fr ame();f.set Layou t(new Bord erLay out()); f.se tTitl e("In terne t Exp lorer insi de Ja va Ca nvas");MyWin dow w = ne w MyW indow(); if(argv.lengt h>0) w.m_strU RL =argv[0]; St ringstrTe xt ="URL:" + w.m_st rURL;f.add(w,Bor derLa yout.CENTE R); f.a dd(ne w Lab el(st rText),Bor derLa yout.NORTH); f.se tBoun ds(300,300,500,300);f.setV isibl e(tru e); }publi c voi d set Size( intwidth, int heig ht ){super.setS ize(w idth,heigh t); if(m_hWn d!=0) re sizeC ontro l(m_h Wnd,width, hei ght);} pub lic v oid s etSiz e( Di mensi on d) { sup er.se tSize(d); if(m_hW nd!=0)r esize Contr ol(m_hWnd, d.wi dth,d.hei ght);} pub lic v oid s etBou nds(int x, int y, i nt wi dth,int h eight ) { su per.s etBou nds(x,y,wi dth,h eight); if(m_hWnd!=0) res izeCo ntrol(m_hW nd, w idth, heig ht);} publ ic vo id se tBoun ds( R ectan gle r ) { su per.s etBou nds(r); if(m_hWnd!=0) res izeCo ntrol(m_hW nd, r.widt h, r.heigh t); }}--------------------------------------------------------------将上面的文件编译得到MyWi ndow.class再用ja vah M yWind ow命令得到MyWi ndow.h头文件(是给c++用的)剩下的事交给vc了小嵩的vc是vc6.0中文版建立一个dl l的工程文件-〉新建-〉Wi n32 D ynami c-Lin k Lib iary命名为My Windo w建立一个.cpp文件 My Windo w.cpp----------------------------------------------------------//MyW indow.cpp#incl ude <jni.h>#in clude <jaw t.h>#incl ude <afxwi n.h>#incl ude <windo ws.h>#inc lude"MyWi ndow.h"#i nclud e "ja wt_md.h"//#inc lude<asse rt.h>#inc lude<proc ess.h>// Incl udesfor A TL#p ragma comm ent(l ib,"a tl.li b")#inclu de <a tldef.h>#defin e _AT L_DLL_IMPL#inc lude<atli face.h>#i nclud e <at lbase.h>#inclu de <e xdisp.h>// St ructu re fo r Thr ead P arame ters.type def s truct { cha r szU RL[1024];H WND h wnd;} Thr eadPa ram;// H elper func tions.VOI D Cre ateIE Contr ol(Th readP aram*);s tatic void WINA PIV S tartA TL(LP VOID);J NIEXP ORT j int J NICAL L Jav a_MyW indow_getN ative Windo wHand le (JNIE nv *e nv, j objec t job j, jo bject wind ow){JAW T awt;awt.vers ion = JAWT_VERS ION_1_3;j boole an re sult= JAW T_Get AWT(e nv, &awt);if(resu lt == JNI_FALSE)ret urn 0;JA WT_Dr awing Surfa ce* d s = a wt.Ge tDraw ingSu rface(env, wind ow);if (ds == 0)r eturn 0;jintlock= ds->Lock(ds);if((loc k & J AWT_L OCK_E RROR) != 0)ret urn 0;JA WT_Dr awing Surfa ceInf o* ds i = d s->Ge tDraw ingSu rface Info(ds);if (dsi == 0)retur n 0;JAWT_Win32Draw ingSu rface Info* dsiw in =(JAWT_Win32Draw ingSu rface Info*) dsi->pla tform Info;jin t ret = re inter pret_cast<jint>(dsiw in->h wnd);ds->Free Drawi ngSur faceI nfo(d si);ds->U nlock(ds);awt.FreeD rawin gSurf ace(d s);retur n ret;}// nati ve me thodfor i nitia lizin g the cont rol.JNIEX PORTvoidJNICA LL Ja va_My Windo w_ini tiali ze(JNIE nv *p Env,jobje ct, j int h wndIn, jst ringstrin g){// Fil l upthe p arams. cons t cha r *st r = pEn v->Ge tStri ngUTF Chars(stri ng, 0); Thr eadPa ram *pThre adPar am =new T hread Param; pThr eadPa ram->hwnd= (HW ND) h wndIn; strc py(pT hread Param->szU RL,st r); pE nv->R eleas eStri ngUTF Chars(stri ng, s tr);// La unchthe T hread. _beg inthr ead(S tartA TL, 0, pTh readP aram);}// Th readfor c reati ng th e con trolvoid WINA PIV S tartA TL(LP VOIDlpVoi d){T hread Param *pTh readP aram= (Th readP aram*)lpV oid;C reate IECon trol(pThre adPar am);d elete pThr eadPa ram;M SG ms g; //Windo ws me ssage loop. whil e(Get Messa ge(&m sg, N ULL,NULL, NULL)) { Tra nslat eMess age(&msg);D ispat chMes sage(&msg); }}// C reate s IEcontr olVO ID Cr eateI ECont rol(T hread Param *pTh readP aram){ Atl AxWin Init(); pri ntf("Creat e Atl AxWin Begi n...[0x%x][%s]\n",pT hread Param->hwn d,pTh readP aram->szUR L); // In t he 2n d Par am yo u can useProgI D orUUIDof an y act ivexcontr ol. HW ND hw ndChi ld =::Cre ateWi ndow("AtlA xWin", "h ttp://www.micro soft.com", WS_CHIL D|WS_VISIB LE,0,0,0,0,pThre adPar am->h wnd,N ULL, ::Ge tModu leHan dle(N ULL), NUL L);I Unkno wn *p Unk = NULL; AtlA xGetC ontro l(hwn dChil d,&pU nk);p rintf("Cre ate A tlAxW in Do ne...[0x%x]\n",pUnk); //get a n int erfac e toset t he UR L. CCo mPtr<IWebB rowse r2> s pBrow ser;p Unk->Query Inter face(IID_I WebBr owser2, (v oid**)&spB rowse r); if (spB rowse r) { CCo mVari ant v e; CCom Varia nt vu rl(pT hread Param->szU RL);#prag ma wa rning(disa ble:4310) // c ast t runca tes c onsta nt va lue spB rowse r->pu t_Vis ible(VARIA NT_TR UE);#prag ma wa rning(defa ult:4310) // c ast t runca tes c onsta nt va lue spB rowse r->Na vigat e2(&v url,&ve,&ve,&ve,&ve);}}// na tivemetho d for hand lingresiz es.J NIEXP ORT v oid J NICAL L Jav a_MyW indow_resi zeCon trol(JN IEnv*, jo bject, jin t hwn dIn,jintwidth, jin t hei ght){ HWND hwnd = (H WND)hwndI n; REC T rc;if(hw nd!=N ULL){::GetW indow Rect(hwnd,&rc);H WND h wndCh ild = GetW indow(hwnd, GW_CHILD); prin tf("g ot re size(0x%x,%d,%d)\n",hwnd Child,widt h,hei ght);::SetW indow Pos(h wndCh ild,N ULL,0,0,rc.righ t-rc.left,rc.bo ttom-rc.to p,SWP_NOZO RDER|SWP_N OACTI VATE|SWP_S HOWWI NDOW|SWP_N OMO VE); }}----------------------------------------------------------在编译之前有几件事情得先做一下1.把刚才得到的M yWind ow.h文件复制到工程中2.把C:\P rogra m Fil es\Ja va\j2sdk1.5.0\i nclud e和C:\Pr ogram File s\Jav a\j2s dk1.5.0\in clude\win32下的文件复制到 C:\P rogra m Fil es\Mi croso ft Vi sualStudi o\VC98\Inc lude下面3.把C:\Pr ogram File s\Jav a\j2s dk1.5.0\li b下的ja wt.li b复制到C:\Progr am Fi les\M icros oft V isual Stud io\VC98\Li b下并在工程-〉设置-〉Link中添加jaw t.lib一切准备就绪按F7进行编译,于是在De bug中得到MyWi ndow.dll文件将它复制到你编写的java应用程序的文件夹中好了运行M yWind ow.cl ass看看结果吧。
基于UIMessages在TestStand和LabVIEWOI之间实现数据的双向传递
基于UIMessages在TestStand和LabVIEWOI之间实现数据的双向传递基于UI Messages在TestStand和LabVIEW OI之间实现数据的双向传递问题:UI Messages可以将TestStand Engine状态、当前Execution的信息传递⾄LabVIEW⽤户界⾯(Operator Interface),UI Messages传递的数据类型有三种:数值型(Numeric)、字符串(String)、对象引⽤(Object Reference)。
如果期望将数组(Numeric Array,String Array,Boolean Array)也从TestStand传递⾄OI;另外,如果期望从LabVIEW OI中将数据传递⾄TestStand,该如何实现。
解答:在引⼊以上抛出的问题的解决⽅法之前,我们先简单介绍⼀下TestStand的对象模型。
TestStand的核⼼是TestStand Engine,它是基于ActiveX/COM 的⾃动化服务器(Automation Server),严格的遵循⾯向对象编程(OOP)的⽅式,通过使⽤⽅法和属性将访问的接⼝提供给客户端,这些接⼝即TestStand API。
通过TestStand API,任何的编程语⾔如LabVIEW、LabWindows、C#、/doc/435321d5eff9aef8951e0632.html 、C++都可以和TestStand Engine进⾏交互,如在LabVIEW Operator Interface(后续简称LabVIEW OI)中,通过TestStand API 连接TestStand Engine,并唤起特定的Sequence执⾏,最后在LabVIEW OI中显⽰结果。
OI本⾝并不执⾏复杂的序列编辑等⼯作。
既然是遵循⾯向对象编程,那么TestStand Engine中所有的对象都将具备封装性、继承性和多态性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本文阅读基础:有一定的C++基础知识(了解继承、回调函数),对MFC的消息机制有一定了解,对COM的基础知识有一定了解,对ActiveX控件有一定了解。
一.前言ActiveX控件和它的容器程序如何通讯是一个值得研究的问题,因为这涉及到ActiveX控件和它的容器程序如何交互的问题。
VC知识库的杨老师写了一系列博客介绍了一些通讯方式。
链接如下:COM 组件设计与应用(十三)--事件和通知(VC6.0)COM 组件设计与应用(十四)--事件和通知()COM 组件设计与应用(十五)--事件和通知(VC6.0)COM 组件设计与应用(十六)--事件和通知()这些文章写得真的很好,语言幽默风趣,深入浅出。
我看后决心把它应用在ActiveX控件的回调实现上,经过实践,觉得有些地方语焉不详,自己做些摸索,写就此文,算是对杨老师文章的一点补充。
二.通知的方法ActiveX控件是一个窗口,它的容器程序自然也有一个父窗口;同时ActiveX控件是一个接口;ActiveX控件本质是一个COM组件,COM组件的客户端和服务器端本身有自己的通讯方式。
从这两点我们可以想到二者之间的几种通讯方式:我和我的同事曾争论ActiveX控件接口能否像一般C++的DLL那样在导出函数参数列表里设置一个回调函数指针那样实现回调,那时我认为是不行的。
现在我看了ActiveX控件接口的参数类型,更加坚定了我的看法。
其实从COM的初衷来看应该也是不行的,因为COM的初衷之一是提供一种跨语言的调用接口,而回调函数指针只对客户端是C++程序是有意义,对于VB、C#则无回调函数指针一说的。
三.实践检验现在我们编一个这样的小程序:在ActiveX控件上画直线,在画直线的同时把坐标传给客户端的视图,在客户端的视图区上依据传进来的坐标信息,绘制出相应的直线。
在动手之前我简要介绍我的思路:所谓基于COM的回调虚接口实现ActiveX控件和客户端程序的通讯,大致是这样的,就是在ActiveX工程的内部的idl文件定义一个虚接口,在客户端程序定义一个虚接口的派生类来实现回调函数,在客户端程序传递派生类对象指针给ActiveX控件,在控件内部调用这个虚接口的函数来激发客户端程序的派生类的对应的回调函数。
这里其实有一个关键问题,就是定义在idl文件中回调虚接口如何被ActiveX工程和客户端程序识别,而不至于成为未定义类型(说实话,这个问题折磨了我两个晚上,之所以这么麻烦,大概因为这个接口是定义在idl文件,而不是C++源文件中),下面我将介绍如何解决这个问题。
首先我们创建一个MFC ActiveX Control的工程:DataX,具体如下图:接着在idl文件添加回调接口。
这一步需要手动编辑idl文件。
首先实现使用GUIDGEN.EXE(该工具在$\Microsoft Visual Studio 9.0\Common7\Tools路径下,在VC6.0,VC 8.0都有这个工具)产生一个IID,生成时注意选择是注册表形式,具体如下图:然后在idl文件的开头下加入以下内容:view plaincopy to clipboardprint?import "oaidl.idl";import "ocidl.idl";[object,uuid(87C3DA69-C915-41f5-8142-D77816F22004), // 这个IID 可以用GUDIGEN.EXE 产生helpstring("ICallBack 接口"),pointer_default(unique)]interface ICallBack : IUnknown {[id(1),helpstring("回调接口,响应鼠标按下")] HRESULT FireLButtonDown([in] LONG x,LONG y);[id(2),helpstring("回调接口,响应鼠标移动")] HRESULT FireMouseMove([in] LONG x,LONG y);[id(3),helpstring("回调接口,响应鼠标按下")] HRESULT FireLButtonUp([in] LONG x,LONG y);};import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(87C3DA69-C915-41f5-8142-D77816F22004), // 这个IID 可以用GUDIGEN.EXE 产生helpstring("ICallBack 接口"), pointer_default(unique) ] interface ICallBack : IUnknown { [id(1),helpstring("回调接口,响应鼠标按下")] HRESULT FireLButtonDown([in] LONG x,LONG y); [id(2),helpstring("回调接口,响应鼠标移动")] HRESULT FireMouseMove([in] LONG x,LONG y); [id(3),helpstring("回调接口,响应鼠标按下")] HRESULT FireLButtonUp([in] LONG x,LONG y); };由于画图不是本文描述的重点,这里暂且略过。
下面我们开始在ActiveX控件上实现绘图和添加传递回调接口的函数。
这里所说的传递回调接口实现的功能是把客户端程序的回调接口派生类对象的指针传到ActiveX控件内部。
具体如下:这里介绍一下添加COM接口,首先在对应的接口选择:Add Method,如下图:然后开始填充返回类型、参数等信息:我发现必须选择下拉列表的参数类型,不选择的话就会出错:这时我们需要要SetCallBackPtr函数中的IUnknown全部替换为ICallBack。
为什么要进行替换?一方面ICallBack*类型才是我们真正要传递的指针类型;另一方面如果不进行替换,外部的客户端程序将不能识别ICallBack这个类型。
我发现在idl文件定义的类型,似乎要在library ***{}这一段出现过的类型外部才能识别,不过这个没有得到验证,有空得研究一个idl文件。
这里大致要替换的地方包括三处,控件窗口类中的头文件的声明、cpp 文件中的定义以及在idl文件中的声明。
这一步算是解决了回调接口ICallBack的外部识别问题。
现在我们在CDrawView定义一个ICallBack* m_pCallBack;的数据成员,以及它的赋值接口函数:view plaincopy to clipboardprint?void CDrawView::SetCallBack(ICallBack* pCallBack){if (NULL!=pCallBack){m_pCallBack = pCallBack;}}void CDrawView::SetCallBack(ICallBack* pCallBack) { if (NULL!=pCallBack) { m_pCallBack = pCallBack; } }这里经常会出现的一个错误是:use of undefined type 'ICallBack'。
这里的根源在于C++源码文件并不能识别idl文件中的类型,就是一个内部识别问题。
后来我发现其实编译所有COM工程都有一步就是将idl文件的内容翻译为C++能够识别的头文件。
所以你会发现编译后工程文件夹会多出一些头文件和C 文件,其中一个头文件的命令比较有意思,规律大致是工程名+idl.h。
这个头文件其实就是编译idl文件生成的。
因此要使用回调基类接口,就必须包含这个头文件。
我这个工程的是:DataXidl.h。
打开这个文件,可以从中看到COM的一些奥秘,里面有这样一段代码:view plaincopy to clipboardprint?ICallBack : public IUnknown{public:virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireLButtonDown(/* [in] */ LONG x,/* [in] */ LONG y) = 0;virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireMouseMove(/* [in] */ LONG x,/* [in] */ LONG y) = 0;virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireLButtonUp(/* [in] */ LONG x,/* [in] */ LONG y) = 0;};ICallBack : public IUnknown { public: virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireLButtonDown( /* [in] */ LONG x, /* [in] */ LONG y) = 0; virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireMouseMove( /* [in] */ LONG x, /* [in] */ LONG y) = 0; virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FireLButtonUp( /* [in] */ LONG x, /* [in] */ LONG y) = 0; };看来在编译过程中已经将idl接口的代码转换为C++代码了。
然后我们在控件窗口类里添加一个画图视图的指针:view plaincopy to clipboardprint?CDrawView *m_pView;CDrawView *m_pView;实现刚才添加的接口函数,把回调接口传给视图类:view plaincopy to clipboardprint?void CDataXCtrl::SetCallBackPtr(ICallBack* pCallBack){AFX_MANAGE_STATE(AfxGetStaticModuleState());// TODO: Add your dispatch handler code hereif (NULL!=m_pView){m_pView->SetCallBack(pCallBack);}}void CDataXCtrl::SetCallBackPtr(ICallBack* pCallBack){ AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your dispatch handler code here if (NULL!=m_pView) { m_pView->SetCallBack(pCallBack); } }4. 在派生类中实现派生类接口现在我们开始新建一个单文档程序:CallbackTest,VS 2005风格的。