📄 mfcstatusdlg.cpp
字号:
// MFCStatusDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MFCStatus.h"
#include "MFCStatusDlg.h"
#include "ReadStatus.h" // **ADDED** The Event Class
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMFCStatusDlg dialog
CMFCStatusDlg::CMFCStatusDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMFCStatusDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMFCStatusDlg)
m_Transport = 2;
m_BusType = FALSE;
m_lblConnected = _T("Disconnected");
m_Ver = _T("v?.?.?.?");
m_BPS = 38400;
m_CardNbr = 0;
m_Clock = -1;
m_Delta1 = -1;
m_Delta2 = -1;
m_GetPPrim = _T("6160");
m_GetToPrim = 0;
m_IP = _T("0.0.0.0");
m_Port = 1;
m_SetToPrim = 0;
m_SetPPrim = 6160;
m_Avg1 = -1;
m_Avg2 = -1;
m_Clock2 = -1;
m_Max1 = -1;
m_Max2 = -1;
// NOTE: the ClassWizard will add member initialization here
//}}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_lastACRtic = 0;
m_totACRtic = 0;
m_ndxACRtic = 0;
m_lastPCtic = 0;
m_totPCtic = 0;
m_ndxPCtic = 0;
_LARGE_INTEGER x;
QueryPerformanceFrequency(&x); // counts per second for timer
m_secPCtic = x.QuadPart * 0.001; // use this number to calculate msec for PC counter
// **ADDED**
}
// **ADDED**
CMFCStatusDlg::~CMFCStatusDlg()
{
// 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 CMFCStatusDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMFCStatusDlg)
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_CLOCK, m_Clock);
DDX_Text(pDX, IDC_TXT_DELTA1, m_Delta1);
DDX_Text(pDX, IDC_TXT_DELTA2, m_Delta2);
DDX_Text(pDX, IDC_TXT_GETPPRIM, m_GetPPrim);
DDX_Text(pDX, IDC_TXT_GETTOPRIM, m_GetToPrim);
DDX_Text(pDX, IDC_TXT_IP, m_IP);
DDX_Text(pDX, IDC_TXT_PORT, m_Port);
DDV_MinMaxLong(pDX, m_Port, 1, 35);
DDX_Text(pDX, IDC_TXT_SETOPRIM, m_SetToPrim);
DDX_Text(pDX, IDC_TXT_SETPPRIM, m_SetPPrim);
DDX_Text(pDX, IDC_TXT_AVG1, m_Avg1);
DDX_Text(pDX, IDC_TXT_AVG2, m_Avg2);
DDX_Text(pDX, IDC_TXT_CLOCK2, m_Clock2);
DDX_Text(pDX, IDC_TXT_MAX1, m_Max1);
DDX_Text(pDX, IDC_TXT_MAX2, m_Max2);
DDX_Control(pDX, IDC_PROG_ACRCLOCK, m_ProgClock);
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMFCStatusDlg, CDialog)
//{{AFX_MSG_MAP(CMFCStatusDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_CONNECT, OnBtnConnect)
ON_BN_CLICKED(IDC_BTN_SETPRIM, OnBtnSetPrim)
ON_BN_CLICKED(IDC_BTN_GETPRIM, OnBtnGetPrim)
ON_BN_CLICKED(IDC_BTN_CLOCK, OnBtnClock)
//}}AFX_MSG_MAP
ON_MESSAGE(WMU_UpdateClock,OnUpdateClock) // **ADDED**
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMFCStatusDlg message handlers
BOOL CMFCStatusDlg::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 CMFCStatusDlg::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 CMFCStatusDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
// **ADDED**
// Code behind buttons
//
void CMFCStatusDlg::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");
UpdateData(FALSE);
// ***
// 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 CMFCStatusDlg::OnBtnSetPrim()
{
//******************
// Assign a value to a p_Parm
UpdateData();
// Set the ACR p_Parm in first parameter to value in second parameter using a Binary call
m_Cntl->SetParmLong(m_SetPPrim,m_SetToPrim,TRUE);
UpdateData(FALSE);
}
void CMFCStatusDlg::OnBtnGetPrim()
{
//******************
// Get a value from a p_Parm (extract from a safearray)
SAFEARRAY* pSA;
long lBound = 0;
CComVariant vItem; // The CComVariant is found in the atlbase.h include file
CComVariant status; // it will clean up SAFEARRAY when it goes out of scope.
UpdateData();
// Get the value of the p_Parm, returned in a safearray
status = m_Stat->GetACRCustom(CString(_T("P")) + m_GetPPrim);
if(status.vt & VT_ARRAY){
pSA = status.parray;
SafeArrayGetElement(pSA, &lBound, &vItem);
if(vItem.vt!=VT_EMPTY)
m_GetToPrim = vItem.lVal;
}else
m_GetToPrim = -1;
UpdateData(FALSE);
}
void CMFCStatusDlg::OnBtnClock()
{
//******************
// Start Event Generator to update global clock
UpdateData();
if(m_StopWork){ // Thread must not have started
m_StopWork = false;
m_workerEvent = new ReadStatus(this);
}
}
LONG CMFCStatusDlg::OnUpdateClock(UINT,LONG xtime)
{
//******************
// Update the clock
// This method is called by the ReadAlert Method in the ReadStatus class,
// when the Communications Server finds there is new data to be read. The
// ReadAlert Method reads that data (the global system clock on the ACR)
// and passes it to this method. In this method, the following fields are
// updated:
// m_Clock :This is the time reported by the ACR (global system clock)
//
// m_Delta1 :If the m_Clock value is greater than the last known ACR
// clock time, the difference goes in here.
//
// m_Avg1 :All the m_Delta1 times are added up and divided by the number
// of m_Delta1 times, creating an average delta time. This is
// an easier number to read on the screen than any single m_Delta1
// value, since they (the m_Delta1 data) change very quickly.
//
// m_Max1 :The highest m_Delta1 is captured here. To eliminate early spikes,
// the first 100 measurements are discarded.
//
// m_ProgClock is the progress bar displaying m_Delta1 when it is between 0 and 100 msec.
//
// The second set of numbers uses the PC clock as a base instead of the passed
// in ACR system clock. The deltas of the two clocks can differ if the ACR was
// feeding data, but the PC was unable to work fast enough to update it, or if
// the data from the ACR was not getting a changed updated as fast as the PC.
//
UpdateData();
m_Clock = xtime;
if(m_Clock > m_lastACRtic && m_lastACRtic != 0){
m_Delta1 = m_Clock - m_lastACRtic;
m_totACRtic += m_Delta1;
++m_ndxACRtic;
m_Avg1 = m_totACRtic / m_ndxACRtic;
if(m_ndxACRtic > 100) // ignore start up numbers
if(m_Max1 < m_Delta1) m_Max1 = m_Delta1;
}
if(m_Delta1>0 && m_Delta1<100)
m_ProgClock.SetValue(m_Delta1);
m_lastACRtic = m_Clock;
_LARGE_INTEGER PCtic;
QueryPerformanceCounter(&PCtic);
m_Clock2 = PCtic.QuadPart / m_secPCtic;
if(m_Clock2 > m_lastPCtic && m_lastPCtic != 0){
m_Delta2 = m_Clock2 - m_lastPCtic;
m_totPCtic += m_Delta2;
++m_ndxPCtic;
m_Avg2 = m_totPCtic / m_ndxPCtic;
if(m_ndxPCtic > 100) // ignore start up numbers
if(m_Max2 < m_Delta2) m_Max2 = m_Delta2;
}
m_lastPCtic = m_Clock2;
UpdateData(FALSE);
return 0;
}
// **ADDED**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -