📄 mfcmovedlg.cpp
字号:
// MFCMoveDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MFCMove.h"
#include "MFCMoveDlg.h"
#include "ReadStatus.h" // **ADDED** The Event Class
#include <bitset>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMFCMoveDlg dialog
CMFCMoveDlg::CMFCMoveDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMFCMoveDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMFCMoveDlg)
m_Transport = 3;
m_BusType = FALSE;
m_lblConnected = _T("Disconnected");
m_Ver = _T("v?.?.?.?");
m_BPS = 38400;
m_CardNbr = 0;
m_IP = _T("172.26.128.152");
m_Port = 1;
m_Master = 0;
m_Axis = 0;
m_24vEnable = -1;
m_KAM = -1;
m_Motion = -1;
m_Drive =-1;
m_KAMR = -1;
m_SetPoint = 0;
m_MoveCnt = 0;
m_Position = 0;
m_MoveAmt = 0;
m_MoveMode = 0;
m_CountDirection = 1;
m_StopDEC = FALSE;
m_MoveABS = TRUE;
m_VEL = -1;
m_FVEL = -1;
m_ACC = -1;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
// **ADDED**
// Create Interfaces using Prog ID
m_Cntl = new IControl;
m_Cntl->CreateDispatch(_T("BoxBridge.Control.1"));
m_Stat = new IStatus;
m_Stat->CreateDispatch(_T("BoxBridge.Status.1"));
// Initialize working data
m_workerEvent = NULL;
m_StopWork = true;
m_axisMsgId = 0;
m_masterMsgId = 0;
// **ADDED**
}
// **ADDED**
CMFCMoveDlg::~CMFCMoveDlg()
{
// Need to Clean up COM
if(m_Cntl){
m_Cntl->Disconnect();
delete m_Cntl;
}
if(m_Stat){
m_Stat->Disconnect();
delete m_Stat;
}
m_StopWork = true;
if(m_workerEvent){
delete m_workerEvent;
}
// CoUninitialize(); // Clean up of COM done automatically by MFC
}
// **ADDED**
void CMFCMoveDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMFCMoveDlg)
DDX_Radio(pDX, IDC_RDO_TRANSPORT, m_Transport);
DDX_Check(pDX, IDC_CHK_PCI, m_BusType);
DDX_Text(pDX, IDC_LBL_CONNECT, m_lblConnected);
DDX_Text(pDX, IDC_LBL_VER, m_Ver);
DDX_Text(pDX, IDC_TXT_BPS, m_BPS);
DDX_Text(pDX, IDC_TXT_CARDNBR, m_CardNbr);
DDX_Text(pDX, IDC_TXT_IP, m_IP);
DDX_Text(pDX, IDC_TXT_PORT, m_Port);
DDX_CBIndex(pDX, IDC_CBO_MASTER, m_Master);
DDX_CBIndex(pDX, IDC_CBO_AXIS, m_Axis);
DDX_Radio(pDX, IDC_LED_24VENABLE, m_24vEnable);
DDX_Radio(pDX, IDC_LED_KAM, m_KAM);
DDX_Radio(pDX, IDC_LED_MOTION, m_Motion);
DDX_Radio(pDX, IDC_LED_DRIVE, m_Drive);
DDX_Radio(pDX, IDC_LED_KAMR, m_KAMR);
DDX_Text(pDX, IDC_TXT_SETPOINT, m_SetPoint);
DDX_Text(pDX, IDC_TXT_MOV_CNT, m_MoveCnt);
DDX_Text(pDX, IDC_TXT_POSITION, m_Position);
DDX_Text(pDX, IDC_TXT_MOVE, m_MoveAmt);
DDX_CBIndex(pDX, IDC_MOV_MODE, m_MoveMode);
DDX_CBIndex(pDX, IDC_MOV_CNT_DIR, m_CountDirection);
DDX_Check(pDX, IDC_STOP_DEC, m_StopDEC);
DDX_Check(pDX, IDC_MOV_ABS, m_MoveABS);
DDX_Text(pDX, IDC_TXT_VEL, m_VEL);
DDX_Text(pDX, IDC_TXT_FVEL, m_FVEL);
DDX_Text(pDX, IDC_TXT_ACC, m_ACC);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMFCMoveDlg, CDialog)
//{{AFX_MSG_MAP(CMFCMoveDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_CONNECT, OnBtnConnect)
ON_BN_CLICKED(IDC_LED_24VENABLE, OnLed24venable)
ON_BN_CLICKED(IDC_LED_KAM, OnLedKam)
ON_BN_CLICKED(IDC_LED_MOTION, OnLedMotion)
ON_BN_CLICKED(IDC_LED_KAMR, OnLedKamr)
ON_BN_CLICKED(IDC_LED_DRIVE, OnLedDrive)
ON_CBN_SELCHANGE(IDC_CBO_AXIS, OnSelchangeCboAxis)
ON_CBN_SELCHANGE(IDC_CBO_MASTER, OnSelchangeCboMaster)
ON_BN_CLICKED(IDC_CLR_KAM, OnClrKAM)
ON_BN_CLICKED(IDC_MOVE_STOP, OnMoveStop)
ON_BN_CLICKED(IDC_MOVE_BTN, OnMoveBtn)
//}}AFX_MSG_MAP
ON_MESSAGE(WMU_UpdateStats,OnUpdateStats) // **ADDED**
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMFCMoveDlg message handlers
BOOL CMFCMoveDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 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); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMFCMoveDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
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 CMFCMoveDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
// **ADDED**
// Code behind buttons, etc.
//
void CMFCMoveDlg::OnBtnConnect()
{
try{
//******************
// Connect to the Device on all interfaces
UpdateData();
m_Ver = CString("v") + m_Cntl->GetBstrVersion(); // Version
m_Cntl->SetNBPS(m_BPS); // Set BPS
m_Cntl->SetNPort(m_Port); // Set Port
m_Cntl->SetBstrIP(m_IP); // Set IP Address
m_Cntl->SetNBus(m_BusType?1:0); // Set Bus, checked(true) is ISA, else PCI
m_Cntl->Connect(m_Transport,m_CardNbr);//Connect to Transport
m_CardNbr = m_Cntl->GetNCard(); // One way to use USB is to grab the first unit, but then need to directly connect after that
m_Stat->SetNStatusWaitRate(7); // Minimum time between status events
m_Stat->SetNBPS(m_BPS); // Set BPS
m_Stat->SetNPort(m_Port); // Set Port
m_Stat->SetBstrIP(m_IP); // Set IP Address
m_Stat->SetNBus(m_BusType?1:0); // Set Bus, checked(true) is ISA, else PCI
m_Stat->Connect(m_Transport,m_CardNbr);//Connect to Transport
if(!(m_Cntl->GetIsOffline() || m_Stat->GetIsOffline())) // Verify Connection
m_lblConnected = _T("Connected");
// Turn on event handler
m_workerEvent = new ReadStatus(this);
UpdateData(FALSE);
// After UpdateData, since it also calls it
OnSelchangeCboMaster();
OnSelchangeCboAxis();
// ***
// Error Handling should go everywhere a call to Communications Server is made
// In this sample it is only placed here to aid readablility.
// ***
// Error Handling - the errors specifically thrown by Communications Server
// show up as COM exceptions and can be caught with the COleDispatchException class.
}catch(COleDispatchException* e) {
ostringstream errmsg;
unsigned short errnbr = e->m_scError;
errmsg << "ERROR NO: " << hex << e->m_scError << dec << "(" << errnbr << ")\nERROR DESC: " << string(e->m_strDescription) << "\nERROR INTERFACE: " << string(e->m_strSource);
MessageBox(errmsg.str().c_str(), "COM Error", MB_OK);
}
catch(CException *e) {
TCHAR szCause[1024];
e->GetErrorMessage(szCause, 1024);
MessageBox(szCause, "non-COM Error", MB_OK);
}
}
void CMFCMoveDlg::OnSelchangeCboMaster()
{
// When a different master is choosen, update the status
UpdateData();
if(m_Stat->GetIsOffline()) return;
// initialize realtime status
ostringstream led;
led << _T("P") << 4112 + m_Master << _T(",P4272") << _T(",P") << 8208 + (256 * m_Master);
if(m_masterMsgId) m_Stat->DelStatus(m_masterMsgId);
m_masterMsgId = m_Stat->AddACRCustom(led.str().c_str());
UpdateData(FALSE);
}
void CMFCMoveDlg::OnClrKAM()
{
// Clear the Kill All Moves flag
UpdateData();
if(m_Stat->GetIsOffline()) return;
m_Cntl->SetFlag(522+(m_Master*32),false,true);
UpdateData(FALSE);
}
void CMFCMoveDlg::OnSelchangeCboAxis()
{
// When a different axis is choosen, update the status
UpdateData();
if(m_Stat->GetIsOffline()) return;
// initialize realtime status
ostringstream led;
led << _T("P") << 4360 + m_Axis << _T(",P") << 12288 + (256 * m_Axis) << _T(",P") << 12295 + (256 * m_Axis);
if(m_axisMsgId) m_Stat->DelStatus(m_axisMsgId);
m_axisMsgId = m_Stat->AddACRCustom(led.str().c_str());
UpdateData(FALSE);
}
void CMFCMoveDlg::OnMoveBtn()
{
// Populate all the information needed to execute a move. This sample only
// moves one axis at a time, so only needs a safearray size of 1 element.
VARIANT symbol;
SAFEARRAY* pSAz;
SAFEARRAYBOUND bound[1];
bound[0].lLbound=0;
bound[0].cElements=1;
pSAz = SafeArrayCreate(VT_VARIANT,1,bound);
long itemNbr = 0;
long itemMask = 1;
UpdateData();
if(m_Cntl->GetIsOffline()) return;
// Init move parameters
m_Cntl->SetNMoveProfile(m_Master);
m_Cntl->SetNMoveMode(m_MoveMode);
m_Cntl->SetFMoveACC(m_ACC);
m_Cntl->SetFMoveVEL(m_VEL);
m_Cntl->SetFMoveFVEL(m_FVEL);
m_Cntl->SetBMoveAbsolute(m_MoveABS);
if(m_CountDirection == 2)
m_Cntl->SetNMoveCounter(-1);
else
m_Cntl->SetNMoveCounter(m_CountDirection);
// Single axis mask is easy, just shift a bit over axis number times.
// For multiple axes, the mask would need to add each single axis value
// together.
itemMask = itemMask << m_Axis;
// Populate SafeArray of Variants (one data point in this example.) Note that Moves
// can be either Integer based moves or Floating Point based moves. The type
// of move is determined by inspecting the type of the variant passed inside the
// Safearray (vItem below). In this sample, the value is fixed as an Integer
// for ease of programming. To allow for either value type in the GUI, you would
// need to write code that figured out if the value was an integer or a float,
// (i.e. not use the type specific MFC converter in DoDataExchange()).
CComVariant vItem(m_MoveAmt);
SafeArrayPutElement(pSAz, &itemNbr, &vItem);
VariantInit(&symbol);
symbol.vt = VT_ARRAY | VT_VARIANT;
symbol.parray = pSAz;
// Move. For ease of programming the Communication Server will destry the SafeArray
// after this call unless SafeArrayLock(pSAz) is called before Move. If that is done
// then you must call SafeArrayUnlock(pSAz) and SafeArrayDestroy(pSAz) to clean up
// the memory.
m_Cntl->Move(itemMask,symbol);
}
void CMFCMoveDlg::OnMoveStop()
{
UpdateData();
if(m_Cntl->GetIsOffline()) return;
m_Cntl->Stop(m_StopDEC);
}
LONG CMFCMoveDlg::OnUpdateStats(UINT,LONG xMsgid)
{
// The StatusWaiting event will trigger when ever a status changes. Check
// which status request (for Master info or Axis info) generated the event
// and then read that status request. The status requests are set up at
// connection time or when the dropdown listboxes specifying the master/axis
// are changed.
// NOTE: The radio buttons used to simulate LEDs show as "on" when they are
// set to the value zero, and "off" for non-zero values.
SAFEARRAY* pSA1;
long lBound1 = 0;
CComVariant vItem1; // The CComVariant is found in the atlbase.h include file
CComVariant vaxis; // it will clean up SAFEARRAY when it goes out of scope.
bitset<32> holdDriveFlags(0);
// Check on the Axis Status
// index 0 = P4360 + Axis Number
// index 1 = P12288 + (Axis Number * 256)
// index 2 = P12295 + (Axis Number * 256)
if(xMsgid == m_axisMsgId){
vaxis = m_Stat->GetStatus(m_axisMsgId);
if(vaxis.vt & VT_ARRAY){
pSA1 = vaxis.parray;
SafeArrayGetElement(pSA1, &lBound1, &vItem1);
if(vItem1.vt!=VT_EMPTY)
holdDriveFlags = vItem1.lVal;
++lBound1;
SafeArrayGetElement(pSA1, &lBound1, &vItem1);
if(vItem1.vt!=VT_EMPTY)
m_Position = vItem1.lVal;
++lBound1;
SafeArrayGetElement(pSA1, &lBound1, &vItem1);
if(vItem1.vt!=VT_EMPTY)
m_SetPoint = vItem1.lVal;
}else{
holdDriveFlags = 0;
}
m_Drive = !(holdDriveFlags.at(17));
m_KAMR = !(holdDriveFlags.at(19));
}
SAFEARRAY* pSA2;
long lBound2 = 0;
CComVariant vItem2; // The CComVariant is found in the atlbase.h include file
CComVariant vmaster; // it will clean up SAFEARRAY when it goes out of scope.
bitset<32> holdMotion(0);
bitset<32> holdVolt24(0);
// Check on the Master Status
// index 0 = P4112 + Master Number
// index 1 = P4272
// index 2 = P8208 + (Master Number * 256)
if(xMsgid == m_masterMsgId){
vmaster = m_Stat->GetStatus(m_masterMsgId);
if(vmaster.vt & VT_ARRAY){
pSA2 = vmaster.parray;
SafeArrayGetElement(pSA2, &lBound2, &vItem2);
if(vItem2.vt!=VT_EMPTY)
holdMotion = vItem2.lVal;
++lBound2;
SafeArrayGetElement(pSA2, &lBound2, &vItem2);
if(vItem2.vt!=VT_EMPTY)
holdVolt24 = vItem2.lVal;
++lBound2;
SafeArrayGetElement(pSA2, &lBound2, &vItem2);
if(vItem2.vt!=VT_EMPTY)
m_MoveCnt = vItem2.lVal;
}else{
holdMotion = 0;
holdVolt24 = 0;
}
m_Motion = !(holdMotion.at(4));
m_KAM = !(holdMotion.at(10));
m_24vEnable = !(holdVolt24.at(13));
}
UpdateData(FALSE);
return 0;
}
// The radio buttons are used as a poor man's led, so make them read only.
void CMFCMoveDlg::OnLed24venable()
{
UpdateData(FALSE);
}
void CMFCMoveDlg::OnLedKam()
{
UpdateData(FALSE);
}
void CMFCMoveDlg::OnLedMotion()
{
UpdateData(FALSE);
}
void CMFCMoveDlg::OnLedKamr()
{
UpdateData(FALSE);
}
void CMFCMoveDlg::OnLedDrive()
{
UpdateData(FALSE);
}
// **ADDED**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -