VCMFC编写串口调试助手文档格式.docx
《VCMFC编写串口调试助手文档格式.docx》由会员分享,可在线阅读,更多相关《VCMFC编写串口调试助手文档格式.docx(48页珍藏版)》请在冰豆网上搜索。
在打开按钮旁边加入自绘的打开和关闭图标:
先加入工具条中的Picture,然后选中右键看属性,并如图将Image选为默认的IDI_ICON_CLOSE。
如下图
5.基本设置
下面对各个按钮及编辑框设置进行描述
右键串口对应的ComboBox,ID设置为IDC_COMLIST,Type设置为DropList,Sort不选择(我系统是WIN764位,不选中反而自动排序,至于XP得试试看了,以下的选择相同)。
右键波特率对应的ComboBox,ID设置为IDC_BAUD,Type及Sort同上。
右键数据位对应的ComboBox,ID设置为IDC_BDATA,Type及Sort同上。
右键停止位对应的ComboBox,ID设置为IDC_BSTOP,Type及Sort同上。
右键校验位对应的ComboBox,ID设置为IDC_CAL,Type及Sort同上。
每个下拉框要点击右边的小箭头,然后将其拉长,不然显示不出内容。
接收EDIT框ID设置为IDC_EDIT_RX。
发送EDIT框ID设置为IDC_EDIT_TX。
自动发送时间间隔的EDIT框ID设置为IDC_EDIT_TIMER。
选择文件后面的EDIT框ID设置为IDC_EDIT_FILEPATH。
接收区的十六进制显示的CheckBox复选框ID设置为IDC_CHECK_HEXRX。
发送区的十六进制发送的CheckBox复选框ID设置为IDC_CHECK_HEXTX。
按钮“打开串口”ID设置为IDC_COMCONTROL。
按钮“清空显示区”ID设置为IDC_BTN_CLRRX。
按钮“手动发送”ID设置为IDC_BTN_HANDSEND。
按钮“清空发送区”ID设置为IDC_BTN_CLRTX。
按钮“自动发送”ID设置为IDC_BTN_AUTOSEND。
按钮“选择文件”ID设置为IDC_BTN_SELCTFILE。
按钮“发送文件”ID设置为IDC_BTN_SENDFILE。
6.开始写代码
6.1.基本思路:
因为串口通信部分代码我可能用在以后的单片机上位机上,因此考虑单独形成CPP和H文件,定义为comm.cpp和comm.h。
在comm.cpp中编写串口创建、打开、关闭以及串口监听线程(用于自动接收)的代码,同时加入进制转换或显示的函数,这些在comm.h文件中申明,在主对话框中包含comm.h即可。
想修改按钮样式,在网上搜了一圈,结果不轻松,最后确定创建新类来实现。
6.2.创建自定义按钮类:
View->
ClassWizard选择AddClass->
New,名字MyButton,基类选择CButton。
在头文件MyButton.h中加入以下变量和函数定义:
private:
intm_Style;
//按钮形状(0-正常,1-当前,2-按下,3-锁定)
boolb_InRect;
//鼠标进入标志
CStringm_strText;
//按钮文字
COLORREFm_ForeColor;
//文本颜色
COLORREFm_MouseInColor;
//鼠标进入时文本颜色
COLORREFm_BackColor;
//背景颜色
COLORREFm_LockForeColor;
//锁定按钮的文字颜色
CRectm_ButRect;
//按钮尺寸
CFont*p_Font;
//字体
voidDrawButton(CDC*pDC);
//画正常按钮
//接口函数
public:
MyButton();
voidSetText(CStringstr);
//设置文字
voidSetForeColor(COLORREFcolor);
//设置文本颜色
voidSetBkColor(COLORREFcolor);
//设置背景颜色
voidSetTextFont(intFontHight,LPCTSTRFontName);
//设置字体
在MyButton.cpp的构造函数中初始化变量:
m_Style=1;
//m_Style=0;
//按钮形状风格
b_InRect=false;
m_strText=_T("
"
);
//按钮文字(使用默认文字)
m_ForeColor=RGB(0,0,0);
//文字颜色(黑色)
m_MouseInColor=RGB(0,0,255);
//鼠标进入时文字颜色(蓝色)
m_BackColor=RGB(230,230,230);
//m_BackColor=RGB(243,243,243);
//背景色(灰白色)
m_LockForeColor=GetSysColor(COLOR_GRAYTEXT);
p_Font=NULL;
//字体指针
用ClassWizard添加下列消息函数:
PreSubclassWindow();
DrawItem();
onMouseMove();
OnLButtonDown();
OnLButtonUp();
在各函数内加入代码:
voidMyButton:
:
PreSubclassWindow()
{
//TODO:
Addyourspecializedcodehereand/orcallthebaseclass
ModifyStyle(0,BS_OWNERDRAW);
//设置按钮属性为自画式
//PreSubclassWindow()在按钮创建前自动执行,所以我们可以在其中做一些初始工作。
//这里只做了一项工作,就是为按钮设置属性为“自绘”式,这样,用户在添加按钮后,就不需设置“Ownerdraw”属性了。
CButton:
}
DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct)
Addyourcodetodrawthespecifieditem
CDC*pDC=CDC:
FromHandle(lpDrawItemStruct->
hDC);
m_ButRect=lpDrawItemStruct->
rcItem;
//获取按钮尺寸
if(m_strText.IsEmpty())
GetWindowText(m_strText);
//获取按钮文本
intnSavedDC=pDC->
SaveDC();
VERIFY(pDC);
DrawButton(pDC);
//绘制按钮
pDC->
RestoreDC(nSavedDC);
//DrawItem()函数是一个关键函数,按钮的绘制工作就在这里进行,它的作用相当于对话框中的OnPaint()函数和视图中的OnDraw()函数。
//这里我做了三项工作:
获取按钮尺寸、获取按钮文本、绘制按钮。
其中绘制工作在自定义函数DrawButton()中完成。
以下就是绘制过程:
DrawButton(CDC*pDC)
//调整状态
if(m_Style==3)m_Style=0;
if(GetStyle()&
WS_DISABLED)
m_Style=3;
//禁止状态
//根据状态调整边框颜色和文字颜色
COLORREFbColor,fColor;
//bColor为边框颜色,fColor为文字颜色
switch(m_Style)
{
case0:
bColor=RGB(192,192,192);
fColor=m_ForeColor;
break;
//正常按钮
case1:
bColor=RGB(255,255,255);
//鼠标进入时按钮
case2:
fColor=m_MouseInColor;
//按下的按钮
case3:
bColor=m_BackColor;
fColor=m_LockForeColor;
//锁定的按钮
}
//绘制按钮背景
CBrushBrush;
Brush.CreateSolidBrush(m_BackColor);
//背景刷
SelectObject(&
Brush);
CPenPen;
Pen.CreatePen(PS_SOLID,3,bColor);
Pen);
RoundRect(&
m_ButRect,CPoint(10,10));
//画圆角矩形
//绘制按钮按下时的边框
if(m_Style!
=2)
CRectRect;
Rect.SetRect(m_ButRect.left+1,m_ButRect.top+1,m_ButRect.right,m_ButRect.bottom);
DrawEdge(&
Rect,BDR_RAISEDINNER,BF_RECT);
//画边框
//绘制按钮文字
SetTextColor(fColor);
//画文字
SetBkMode(TRANSPARENT);
DrawText(m_strText,&
m_ButRect,DT_SINGLELINE|DT_CENTER
|DT_VCENTER|DT_END_ELLIPSIS);
//绘制拥有焦点按钮的虚线框
if(GetFocus()==this)
Rect.SetRect(m_ButRect.left+3,m_ButRect.top+2,m_ButRect.right-3,m_ButRect.bottom-2);
DrawFocusRect(&
Rect);
//画拥有焦点的虚线框
}
//变量m_Style表征当前按钮状态,它的取值为:
0-正常,1-当前,2-按下,3-锁定。
不同状态下按钮的边框颜色和文字颜色有所不同。
//m_Style的值在鼠标响应函数中进行修改。
//绘制工作主要利用CDC类的绘图函数完成,主要注意在m_Style不同取值下表现出来的差别。
OnLButtonDown(UINTnFlags,CPointpoint)
Addyourmessagehandlercodehereand/orcalldefault
m_Style=2;
Invalidate();
//重绘按钮
OnLButtonDown(nFlags,point);
//OnLButtonDown()函数是单击鼠标左键时的消息函数。
这里只是重新绘制按钮,具体的单击响应应该在拥有按钮的对话框或视图中进行。
OnMouseMove(UINTnFlags,CPointpoint)
if(!
b_InRect||GetCapture()!
=this)//鼠标进入按钮
b_InRect=true;
//设置进入标志
SetCapture();
//捕获鼠标
//m_Style=1;
//设置按钮状态
else
if(!
m_ButRect.PtInRect(point))//鼠标离开按钮
//清除进入标志
ReleaseCapture();
//释放捕获的鼠标
OnMouseMove(nFlags,point);
//onMouseMove()函数是鼠标移动消息函数,用于判定当前鼠标指针是否在按钮上。
b_InRect是个标志,为true表示鼠标指针进入了按钮区域,
//此时要捕获鼠标,让鼠标命令传送给按钮。
当鼠标指针离开按钮时,要清除b_InRect标志,并且释放捕获的鼠标,让其它窗口可以接收鼠标命令。
//Invalidate()函数用于更新按钮,它会自动调用DrawItem()函数重新绘制按钮。
//设置条件的目的是仅在鼠标指针进入按钮和离开按钮时更新按钮,这样可以防止鼠标在按钮上移动时发生闪烁。
OnLButtonUp(UINTnFlags,CPointpoint)
OnLButtonUp(nFlags,point);
//OnLButtonUp()函数是单击鼠标左键后弹起时的消息函数。
这里也只是重绘按钮,这样能使按钮在按下和弹起时有所不同,使按钮看上去有动态效果。
//接口函数是用CMyButton类定义的按钮修改颜色、字体和按钮文字的接口,由以下函数组成:
//设置按钮文本
SetText(CStringstr)
SetWindowText(str);
//设置文本颜色
SetForeColor(COLORREFcolor)
m_ForeColor=color;
//设置背景颜色
SetBkColor(COLORREFcolor)
m_BackColor=color;
//设置字体(字体高度、字体名)
SetTextFont(intFontHight,LPCTSTRFontName)
if(p_Font)deletep_Font;
//删除旧字体
p_Font=newCFont;
p_Font->
CreatePointFont(FontHight,FontName);
//创建新字体
SetFont(p_Font);
///由于新字体由new生成,必须显式回收,这项工作可以在CMyButton类的析构函数中进行:
/*CMyButton:
~CMyButton()
//删除字体
*/
//这样一个可设置颜色、字体的按钮类就做好了。
使用时,先在对话框中放置好按钮,再用ClassWizard为按钮添加控制变量,
//并且将变量的类型设置为CMyButton。
之后,可以用该变量调用接口函数设置按钮颜色和字体。
OK,自定义按钮完成。
6.3.实现过程及代码:
现在可以对按钮,EDIT框等控件添加变量,文字描述麻烦,上图。
comm.cpp编写内容如下
#include"
stdafx.h"
commassist.h"
commassistDlg.h"
comm.h"
charConvertHexChar(charch);
HANDLEhCom;
//串口句柄
CStringstrcomname;
//串口名,如"
COM1"
boolComIsOK;
//串口打开状态标识,为真表示已打开,否则未打开
//============自动寻找串口函数=================================
//函数功能:
通过扫描注册表来找出当前所有物理串口
//输入参数:
无
//返回类型:
//说明:
若搜索成功,则每搜到一个串口便发送消息通知主对话框,并将串口号以WPARAM传递
voidFindComm()
//枚举当前系统中的串口
LONGresult=0;
HKEYkey=NULL;
result=RegOpenKeyEx(HKEY_LOCAL_MACHINE,//需要打开的主键的名称
"
HARDWARE\\DEVICEMAP\\SERIALCOMM"
//需要打开的子键的名称,设备串口
0,//保留,必须设置为0
KEY_READ,//安全访问标记,也就是权限
&
key);
//得到的将要打开键的句柄,当不再需要句柄,
//必须调用RegCloseKey关闭它
if(result)
AfxMessageBox("
无法获取串口,请确认是否安装并连接串口!
return;
TCHARportname[250];
//串口名
TCHARdata[250];
DWORDportnamelen=0;
//串口名长度
DWORDdatalen=0;
intindex=0;
while
(1)//找完COM后跳出
portnamelen=255;
datalen=255;
result=RegEnumValue(key,//Long,一个已打开项的句柄,或者指定一个标准项名
index++,//Long,欲获取值的索引。
注意第一个值的索引编号为零
portname,//String,用于装载位于指定索引处值名的一个缓冲区
&
portnamelen,//Long,用于装载lpValueName缓冲区长度的一个变量。
//一旦返回,它会设为实际载入缓冲区的字符数量
NULL,//Long,未用;
设为零
NULL,//Long,用于装载值的类型代码的变量
(LPBYTE)data,//Byte,用于装载值数据的一个缓冲区
datalen);
//Long,用于装载lpData缓冲区长度的一个变量。
if(result)break;
//发送消息,WM_USER+1为自定义消息,即找到串口的,并将串口号"
COMx"
通过WPARAM参数传送给主对话框窗口
//:
AfxGetMainWnd()->
m_hWnd,获得主对话框句柄
//(WPARAM)(LPCTSTR)data,类型转换
:
SendMessage(:
m_hWnd,WM_FOUNDCOMM,(WPARAM)(LPCTSTR)data,0);
}
RegCloseKey(key);
//调用RegCloseKey关闭打开键的句柄
//============自动寻找串口函数结束==================
//==========串口打开函数===========================
//功能:
打开串口,将已打开的串口句柄赋值给hCom,给出串口打开状态ComIsOK,完成串口状态设置
波特率,数据位,停止位,校验位
voidOpenComm(intnBaud,intnData,intnStop,intnCal)
hCom=CreateFile(strcomname,//串口号
GENERIC_READ|GENERIC_WRITE,//允许读或写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//重叠方式,用于异步通信
NULL);
if(hCom==INVALID_HANDLE_VALUE)
打开COM失败,串口不存在或已被占用!
ComIsOK=false;
ComIsOK=true;
SetCommMask(hCom,EV_TXEMPTY