MFC--对话框控制程序详解2

在研一项目过程中,接触到雷赛公司的控制器电机系列,采用PC上位机VC驱动电机运转,这里对过程中的程序进行详解,因为以前没有接触过MFC,也是对MFC的一个很好补充,在实战中学习MFC。前面的例程后序补充。现在对一个例程的程序执行过程进行分析。

可以仔细看中间注释代码,供同样的MFC菜鸟理解。

<pre name="code" class="cpp">// SMC_ExampleDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SMC_Example.h"
#include "SMC_ExampleDlg.h"
//如果生成调试版本,要指示当前文件的名称。__FILE__是一个宏,在编译器编译过程中给它赋值为当前正在编译的文件名称
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

 //  Dialog Data
	 //{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };//只是表明About对话框的模板ID是IDD。
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support   注意程序中调用虚函数
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()   //是向类中添加消息映射必要的结构体和函数声明
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)  //构造函数
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)  //实现数据交换
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

//在BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()之间添加你的消息响应函数,为每个消息处理函数加入一个入口
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSMC_ExampleDlg dialog

CSMC_ExampleDlg::CSMC_ExampleDlg(CWnd* pParent /*=NULL*/)      //对话框构造函数
	: CDialog(CSMC_ExampleDlg::IDD, pParent)           //一个继承类的构造函数 ,初始化数据 
{                                                        //pParent定义?

	//{{AFX_DATA_INIT(CSMC_ExampleDlg)
	m_iAxisNum = 0; 
	m_iReturnMode = 0;//返回,模式
	m_iSpeedMode = 0;
	m_iOriginDir = 0;//回零方向
	m_iConnectNum = 0; //链接号 
	m_fBeginSpeed = 100;
	m_fDecTime = 0.1;//减速时间
	m_iRunDistance = 2000;//运动距离
	m_fAccTime = 0.1;
	m_fStopSpeed = 100;//停止速度
	m_fRunSpeed = 300;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);   //图标句柄
}

void CSMC_ExampleDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);          //数据交换
	//{{AFX_DATA_MAP(CSMC_ExampleDlg)
	DDX_Radio(pDX, IDC_RADIO_XAXIS, m_iAxisNum);   //对话数据交换函数
	DDX_Radio(pDX, IDC_RADIO_RETURNMODE, m_iReturnMode);
	DDX_Radio(pDX, IDC_RADIO_SPEED, m_iSpeedMode);
	DDX_Radio(pDX, IDC_RADIO_DIR, m_iOriginDir);
	DDX_Text(pDX, IDC_EDIT_BEGINSPEED, m_fBeginSpeed);
	DDX_Text(pDX, IDC_EDIT_DECTIME, m_fDecTime);
	DDX_Text(pDX, IDC_EDIT_RUNDISTANCE, m_iRunDistance);
	DDX_Text(pDX, IDC_EDIT_ACCTIME, m_fAccTime);
	DDX_Text(pDX, IDC_EDIT_RUNSPEED, m_fRunSpeed);
	DDX_Text(pDX, IDC_EDIT_STOPSPEED, m_fStopSpeed);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CSMC_ExampleDlg, CDialog)  //使用BEGIN_MESSAGE_MAP宏开始你的消息映射的定义
//{{AFX_MSG_MAP(CSMC_ExampleDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_START, OnButtonStart)//开始
	ON_BN_CLICKED(IDC_BUTTON_CLEARPOS, OnButtonClearpos)
	ON_BN_CLICKED(IDC_BUTTON_SLOWDOWN, OnButtonSlowdown)
	ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)
	ON_BN_CLICKED(IDC_BUTTON_EXIT, OnButtonExit)
	ON_BN_CLICKED(IDC_BUTTON_RETURN, OnButtonReturn)
	//}}AFX_MSG_MAP
	ON_STN_CLICKED(IDC_STATIC_POSITION, &CSMC_ExampleDlg::OnStnClickedStaticPosition)
	ON_BN_CLICKED(IDC_RADIO_RETURNMODE, &CSMC_ExampleDlg::OnBnClickedRadioReturnmode)
	ON_BN_CLICKED(IDC_BUTTON1, &CSMC_ExampleDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_RADIO_DIR, &CSMC_ExampleDlg::OnBnClickedRadioDir)
	ON_BN_CLICKED(IDC_RADIO3, &CSMC_ExampleDlg::OnBnClickedRadio3)
	ON_BN_CLICKED(IDC_RADIO_XAXIS, &CSMC_ExampleDlg::OnBnClickedRadioXaxis)
	ON_STN_CLICKED(IDC_STATIC_RUNSTATE, &CSMC_ExampleDlg::OnStnClickedStaticRunstate)
	ON_BN_CLICKED(IDC_RADIO_SPEED, &CSMC_ExampleDlg::OnBnClickedRadioSpeed)
	ON_BN_CLICKED(IDC_RADIO10, &CSMC_ExampleDlg::OnBnClickedRadio10)
	ON_BN_CLICKED(IDC_RADIO8, &CSMC_ExampleDlg::OnBnClickedRadio8)
	ON_EN_CHANGE(IDC_EDIT_ACCTIME, &CSMC_ExampleDlg::OnEnChangeEditAcctime)
	ON_EN_CHANGE(IDC_EDIT_STOPSPEED, &CSMC_ExampleDlg::OnEnChangeEditStopspeed)
	ON_EN_CHANGE(IDC_EDIT_BEGINSPEED, &CSMC_ExampleDlg::OnEnChangeEditBeginspeed)
	ON_BN_CLICKED(IDC_RADIO_YAXIS, &CSMC_ExampleDlg::OnBnClickedRadioYaxis)
	//ON_BN_CLICKED(IDC_RADIO_UAXIS, &CSMC_ExampleDlg::OnBnClickedRadioUaxis)
	ON_BN_CLICKED(IDC_RADIO_ZAXIS, &CSMC_ExampleDlg::OnBnClickedRadioZaxis)
	ON_BN_CLICKED(IDC_RADIO4, &CSMC_ExampleDlg::OnBnClickedRadio4)
	ON_BN_CLICKED(IDC_RADIO5, &CSMC_ExampleDlg::OnBnClickedRadio5)
	ON_BN_CLICKED(IDC_RADIO6, &CSMC_ExampleDlg::OnBnClickedRadio6)
	ON_EN_CHANGE(IDC_EDIT_RUNDISTANCE, &CSMC_ExampleDlg::OnEnChangeEditRundistance)
	ON_EN_CHANGE(IDC_EDIT_DECTIME, &CSMC_ExampleDlg::OnEnChangeEditDectime)
	ON_EN_CHANGE(IDC_EDIT_RUNSPEED, &CSMC_ExampleDlg::OnEnChangeEditRunspeed)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSMC_ExampleDlg message handlers

BOOL CSMC_ExampleDlg::OnInitDialog()      //对话窗口初始化
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);   //获得系统菜单
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog

	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标
	
	// TODO: Add extra initialization here
	
	UINT ret = smc_board_init(m_iConnectNum,1,"COM3",115200);//控制器 链接初始化函数,分配系统资源
	//正确连接的返回值是0,下面是错误提示
	if(ret!=0)
	{
		MessageBox("连接失败,请进入代码重设对应的连接参数!");
		return TRUE;
	}
	
	SetTimer(0,200,NULL);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSMC_ExampleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)  //判断ID或者地址是不是 IDM_ABOUTBOX 这个ID或者他的地址
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	} 
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

void CSMC_ExampleDlg::OnPaint() //事件发生时执行画图程序
{
	if (IsIconic())   //对话窗窗体是否最小化发生
	{
		CPaintDC dc(this); // 声明DC class 对象 dc, 并构建,用于画图

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);//给窗口发送发送消息,立即调用方式
		                                                            //发送消息 WM_ICONERASEBKGND (图标背景删除)

		// 下面语句是把图标(icon)放到客户区中心位置。
		int cxIcon = GetSystemMetrics(SM_CXICON);//声明cxIcon,初始化GetSystemMetrics(SM_CXICON);    
		int cyIcon = GetSystemMetrics(SM_CYICON);//声明cyIcon,初始化GetSystemMetrics(SM_CYICON); 
		CRect rect;  // 声明矩形class rect, 
		GetClientRect(&rect);  // 取得客户区 矩形大小
		//下面声明 x,y, 计算 x,y 坐标。用dc.DrawIcon 画 图标,还是对话框的操作
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2;
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSMC_ExampleDlg::OnQueryDragIcon()//这个函数是系统获取你的鼠标图标的,
	                                      //比如你要换掉系统默认的鼠标箭头图标,
	                                      //就在构造函数中加载鼠标箭头的图标。
	                                      //默认是返回系统的鼠标图标。HCURSOR
{
	return (HCURSOR) m_hIcon;
}



void CSMC_ExampleDlg::OnTimer(UINT nIDEvent)    //我们只是重载OnTimer;其实内部还有很多要处理的,
                                                //我们只是重载一下,处理想做的事情,再让它按原流程继续处理
                                                //相当于在中间加入了一些我们需要处理的事件
{
	// TODO: Add your message handler code here and/or call default
	switch(nIDEvent)
	{
	case 0:   //当计时器(ID=0)到时间:  动作
		{
			double lPos ;
			smc_get_position_unit(m_iConnectNum,m_iAxisNum,&lPos);//读取当前指令位置计数器值,轴号 ,pos为当前返回值
			CString csPos;
			csPos.Format(_T("%f"),lPos);
			GetDlgItem(IDC_STATIC_POSITION)->SetWindowText(csPos);//得到静态文本框(IDC-STATIC)的ID(POSITION),
			                                                      //然后向这个文本框写入文本csPos所代表的内容
			short iRunState = smc_check_done(m_iConnectNum,m_iAxisNum);
			if(iRunState)
			{
				GetDlgItem(IDC_STATIC_RUNSTATE)->SetWindowText(_T("停止"));
			}
			else
			{
				
				GetDlgItem(IDC_STATIC_RUNSTATE)->SetWindowText(_T("运行中"));
			}
		}
		break;
    default:
		break;
	}
	CDialog::OnTimer(nIDEvent);
}

//控制面板操作,这里对对话框的操作控件具体如何执行进行解释。

//启动
void CSMC_ExampleDlg::OnButtonStart()    //点位运动
{
	// TODO: Add your control notification handler code here
	
	UpdateData();  
	//smc_set_equiv(m_iConnectNum,m_iAxisNum,1000);         //返回脉冲当量值设置
	smc_set_pulse_outmode(m_iConnectNum,m_iAxisNum,0);
	smc_set_s_profile(m_iConnectNum,m_iAxisNum,0,0.01);//设置单轴速度曲线 S 段参数值
	smc_set_profile_unit(m_iConnectNum,m_iAxisNum,m_fBeginSpeed,m_fRunSpeed,m_fAccTime,m_fDecTime,m_fStopSpeed);//设置单轴运动速度曲线
	smc_pmove_unit(m_iConnectNum,m_iAxisNum,m_iRunDistance,0);   //定长运动,加/减速度恒定
	//本来脉冲数决定了运动的距离,这里直接封装,设置脉冲当量就行
	//若未设置的话,脉冲当量默认值为100
}
//复位
void CSMC_ExampleDlg::OnButtonReturn()     //回原点运动
{
	// TODO: Add your control notification handler code here
	UpdateData();
	smc_set_home_pin_logic(m_iConnectNum,m_iAxisNum,0,0);//设置 ORG 原点信号,信号ORG低电平有效
	smc_set_homemode(m_iConnectNum,m_iAxisNum,m_iOriginDir,m_iSpeedMode,m_iReturnMode,0);//设置回原点模式,默认低速回零
	smc_home_move(m_iConnectNum,m_iAxisNum);//回原点运动
	while(smc_check_done(m_iConnectNum,m_iAxisNum) == 0 )//检测指定轴的运动状态
	{
		AfxGetApp()->PumpMessage();	
	}
	smc_set_position_unit(m_iConnectNum,m_iAxisNum,0);//设置当前指令位置计数器值
}
//位置清零
void CSMC_ExampleDlg::OnButtonClearpos() 
{
	// TODO: Add your control notification handler code here
	UpdateData();  //更新数据在对话框的显示
	smc_set_position_unit(m_iConnectNum,m_iAxisNum,0);//设置当前指令位置计数器值
}

//减速停止
void CSMC_ExampleDlg::OnButtonSlowdown() 
{
	// TODO: Add your control notification handler code here
	smc_stop(m_iConnectNum,m_iAxisNum,0);//指定轴停止运动
}
//立即停止
void CSMC_ExampleDlg::OnButtonStop()  
{
	// TODO: Add your control notification handler code here
	smc_stop(m_iConnectNum,m_iAxisNum,1);//指定轴停止运动
}
//退出
void CSMC_ExampleDlg::OnButtonExit() 
{
	// TODO: Add your control notification handler code here
	smc_board_close(m_iConnectNum);//控制器关闭函数,释放系统资源
	this->DestroyWindow();
}

//坐标位置
void CSMC_ExampleDlg::OnStnClickedStaticPosition()
{
	// TODO: 在此添加控件通知处理程序代码
}

//一次回零
void CSMC_ExampleDlg::OnBnClickedRadioReturnmode()//点击静态位置
{
	// TODO: 在此添加控件通知处理程序代码
}

void CSMC_ExampleDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	//smc_set_position_unit(m_iConnectNum,m_iAxisNum,0);
}

//回原点方向 正向
void CSMC_ExampleDlg::OnBnClickedRadioDir()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	m_iOriginDir = 1;
}

//一次回零加反找
void CSMC_ExampleDlg::OnBnClickedRadio3()
{
	// TODO: 在此添加控件通知处理程序代码
}

//运动轴 x轴
void CSMC_ExampleDlg::OnBnClickedRadioXaxis()
{
	// TODO: 在此添加控件通知处理程序代码
}

//运动轴 y轴
void CSMC_ExampleDlg::OnBnClickedRadioYaxis()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);  
	m_iAxisNum = 1; 
}

//运动轴 z轴
void CSMC_ExampleDlg::OnBnClickedRadioZaxis()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	m_iAxisNum = 2; 
}

//void CSMC_ExampleDlg::OnBnClickedRadioUaxis()
//{
	// TODO: 在此添加控件通知处理程序代码
//}

//运动状态
void CSMC_ExampleDlg::OnStnClickedStaticRunstate()
{
	// TODO: 在此添加控件通知处理程序代码
}

//低速回原点
void CSMC_ExampleDlg::OnBnClickedRadioSpeed()  
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	m_iSpeedMode = 0;
}

//高速回原点
void CSMC_ExampleDlg::OnBnClickedRadio10()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	m_iSpeedMode = 1;
}

//反向回原点模式
void CSMC_ExampleDlg::OnBnClickedRadio8()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();
	m_iOriginDir = 0;
}

//加速时间
void CSMC_ExampleDlg::OnEnChangeEditAcctime()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

//停止时间
void CSMC_ExampleDlg::OnEnChangeEditStopspeed()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

//起始速度
void CSMC_ExampleDlg::OnEnChangeEditBeginspeed()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

//两次回零
void CSMC_ExampleDlg::OnBnClickedRadio4()
{
	// TODO: 在此添加控件通知处理程序代码
}

//一次回零加EZ
void CSMC_ExampleDlg::OnBnClickedRadio5()
{
	// TODO: 在此添加控件通知处理程序代码
}

//EZ
void CSMC_ExampleDlg::OnBnClickedRadio6()
{
	// TODO: 在此添加控件通知处理程序代码
}

//运动距离
void CSMC_ExampleDlg::OnEnChangeEditRundistance()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

//减速时间
void CSMC_ExampleDlg::OnEnChangeEditDectime()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

//运动速度
void CSMC_ExampleDlg::OnEnChangeEditRunspeed()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

//#1015

	// TODO:  在此添加控件通知处理程序代码
}

制作出来的对话框如图:

MFC--对话框控制程序详解2_第1张图片

即可以对电机的各种运行模式进行操作。待深究改进该程序。

 
 

你可能感兴趣的:(MFC--对话框控制程序详解2)