从零开始学VC系列教程完整版

更新时间:2024-04-30 12:34:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

从零开始学VC系列教程 一.信息显示实验 题外话:第一次写教程,不知道该怎么开始.以前见过的教程可能都会介绍比较多的理论然后才开始讲实际操作,我想对于VC,理论讲得太多大家可能更糊涂,所以选择了这个方案,我们先一步步照着做,每一次只介绍一两个知识点,并且把理论放在后面说明,希望大家能喜欢这种方式,并对这种方式提出意见和建议,以便以后章节更适合大家的学习.

或许我写的还不能称之为教程,只是一些操作步骤及说明,通过这些练习,希望能使大家对VC有一个新的认识.VC的功能是十分强大的,但我们一般并不会用到所有的功能,就像大家熟悉的KeilC一样,其实Keil功能也是很多的,平时也没见谁把Keil的功能都用到了.基于此,我写的这个教程可能在VC专业人士看来比较简单.不是要班门弄斧,而是希望推行上位机技术,形成一个氛围让大家来学习交流,PC机与下位机结合毕竟也是发展的一个方向.望高手谅解小辈的不自量力.同时,我们结合单片机编程,让大家明白上位机控制方法及原理,当然这是今后章节的内容了. 本节内容:学会在文本框中显示文本,学会弹出式对话框使用. 学习目的:信息显示是人机交互的基础,同时,信息显示也为以后的程序调试打下基础.

1. 新建工程.打开VC6.0点击[文件]->[新建],弹出如下对话框.

在工程选项中选择MFC AppWizard[exe],选择好工程存入的位置,然后在工程名称中填入工程的名称,例如Eg01,填入Eg01后.VC会在我们选择的路径后自动加入一个以工程名命名的文件夹作为工程目录.完成按[确定]就会进入工程向导,出现以下的提示.

在这个我们选择[基于对话框]就行了.单文档及多文档方式会在以后详细介绍.这里也简要说明一下.①单文档.程序一次只能处理一个文档对象(文件).像写字板,记事本等.②多文档.程序一次可以处理多个对象(文件),像word之类的,可以同时打开多个文件.③基本对话框.程序一般用于处理一些比较小的,工具型的软件.像双龙的ISP下载软件, Easy 51Pro等都是基于对话框.一些不是很复杂的工业软件也通常可以用基于对话框的形式,这种方式的优点是所见即所得,一些控件可以像VB一样拖到工作区就行了.选好以后直接按[完成]就可以了.至于[下一步]的向导,这里我们先不管.然后会进入以下的画面.其中红色及绿色是我的标注,看不清图片可以下载图片放大.

选中静态文本框[TODO:在这里设置对话框控制],单击指标右键,在弹出的快捷菜单中选择[属性Properties]菜单项,弹出如下对话框

修改IDC_STATIC为IDC_FIRSTLABEL,标题可以写为”第一个应用程序”然后关闭这个对话框,就可以看到刚才的静态文本框内容变为”第一个应用程序”了.

在刚才的操作中,我们将静态文本框的ID改为了IDC_FIRSTLABEL,在VC中,ID是控件的标志,不能有相同的ID出现,但允许多个名为IDC_STATIC的ID号.所以,一般并不把文件名命为IDC_STATIC,除非以后我们不想在程序中改变这个控件的属性.有一些控制,例如GroupBox一般并不在程序中改变什么,所以不改变其ID号.ID是程序访问控件的标识,所以一个应用程序中不能有重复ID. 按下来我们要添加一个按钮.

用鼠标将控件条上的按钮拖到对话框上,可以看到对话框上多了一个按钮. 用上叙方法,改变按钮ID为IDC_BTN1,标题改为”显示”,这样就做好一个按钮了.下面我们为按钮添加代码.

双击按钮,会出现以下的提示框.

按[OK]为按钮添加响应函数,出面以下画面

void CEg01Dlg::OnBtn1() { // TODO: Add your control notification handler code here }

这一段就是刚才按钮的函数了.当然,现在还没有响应.现在我们添加一个事件,让这个按钮按下后上面的静态文本框的内容变为”串口号:COM1 波特率:57600”把上面的代码改为 void CEg01Dlg::OnBtn1() { // TODO: Add your control notification handler code here

SetDlgItemText(IDC_FIRSTLABEL,” 串口号:COM1 波特率:57600”); }

添加完成以后,按F7编译.如果编译通过,按F5运行,可以看到程序运行后的对话框

按下按钮,可以看到上面的静态文本框的内容改变了.那么恭喜你,完成我们这个例子的第一步操作了.

当然,我这里的对话框看起来没那么高,大家可以调一下高度.怎么退回到控件编辑状态呢?

首先,我们单击选项卡中的[ResorceView],现在大家只能看到[Reso…]看到IDD_EG01_DIALG了吧,这个其实也是一个ID,是我们对话框的ID,如果大家改一下对话框的ID,就可以看到这里的ID也变了.在VC中,所有的控件都认为是窗体,只是形式不同.双击IDD_EG01_DIALG就可以看到我们刚才的控制编辑状态了.双击[显示]按钮又可以回到代码状态. 刚才的例子很简单,却是我们以后会用得最多的.下面我们来分析一下代码 void CEg01Dlg::OnBtn1() { // TODO: Add your control notification handler code here SetDlgItemText (IDC_FIRSTLABEL,” 串口号:COM1 波特率:57600”); }

看看SetDlgItemText这个函数,大家就会明白了, IDC_FIRSTLABEL是我们给静态文本框分配的ID,后面的参数是要显示的内容.上面我们提到过,VC中的控件都认为是窗体,所以,对于所有的文本显示,我们都可以用这个函数来做,大家可以试着加入一个编辑框(Edit),同样可以使用用这个函数,只要ID号对了就可以了.VC对大小写敏感,大家要注意大小写. 下面我们用另一个方法来实现. 把代码改为

void CEg01Dlg::OnBtn1() { // TODO: Add your control notification handler code here CString a;

a=” 串口号:COM1 波特率:57600”; SetDlgItemText (IDC_FIRSTLABEL,a); }

然后按F7编译,无误则按F5运行.可以看到运行结果是一样的.

大家可以看到,我们把变量a定义为CString类型,这个类型我们在C中可能没有见过.CString 其实是VC中的一个类.这里我们要引入类的概念了.类跟C语言结构体很像,结构体可以有成员变量,但不能有成员函数,类不但可以有成员变量,还可以有成员函数,并且支持多种方法.在VC中,类用class标识.下面是一个类的定义,我们来分析一下. class CEg01Dlg : public CDialog {

public: CString GetPath(void); protected: int GetMax(int a,int b); public: int a; int b; };

这个类是我改过的,为了大家看得明白一点.首先,我们从这句class CEg01Dlg : public CDialog知道这个类名是CEg01Dlg,那么public后面的CDialog是什么意思呢?CDialog其实也是一个类,是VC中标准对话框类. public CDialog意思是我们定义的这个类CEg01Dlg从CDialog派生,也叫从CDialog继承,从继承这个词语大家就会明白CEg01Dlg不但可以有自身函数,而且还可以用到CDialog里的变量及函数,所以说是继承,就像我们说的继承财产一样,儿子不但可以有自己的钱,还有从老爸那里继承的产财,这些钱都能花.所以,我们也叫CDialog为父类(不

是爸类啊),把CEg01Dlg称为子类.当然,这是相对的.如果再定义一个类从CEg01Dlg派生,那么CEg01Dlg也就是父类,派生出来的类就是子类.这段可能有点难明白,大家可以慢慢体会.我们再回到CString上面来,这个类不是派生的,所以也没有父类了.用CString定义一个变量a,我们称为类变量,CString有很强大的功能,我们这里只用到一个功能,就是字符串,a可以是一个不定长度的字符串,所以我们可以给a赋一个任意的字符串而不用关心长度.当然,我们也可以用int StringLen=a.GetLength();来获得这个字符串的长度.从这句可以看到,GetLength()是类CString里的一个函数.大家可能又会关心一个问题,怎么把长度显示出来呢?我们把代码改为 void CEg01Dlg::OnBtn1() { // TODO: Add your control notification handler code here

CString a; a=\串口号:COM1 波特率:57600\ SetDlgItemText (IDC_FIRSTLABEL,a); a.Format(\字符串的长度:%d\ MessageBox(a); }

运行一下,效果如下

这里我们用到了类Cstring的另一个成员函数Format();这个函数用起来跟C语言里的Printf()很像,我就不多说明了.格式化后的字符串还是存放在a中,在这里,我们还用到了一个新的函数MessageBox();我们只是用了这个函数最简单的用法,显示一个字符串.MessageBox用于弹出一个提示对话框.查查MSDN就知道,函数原型是

int MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK ); 在VC里面,函数可以有默认值,例如LPCTSTR lpszCaption = NULL, UINT nType = MB_OK变量lpszCaption的默认值是NULL, nType的默认值是MB_OK,这些有默认值的变量我们可以不传值,所以这个函数使用时,最简单的用法就是传lpszText就可以了.如果我们要显示一个固定的字串,可以这样调用MessageBox(“大家好”);是不是很简单啊?

这一章就写到这里了,一些问题大家可以提.未尽知识点,会在以后再详细介绍.

从零开始学VC系列教程 二. 对话框及常用控件实验

恭喜你,进入VC学习的第二节了.这一节是人机交互的基础.所谓人机交互,说通俗点就是与机器对话.然而我们现在的技术还不能像科幻片里一样与机器人直接说话就行了.所以,我们的操作意图还得通过文本输入,命令按钮等等来实现.

本节内容:学会对话框调用及一些常用控件的使用方法. 学习目的:学习人机交互,为软件开发提供界面基础.

1. 新建工程.参考第一节的方法新建一个工程,名字为Eg02完成后如下图

细心的朋友一定会发现.新建的工程里还有一个对话框,ID名是IDD_ABOUTBOX这个是做什么用的呢?我们用到的软件都会有一个版权声明.通过第一章的学习,大家应该知道怎么观看这个IDD_ABOUTBOX对话框了吧.没错!双击IDD_ABOUTBOX就可以了.我们会看到如下的一个对话框

这就是我们这个程序的关于对话框,一般用于版权声明及版本号标识.大家看到的这个对话框里有两个静态文本框和一个图像框(Picture),静态文本框我们在前一节已经介绍过了.大家可以修改一下版权所有这一行,填什么都可以,签个大名也行.完成以后你一定想看看效果,这个对话框怎么打开呢?其实VC已经为我们做好了.先按F7编译,然后按F5运行.大家可以看到

程序运行了.

单击应用程序图标,就会出现一个菜单,选最后一个[关于Eg02],关于对话框就弹出来了.

当然,这是系统为我们做好的.自己怎么在程序中调用这个对话框呢?为了演示,首先参考第一节的内容添加一个按钮,然后把按钮的ID改为IDC_BTN_ABOUTME,把标题,也就是Caption改为[关于].最终效果如下

下面我们为按钮添加代码.相信大家一定还记得怎么进入代码吧..对了,双击[关于]按钮,在弹出的对话框中点[确定]就可以了.为了让大家更好的理解下面的操作,我们先要解释一下关于对话框的类.VC向导会为关于对话框建立一个类,大家看看下面的图

单击标签ClassView(这里显示的是[Class…])就可以看到Eg02这个应用程序的类.第一个CAboutDlg就是关于对话框的类.CEg02Dlg对应IDD_EG02_DIALOG.中间的Ceg02App是应用程序的基础类.所以,如果要对关于对话框进行操作,就要用到类CAboutDlg,因为与此有关的函数及变量都封装在CAboutDlg中.看到这里大家可能又糊涂了,没关系,在以后的教程中,通过一些练习大家就会慢慢领会到的.这里还是先为[关于]按钮添加代码. void CEg02Dlg::OnBtnAboutme() { // TODO: Add your control notification handler code here }

上面是VC为[关于]按钮添加的响应函数.我们添加代码成以下所示 void CEg02Dlg::OnBtnAboutme() { // TODO: Add your control notification handler code here CAboutDlg ADlg; ADlg.DoModal(); }

一共有两句,第一句是CAboutDlg ADlg;作用是定义一个变量Adlg.第二句是ADlg.DoModal();功能是调用类CAboutDlg里的一个函数DoModal();这个函数在MSDN里的解释是Call this member function to invoke the modal dialog box and return the dialog-box result when done. This member function handles all interaction with the user while the dialog box is active. This is what makes the dialog box modal; that is, the user cannot interact with other windows until the dialog box is closed.一般我们用于显示一个对话框.其实大家看看CAboutDlg这个类下面,只有两个函数

DoModal()这个函数并不在这个里面.第一章我们提到过类的派生和继承.其实CAboutDlg这

个类是派生于CDialog类,DoModal()这个函数是CDialog的成员函数,由于CAboutDlg是继承父类CDialog的,所以CDialog里的函数在CAboutDlg中也可以使用. 下面我们来说说几个常用控件的使用.

首先在IDD_EG02_DIALOG对话框中加入一个Edit(编辑框)控件.Edit一般用于输入输出数据文本.相当于VB里的TextBox.加入Edit控件后,编辑其属性为

然后,我们再加一个按钮(PushButton),并编辑其属性为

接下来,我们先说一下要实现的效果.很简单,在编辑框里输入一个文本,然后按显示,就把文本显示在静态文本框中.所以,这里要把静态文本编辑框的ID改为IDC_DISPLABEL 下面我们为[显示]按钮添加代码 void CEg02Dlg::OnBtnShow()

{ // TODO: Add your control notification handler code here CString a; GetDlgItemText(IDC_EDIT_INPUT,a); SetDlgItemText(IDC_DISPLABEL,a); }

其实不复杂,也只有三句,第一句定义一个CString类变量a 我们来说说GetDlgItemText这个函数吧.查查MSDN就知道函数原型了.

int GetDlgItemText( int nID, LPTSTR lpStr, int nMaxCount ) const; int GetDlgItemText( int nID, CString& rString ) const;

大家看看就觉得奇怪了,怎么有两个原型啊?并且一个是传两个参数,另一个是传三个参数.在VC里面,同一个类下是可以存在多个同名函数的,具体调用哪个函数要看参数的不同.在这里我们传入了两个参数,所以VC会调用int GetDlgItemText( int nID, CString& rString ) const;这个函数.第一个函数是控件的ID号,第二个是字串.第二个传了地址,所以我们在下一句中用的a已经是获得IDC_EDIT_INPUT的文本了.运行效果如下

下面介绍一下进度条的使用以及定时器的使用.

我们要实现的效果是进度从0到满格,然后再从0到满格,依次循环.每跳一格间隔500ms,这个时间我们用定时器来实现.

首先从控件条里拖出一个进程条到对话框,修改属性如下

然后我们要介绍一下VC的定时器.VC里面使用定时器有多种方式,我们先介绍一种作为抛

砖引玉

首先添加一个Windows消息处理器.消息这个词语可能很陌生,我们会在后面很多次说明.这里先照图做

在类管理器里选中Ceg02Dlg这个类,然后点右键,就会弹出一个菜单,选择[Add Windows Message Handler…],接下来会弹出另一个菜单

从零开始学VC系列教程之三串口通信与自定义消息

课程之前:首先请大家确认一下前面两章都已经熟悉,因为一些前面已经介绍过的基础操作在这里将不再详细说明,如果有什么问题,可以翻看一下前面的两章或者留言提问.本章是基于PC机与单片机的串口通信,用到了一个动态链接库和一个自定义消息.

学习目标:掌握VC下串口编程式的方法,掌握动态库的静态调用及自定义消息. 课程详解:

1. 参照第一章新建一个基于对话框的Vc工程,名称定义为Eg03.

图片01 (原文件名:001.jpg)

2. 工程建立后,在对话框上加入一个组合框(ComboBox),ID号改为IDC_COMPORT 用于选择使用PC机上的哪一个串口.

在组合框后加入一个按钮,标题(Caption)改为”打开”,ID号改为IDC_BTN_PORTOPEN 用于打开串口,开始通信.

下面加入一个编程框(EDIT),ID号改为IDC_EDIT_RECMSG 用于显示接收到的数据.

在编程框下面再添加一个编程框(EDIT),.ID号改为IDC_EDIT_SEDMSG 用于添加要发送的数据. 然后在这个编程框后加入一个按钮.标题(Caption)为”发送”,ID号为IDC_BTN_SEND 最后调整位置及大小如下

图片02 (原文件名:002.jpg)

3. 添加Lib文件.这里介绍的串口通信用的不是VC自带的MSCOMM控件.原因有两个,一是顺便介绍一下动态库和自定义消息的用法.二是MSCOMM控件使用时数据类型转换比较复杂,并且使用也不是很方便.当然,以后也会介绍多线程串口通信给大家,我们会在后面开设一章多线程编程方法,并在那里详细介绍基于多线程的串口通信.这里使用一个动态库,其实也是别人封装好了的多线程通信,名字是Pcomm.在工程下载中,给出了三个文件,分别是Pcomm.h, Pcomm.lib, Pcomm.dll,现在请大家把这三个文件拷到工程目录,也就是Eg03这个文件夹中.至于什么是动态库,这三个文件倒底是什么作用,我们做完这个例程后再解释,现在还是先按步就搬,营造一个感性认识.下面添加Lib文件到工程.首先点击[工程](Project),选择下拉式菜单中的[设置](ProjectSettings)

图片03 (原文件名:003.jpg)

然后会弹出一个对话框,在标签卡中选择[连接]

图片04 (原文件名:004.jpg)

然后在[对象/模块]中添加Pcomm.lib,完成后如上面所示,单击[确定]退出.这样,我们就为Pcomm.dll这个动态库添加了静态链接,同时,这也就是动态库的静态链接方法,当然,还有一步就是包含Pcomm.h这个头文件.在刚才的步骤中,我们将Pcomm.Lib添加到工程,这个文件主要用于指定Pcomm.dll中各个功能函数的入口及地址,Pcomm.Lib就像一个地图指出目的地的路标,而真正的函数是在Pcomm.Dll中的.当然,为了方便调用,我们还要得到Pcomm.Dll中的函数声明,这些函数声明就在Pcomm.h这个头文件中,所以,大家打开Pcomm.h这个文件,只有函数及变量定义,并没有函数过程.下面我们来添加这个文件.

4. 打开左边的[工作空间](WorkSpace)中选择标签[ClassView](这里大家只能看到[Class…] 这一步前两章已经详细介绍过了,大家可以参考.),然后双击[OnInitDialog]就可以打开代码窗口了,在原有头文件包含后面加入串口头文件引用.输入#include ”Pcomm.h”就可以了,完成后如下图

图片05 (原文件名:005.jpg)

这一步我们加入了动态库的函数声明,后面就可以直接使用Pcomm.Dll中的函数了.下面我们来添加事件响应.

单击工作空间中间的标签[ResourceView](大家看到的是[Reso…]),再双击[IDD_EG03_DIALOG]就可以回到控件编辑状态.

图片06 (原文件名:006.jpg)

首先为[打开]按钮添加代码.双击[打开]按钮,然后在按钮事件中添加.完成后如下 void CEg03Dlg::OnBtnPortopen() {

// TODO: Add your control notification handler code here Port=GetDlgItemInt(IDC_COMPORT); if(SIO_OK!=sio_open(Port)) {

MessageBox(\串口打开错误\ } else {

sio_ioctl(Port,BaudRate,DataBits | StopBits | Parity); sio_cnt_irq(Port,CntIrq,1); } }

其中, sio开头的变量及函数都是Pcomm中的,我们来解释一下. sio_open是打开某个串口,传入的参数是串口号,如果我们要打开COM1,可以用sio_open(1),返回的参数在Pcomm里面定义了,如果返回SIO_OK就表示串口打开没有问题,否则,就是打开串口失败. sio_ioctl用于设置通信的相关信息,Port中串口号, BaudRate是波特率, DataBits是数据位数, StopBits是停止位数, Parity是校验. sio_cnt_irq用于设定中断回调函数.中断回调函数其实前面的Timer定时器里也提到过,在这里,我们设定一个中断回调函数,每当串口接收到指定字节数据时,系统就会自动调用这个中断回调函数,就像单片机中的串口中断函数一样.这里的回调函数名是CntIrq,我们将在后面定义.细心的朋友一定会发现, BaudRate,DataBits | StopBits | Parity这些都没定义过啊?所以要定义一下这些变量.参照前面的加入文件的方法,在头文件引用下一行加入以下宏定义 #define BaudRate B57600 //波特率 #define DataBits BIT_8 //数据位 #define Parity P_NONE //效验位 #define StopBits STOP_1 //停止位 完成后如图

图片07 (原文件名:007.jpg)

下面我们要定义sio_cnt_irq 一般来说,中断回调函数并不写在类里面,我们添加后如下

图片08 (原文件名:008.jpg)

///////////////////////////串口中断回调函数////////////////////////////////// VOID CALLBACK CntIrq(int port) {

if(::AfxGetMainWnd()) {

if(::AfxGetMainWnd()->m_hWnd) {

::PostMessage(::AfxGetMainWnd()->m_hWnd,WM_PCOMM,0,0); } } }

学习过前面两章我们知道,这个中断回调函数只做了一件事情,就是发送一个WM_PCOMM消息到窗口. AfxG

etMainWnd()这个函数用于获得主窗口,返回类型是CWnd的指针,主窗体句柄我们是不知道的,用AfxGetMainWnd()->m_hWnd来获得.这样,消息就可到发到主窗体了.有了这个函数,每当串口接收了数据,就会发一个消息到窗体.WM_PCOMM这个消息不是系统的,也不是Pcomm本身的,它是我们自定义的一个消息,怎么定义呢?我们在前面说的宏定义后面再加入一个定义 #define WM_PCOMM WM_USER+500 //自定义消息

图片09 (原文件名:009.jpg)

WM_USER是一个消息地址,这个是系统定义好的,从这个地址开始可以自定义消息, 我们把WM_PCOMM定义为WM_USER+500也就是说,我们定义的这个消息位于WM_USER后面的偏移500,当然,这只是个地址,与执行先后无关.这个偏移大家可以自己随便设,不与别的自定义消息冲突就行了.消息定义好了还要为消息添加关联.首先要定义一个消息响应函数,名字随便,我们这里取名为OnPcomm(),双击[工作空间]中的Ceg03Dlg就可以打开窗体的文头件,这里定义了Ceg03Dlg 这个类,我们在类定义里面添加一个成员函数. afx_msg void OnPcomm(); //这里是我们自定义的消息响应函数 完成后如图

此外,这里还顺便定义了一个变量,就是前面我们用到的Port 用于记录打开的串口号. public:

int Port;

图片10 (原文件名:010.jpg)

位置就放在DECLARE_MESSAGE_MAP() 的前面.函数声明就可以了.现在来添加函数体.双击[OnInitDialog( )],然后在该文件的最后添加一个函数.写成如下形式. void CEg03Dlg::OnPcomm() {

char buf[200];

int end=sio_read(Port,buf,100); if(end) {

CString a,b=\

GetDlgItemText(IDC_EDIT_RECMSG,b); buf[end]=0;

for(int i=0;i

a.Format(\\char)buf[i]);

b+=a; }

SetDlgItemText(IDC_EDIT_RECMSG,b); } }

这一段其实不难理解,因为前面两章已经介绍过多次了. sio_read是Pcomm的函数,从串口读取数据用. GetDlgItemText(IDC_EDIT_RECMSG,b);用于读出以前的历史记录,这样每次发上来的数据都放在后面连接起来.end是返回的收到的数据个数.用十六进制形式显示出来.

图片11 (原文件名:011.jpg)

做完了上面一些,我们差一步就可以收到数据了.因为数据发上来后,底层响应,并调用了回调函数,在回调

函数里面,发出一个消息WM_PCOMM 虽然我们在后面定义了一个Pcomm()函数专门用于响应这个消息,但这个自定义消息并不是自动连接到Pcomm()的,需要添加一个消息影射才能使WM_PCOMM消息影射到Pcomm()函数.双击左边[工作空间](WorkSpace)中的 DoDataExchange(CDataExchange* pDX)

DoDataExchange这个函数的下面一般都这是用于定义消息影射的,将下面一段程序增加一行,完成后如下. BEGIN_MESSAGE_MAP(CEg03Dlg, CDialog) //{{AFX_MSG_MAP(CEg03Dlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_BTN_PORTOPEN, OnBtnPortopen) //}}AFX_MSG_MAP

ON_MESSAGE(WM_PCOMM,OnPcomm) //这里是消息影射 END_MESSAGE_MAP()

图片12 (原文件名:012.jpg)

完成以后就可以按F7编译一下,如果无误就可以接收到数据了.运行后,选择正确的串口号,按一下[打开]

按钮就可以了.

现在我们再来看看怎么发送数据

回到控件编辑状态,双击[发送]按钮,为该按钮添加代码. void CEg03Dlg::OnBtnSend() {

// TODO: Add your control notification handler code here CString a;

unsigned char b=0;

GetDlgItemText(IDC_EDIT_SEDMSG,a); //取得编辑框内所有文本 a.MakeUpper();//全部转换为大写

for(unsigned char i=0;i

if(a.GetAt(i)>='A' && a.GetAt(i)<='Z') b=(a.GetAt(i)-55)*16; //判断填入的是字母还是数字,并把字符转换成十六进制数

else if(a.GetAt(i)>='0' && a.GetAt(i)<='9') b=(a.GetAt(i)-0x30)*16;

if(a.GetAt(i+1)>='A' && a.GetAt(i+1)<='Z') b+=(a.GetAt(i+1)-55);

else if(a.GetAt(i+1)>='0' && a.GetAt(i+1)<='9') b+=(a.GetAt(i+1)-0x30);

sio_putch(Port,b); //发送 } }

这一段主要是把获得的编辑框内的字串转换成十六进制的数字,转换一个发送一个.Cstring类型以前已经提起来,应该际上是一个类, MakeUpper是一个成员函数,用于将字符串全部转成大写.GetAt也是一个成员函数,可以取出字符串中任意下标的字符. sio_putch用于发送一个字符.

图片13 (原文件名:013.jpg)

填写待发送数据的时候要注意,每两位中间空格一下.填入的是十六进制数据.

下面再来总结一下静态方式调用动态库的方法. 1. 拷贝Lib,H头文件到工程路径 2. 在工程->设置中加入Lib模块. 3. 加入.h头文件,用于函数声明 4. 将Dll文件拷入到工程目标路径中 总结一下自定义消息方法:

1. 用#define WM_NAME WM_USER+1 定义一个自定义消息,名称随便.一般用WM开头.WM_USER+1中的1那个数字是自己定的,一个消息就无所谓了,喜欢多少都行,如果要定义很多个消息,不要冲突就行了

2. 在类定义里面声明一个消息响应函数,写成 afx_msg void FunctionName();格式. 3. 添加一个消息影射ON_MESSAGE(WM_NAME, FunctionName)注意这句后面是没有分号的. 4. 写好FunctionName的函数. 很简单的四步就行了.

从零开始学VC系列教程之 四.并口控制与类的使用

学习目标:掌握VC下并口程序的方法及类的使用. 课程详解:

参照第一章新建一个基于对话框的Vc工程,名称定义为Eg04.

图01 (原文件名:01.JPG)

类型选基于对话框.

在本例中,我们要用到一些资源,现列出如下 WinIo.sys

WinIo.dll 这是一个动态库,与WinIo.sys完成同并口的连接.

WinIo.lib 这是为静态调用提供的引入库文件.虽然引入库文件和静态库文件都是以Lib为扩展名的,但实际上有本质的区别.

WinIo.h 这是IO操作的头文件.

ParallelPort.cpp 这是一个并口操作类,用于同WinIo接口,并定义了相关的操作函数.虽然这个类用于同WinIo的操作接口,但这个类并不是从WinIO派生的,只是一个独立的自定义类.至于类的自定义,以前我们也提到过.

ParallelPort.h 这是并口类的头文件.

这几个文件是可以从网上下载到的,并不是我做的,所以这个动态库大家就不用问我要源码了,因为我也没有.

首先,把WinIo.lib WinIo.h ParallelPort.cpp ParallelPort.h拷贝到工程目录中,后面马上就要用到.再把WinIo.Dll WinIo.sys拷贝到工程目录的Debug目录中,以后工程发布后,这两个文件要跟随工程一起.

下面添加引入库到系统中,点击[工程]->[设置]在弹出的对话框中选择[连接]标签,然后在[对象/库模块]中加入WinIo.lib完成后如下图.

图02 (原文件名:02.JPG)

然后加入并口操作类的头文件.一般来说,网上可以下载到的源码都是以类的形式给出的,VC的好处也在于可以把一个操作封装成类,以便在不同的工程中调用.如图,双击类管理器中的Ceg04Dlg在弹出的文件中加入#include \//添加并口类头文件

图03 (原文件名:03.JPG)

同时,还要定义一个类变量,用于并口类的操作. 在刚打开的类定义文件中找到CEg04Dlg类,并加入一个类变量m_Port,完成后如下图所示

图04 (原文件名:04.JPG)

为了操行方便,把并口操作类也加入到工程中,点击[FileView]标签,标签位置在类管理类下面,见上图中的[FileVi…]然后在[Source Files]中加入ParallelPort.cpp在[Header Files]中加入ParallelPort.h这样,就可以在类管理中看到我们所用到的并口操作类了,同时也可以方便的查阅类函及成员变量. 下面在界面中加入六个按钮和两个文本编辑框,方法前面已经介绍多次.完成后如下图

图05 (原文件名:05.JPG)

其中,各控件ID如下

上面的编辑框 IDC_EDIT_READ 用于显示收到的数据 下面的编辑框 IDC_EDIT_WRITE 用于填写要发送的数据

读数据口 IDC_BTN_DREAD 用于读取并口数据总线 写数据口 IDC_BTN_DWRITE 用于写并口数据口数据

读控制口 IDC_BTN_CREAD 用于读取并口控制总线 写控制口 IDC_BTN_CWRITE 用于写并口控制口数据 读状态口 IDC_BTN_SREAD 用于读并口状态总线

并口流水灯 IDC_BTN_LED 用于在数据线上输出流水灯效果

先要介绍一下并口,以便理解接下来的操作是什么意思.以下一些关于并口的介绍,摘自互联网.

并口SPP模式寄存器定义 数据寄存器(基地址)

位 引脚:D-sub 源 是否在连接器处倒相 0 2 数据位0 C 否 2

1 3 数据位1 C 否 3

2 4 数据位2 C 否 4

3 5 数据位3 C 否 5

4 6 数据位4 C 否 6

5 7 数据位5 C 否 7

6 8 数据位6 C 否 8

7 9 数据位7 C 否 9

注:控制寄存器的第5位控制数据位是否能够输出。

状态寄存器(基地址+1)

位 引脚:D-sub 源 是否在连接器处倒相 3 15 nError 设 否 32

4 13 Select 设 否 13

5 12 Paper Out 设 否 12

6 10 nAck 设 否 10

7 11 Busy 信号名 信号 引脚:Centronics P P P P P P P P信号名 信号 引脚:Centronics 外 外 外 外 外

设 是 11 注:1,2位未定义。

控制寄存器(基地址+2)

位 引脚:D-sub 信号名 信号源 是否在连接器处倒相 引脚:Centronics 0 1 nStrobe PC 是 1

1 14 nAutoLF PC 是 14

2 16 nInit PC 否 31

3 17 nSelectIn PC 是 36

注: 连接器中没有提供的附加位:

4:4:中断启用,此位为1时,IRQ从nAck送往系统的中断控制器;为0时,IRQ不送往中断控制器。 5:5:双向控制端口的方向控制位,此位为0时,输出启动;为1时,不能输出;控制端口可以读取外部逻辑电平。 6、7:未定义。

学过单片机或相关知识的应该可以看懂表格中的意思了,上面罗列的是除去电源及地线后可用到的IO口,数据口8位,由状态寄存器第五位决定能否输出,状态口共5位,控制口共4位.一般我们只用到数据口来传输数据.一般来说,并口基地址是0x378,也就是数据寄存器的地址,在并口类中默认.明白了这些以后,就可以对并口进行相应的操作了.

接下来要在程序初始化时初始化并口,在前面的操作中,定义了一个类变量m_Port,这个类变量在后面我们将多次用到.首先展开类管理器中的CEg04Dlg双击OnInitDialog()在窗口初始化中加入以下代码. //在这里初始化并口

if(m_Port.InitPort()==TRUE) {

SetDlgItemText(IDC_EDIT_READ,\并口初始化成功,并口地址:0x378\

} else {

SetDlgItemText(IDC_EDIT_READ,\并口初始化失败!\ } 完成后如下图所示

本文来源:https://www.bwwdw.com/article/oong.html

Top