1、在打开按钮旁边加入自绘的打开和关闭图标:先加入工具条中的Picture,然后选中右键看属性,并如图将Image选为默认的IDI_ICON_CLOSE。如下图5. 基本设置下面对各个按钮及编辑框设置进行描述右键串口对应的Combo Box,ID设置为IDC_COMLIST,Type设置为Drop List,Sort不选择(我系统是WIN7 64位,不选中反而自动排序,至于XP得试试看了,以下的选择相同)。右键波特率对应的Combo Box,ID设置为IDC_BAUD,Type及Sort同上。右键数据位对应的Combo Box,ID设置为IDC_BDATA,Type及Sort同上。右键停止位对应的
2、Combo Box,ID设置为IDC_BSTOP,Type及Sort同上。右键校验位对应的Combo Box,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。接收区的十六进制显示的Check Box复选框ID设置为IDC_CHECK_HEXRX。发送区的十六进制发送的Check Box复选框ID设置为
3、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。
4、在comm.cpp中编写串口创建、打开、关闭以及串口监听线程(用于自动接收)的代码,同时加入进制转换或显示的函数,这些在comm.h文件中申明,在主对话框中包含comm.h即可。想修改按钮样式,在网上搜了一圈,结果不轻松,最后确定创建新类来实现。6.2. 创建自定义按钮类:View - Class Wizard选择Add Class - New,名字MyButton,基类选择CButton。在头文件 MyButton.h 中加入以下变量和函数定义:private: int m_Style; /按钮形状(0-正常,1-当前,2-按下,3-锁定) bool b_InRect; /鼠标进入标志 CS
5、tring m_strText; /按钮文字 COLORREF m_ForeColor;/文本颜色 COLORREF m_MouseInColor;/鼠标进入时文本颜色 COLORREF m_BackColor;/背景颜色 COLORREF m_LockForeColor; /锁定按钮的文字颜色 CRect m_ButRect; /按钮尺寸 CFont* p_Font; /字体 void DrawButton(CDC *pDC); /画正常按钮/ 接口函数public: MyButton(); void SetText(CString str); /设置文字 void SetForeColor
6、(COLORREF color); /设置文本颜色 void SetBkColor(COLORREF color); /设置背景颜色 void SetTextFont(int FontHight,LPCTSTR FontName); /设置字体在 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)
7、; /鼠标进入时文字颜色(蓝色) 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();在各函数内加入代码:void MyButton:PreSubclassWindow() /
8、 TODO: Add your specialized code here and/or call the base class ModifyStyle( 0, BS_OWNERDRAW ); /设置按钮属性为自画式 /PreSubclassWindow()在按钮创建前自动执行,所以我们可以在其中做一些初始工作。 /这里只做了一项工作,就是为按钮设置属性为“自绘”式,这样,用户在添加按钮后,就不需设置“Owner draw”属性了。 CButton:DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) Add your code to draw the spe
9、cified item CDC *pDC = CDC:FromHandle( lpDrawItemStruct-hDC ); m_ButRect = lpDrawItemStruct-rcItem; /获取按钮尺寸 if( m_strText.IsEmpty() ) GetWindowText( m_strText ); /获取按钮文本 int nSavedDC = pDC-SaveDC(); VERIFY( pDC ); DrawButton( pDC ); /绘制按钮 pDC-RestoreDC( nSavedDC ); /DrawItem()函数是一个关键函数,按钮的绘制工作就在这里进行
10、,它的作用相当于对话框中的OnPaint()函数和视图中的OnDraw()函数。/这里我做了三项工作:获取按钮尺寸、获取按钮文本、绘制按钮。其中绘制工作在自定义函数DrawButton()中完成。以下就是绘制过程:DrawButton(CDC *pDC) /调整状态 if( m_Style=3 ) m_Style = 0; if( GetStyle() & WS_DISABLED ) m_Style = 3; /禁止状态 /根据状态调整边框颜色和文字颜色 COLORREF bColor, fColor; /bColor为边框颜色,fColor为文字颜色 switch( m_Style ) ca
11、se 0: bColor = RGB(192,192,192); fColor = m_ForeColor; break; /正常按钮 case 1: bColor = RGB(255,255,255); /鼠标进入时按钮 case 2: fColor = m_MouseInColor; /按下的按钮 case 3: bColor = m_BackColor; fColor = m_LockForeColor; /锁定的按钮 /绘制按钮背景 CBrush Brush; Brush.CreateSolidBrush( m_BackColor ); /背景刷SelectObject( &Brush
12、 ); CPen Pen; Pen.CreatePen(PS_SOLID, 3, bColor );Pen );RoundRect(&m_ButRect,CPoint(10,10); /画圆角矩形 /绘制按钮按下时的边框 if( m_Style!=2 ) CRect Rect; Rect.SetRect( m_ButRect.left+1, m_ButRect.top+1, m_ButRect.right, m_ButRect.bottom );DrawEdge( &Rect, BDR_RAISEDINNER, BF_RECT ); /画边框 /绘制按钮文字SetTextColor( fCol
13、or ); /画文字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 表
14、征当前按钮状态,它的取值为:0-正常,1-当前,2-按下,3-锁定。不同状态下按钮的边框颜色和文字颜色有所不同。/m_Style 的值在鼠标响应函数中进行修改。/绘制工作主要利用CDC类的绘图函数完成,主要注意在 m_Style 不同取值下表现出来的差别。OnLButtonDown(UINT nFlags, CPoint point) Add your message handler code here and/or call default m_Style = 2; Invalidate(); /重绘按钮OnLButtonDown(nFlags, point);/OnLButtonDown(
15、)函数是单击鼠标左键时的消息函数。这里只是重新绘制按钮,具体的单击响应应该在拥有按钮的对话框或视图中进行。OnMouseMove(UINT nFlags, CPoint point) if( !b_InRect | GetCapture()!=this ) /鼠标进入按钮 b_InRect = true; /设置进入标志 SetCapture(); /捕获鼠标 /m_Style = 1; /设置按钮状态 else if ( !m_ButRect.PtInRect(point) ) /鼠标离开按钮 /清除进入标志 ReleaseCapture(); /释放捕获的鼠标OnMouseMove(nFl
16、ags, point);/onMouseMove()函数是鼠标移动消息函数,用于判定当前鼠标指针是否在按钮上。b_InRect是个标志,为true表示鼠标指针进入了按钮区域,/此时要捕获鼠标,让鼠标命令传送给按钮。当鼠标指针离开按钮时,要清除b_InRect标志,并且释放捕获的鼠标,让其它窗口可以接收鼠标命令。/Invalidate()函数用于更新按钮,它会自动调用DrawItem()函数重新绘制按钮。/设置条件的目的是仅在鼠标指针进入按钮和离开按钮时更新按钮,这样可以防止鼠标在按钮上移动时发生闪烁。OnLButtonUp(UINT nFlags, CPoint point) OnLButto
17、nUp(nFlags, point);/OnLButtonUp()函数是单击鼠标左键后弹起时的消息函数。这里也只是重绘按钮,这样能使按钮在按下和弹起时有所不同,使按钮看上去有动态效果。/接口函数是用 CMyButton类 定义的按钮修改颜色、字体和按钮文字的接口,由以下函数组成:/设置按钮文本SetText(CString str) SetWindowText(str);/设置文本颜色SetForeColor(COLORREF color) m_ForeColor = color;/设置背景颜色SetBkColor(COLORREF color) m_BackColor = color;/设置
18、字体(字体高度、字体名)SetTextFont(int FontHight,LPCTSTR FontName) if ( p_Font ) delete p_Font; /删除旧字体 p_Font = new CFont; p_Font-CreatePointFont( FontHight, FontName ); /创建新字体 SetFont( p_Font );/由于新字体由 new 生成,必须显式回收,这项工作可以在 CMyButton类 的析构函数中进行:/*CMyButton:CMyButton() /删除字体*/这样一个可设置颜色、字体的按钮类就做好了。使用时,先在对话框中放置好按
19、钮,再用 ClassWizard 为按钮添加控制变量,/并且将变量的类型设置为 CMyButton。之后,可以用该变量调用接口函数设置按钮颜色和字体。OK,自定义按钮完成。6.3. 实现过程及代码:现在可以对按钮,EDIT框等控件添加变量,文字描述麻烦,上图。comm.cpp编写内容如下#include stdafx.hcommassist.hcommassistDlg.hcomm.hchar ConvertHexChar(char ch);HANDLE hCom; /串口句柄CString strcomname; /串口名,如COM1bool ComIsOK; /串口打开状态标识,为真表示已
20、打开,否则未打开/=自动寻找串口函数=/函数功能:通过扫描注册表来找出当前所有物理串口/输入参数:无/返回类型:/说 明:若搜索成功,则每搜到一个串口便发送消息通知主对话框,并将串口号以WPARAM传递void FindComm() /枚举当前系统中的串口 LONG result = 0; HKEY key = NULL; result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, /需要打开的主键的名称 HARDWAREDEVICEMAPSERIALCOMM, /需要打开的子键的名称,设备串口 0, /保留,必须设置为0 KEY_READ, /安全访问标记,也就是权限
21、 &key); /得到的将要打开键的句柄,当不再需要句柄, /必须调用 RegCloseKey 关闭它 if( result ) AfxMessageBox(无法获取串口,请确认是否安装并连接串口! return; TCHAR portname250; /串口名 TCHAR data250; DWORD portnamelen = 0; /串口名长度 DWORD datalen = 0; int index = 0; while(1) /找完COM后跳出 portnamelen = 255; datalen = 255; result = RegEnumValue(key, /Long,一个已
22、打开项的句柄,或者指定一个标准项名 index+, /Long,欲获取值的索引。注意第一个值的索引编号为零 portname, /String,用于装载位于指定索引处值名的一个缓冲区 &portnamelen, /Long,用于装载lpValueName缓冲区长度的一个变量。 /一旦返回,它会设为实际载入缓冲区的字符数量 NULL, /Long,未用;设为零 NULL, /Long,用于装载值的类型代码的变量 (LPBYTE)data, /Byte,用于装载值数据的一个缓冲区 datalen); /Long,用于装载lpData缓冲区长度的一个变量。 if( result ) break; /
23、发送消息,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,完成串口状态设置波特率,数据
24、位,停止位,校验位void OpenComm(int nBaud, int nData, int nStop, int nCal) 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
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1