⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cppstatus.cpp

📁 介绍控制器运动的例子
💻 CPP
字号:
// CPPStatus.cpp : Simple Status parameter watch using a console.
// The application asks the user for connection information and a p-Parameter to watch.
// If that p-Parameter changes, the application is signaled by a status event and the
// value of the p-Parameter is read. The example shows how to call a COM in-process server 
// interface and take advantage of connection points.
//
// Include Files

// STL for strings and IO 
#include <string>
#include <iostream>
#include <sstream>
#include <limits>
//using namespace std;       // uncomment this statement to avoid putting std:: everywhere

// ATL for easier use of COM 
#define _WIN32_DCOM           // Before windows.h, allows CoInitializeEx()
#include <windows.h>
#include <atlbase.h>  
CComModule _Module;
#include <atlcom.h>
#undef max  // max is a windows macro (bad), but I need to use the max in STL

// Import the BoxBridge Type Library to make COM stuff a bit easier to read
#import "..\ComACRsrvr.tlb" no_namespace named_guids

// ATL defined structure for defining the parameter data of the callback.  
// In this case there are no prameters.
_ATL_FUNC_INFO StatAlertInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4}};

//-----------------------------------------------------------------------------
// Connection Points are really callbacks, so we have to implement a COM method 
// that can be called from the automation server.  Using a class lets us inherit 
// from the ATL template, saving us the pain of implementing the generic interfaces.
//-----------------------------------------------------------------------------
class CStatEvent:
	public IDispEventSimpleImpl<1, CStatEvent, &DIID__IStatusEvents>
{
  // The CStatEvent will provide a callback for the StatusWaiting Event on the Status
  // Interface. When it is called, there is data waiting to be read, so the method reads
  // the data and sends it to the standard output.  All code in this class is  done inline 
  // for ease of reading.
public:
  CStatEvent(IStatusPtr stat)
  {
    // This class uses a passed in smart pointer that is already connected to establish
    // communications.  Another way to do this would be to pass in the connection state
    // information, create a new object reference and connect.  This is show in the 
    // CPPControl sample.  A third way would be to use global variables to hold the 
    // interface pointers.
    // This is another reference to a smart pointer, so it must be set to NULL in the destructor
    m_Stat = stat;
    HRESULT hr = DispEventAdvise((IUnknown*)m_Stat);
  }
  virtual ~CStatEvent()
  {
    DispEventUnadvise((IUnknown*)m_Stat);
    m_Stat = NULL;  // Setting smart pointers to NULL is *VERY IMPORTANT*
  }
  void __stdcall StatAlert(long msgId, long errNbr)
  {
    // Data is waiting to be read, send it to the std out
  try{
    // Init SafeArray Stuff
    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.

    // Read and display status (there could be more than one status value in
    // the returned array, but this sample just shows the first one.
    status = m_Stat->GetStatus(msgId);
    if(status.vt & VT_ARRAY){ 
      pSA = status.parray;
      SafeArrayGetElement(pSA, &lBound, &vItem);
      if(vItem.vt==VT_I4)
        std::cout << "Value in message id" << msgId << " is now " << vItem.lVal << '\n';
      if(vItem.vt==VT_R4)
        std::cout << "Value in message id" << msgId << " is now " << vItem.fltVal << '\n';
    }
  }catch(...){ return; /*ignore errors here*/ }
  }

  // The IDL used for this event is:
  //
	//  [ uuid(548F6282-AEE7-4AFA-B1F6-8C85389DD697),
  //		helpstring("_IStatusEvents Interface")]
  //	dispinterface _IStatusEvents
	//  {	properties:
  //		methods:
	//  	[id(1), helpstring("Status Waiting")] HRESULT StatusWaiting([in] long msgID, [in] long error);
	//  };
  //
  // Information mapped by the ATL class (above) supports Connection Points.
  //
BEGIN_SINK_MAP(CStatEvent)
	SINK_ENTRY_INFO(1, DIID__IStatusEvents, 1, StatAlert, &StatAlertInfo)
END_SINK_MAP()

private:
  IStatusPtr m_Stat;  // smart pointer from #import
};

void getInputLong(long &in, const std::string &msg, const long inMin = 0, const long inMax = 0) {
  // The cin has problems if the proper type of data is not entered, so 
  // handel those issues in one place.  Since most of the cin is in the
  // main(), this is a global function, but could also be a class method.
  while (!(std::cin >> in) || ((inMax > inMin) && (in < inMin || in > inMax))) {
     std::cout << msg;
     std::cin.clear();
     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

//-----------------------------------------------------------------------------
// Main Terminal Loop
//-----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
  // The Interface pointers are here (before the try) to allow easy clean up in 
  // main()'s try/catch. It is important to set any smart pointers to NULL before exiting. 
  IStatusPtr gStat;
  CStatEvent* alert = NULL;

  try{
  // Need to initialize for each thread as multithreaded
  CoInitializeEx(NULL, COINIT_MULTITHREADED);

  // Establish Communication Server
  gStat.CreateInstance(CLSID_Status);
  std::string ver = std::string(_com_util::ConvertBSTRToString(gStat->bstrVersion)); // Version
  std::cout << "--------Simple Status Watch using the BoxBridge v" << ver << "--------\n\n";

  // Collect Connection Information
  long transport = 0;   // transport type
  std::string portname; // transport lable
  long busType = 0;     // bus type
  long portNbr = 1;     // com port
  long portBPS = 2;     // bps of com port
  std::string ipaddr;   // ip address
  long cardNbr = 0;     // card index
  std::string input;    // terminal input
  long bps[3] = {9600,19200,38400}; // bps values
  std::string pparm;    // parameter to monitor

  std::cout << "How are we connecting.  Type in a number and press <enter>\n0=Offline, 1=Bus, 2=Serial, 3=Ethernet, 4=USB: ";
  getInputLong(transport, "You must enter a number between 0 - 4: ",0,4);

  switch (transport){
  // Various transport types require specific extra communication data
  case 0: 
    portname = "OFFLINE"; 
    break;
  case 1: 
    portname = "BUS";
    std::cout << "What Type of bus is the device in?\n0=PCI, 1=ISA: ";
    getInputLong(busType, "You must enter a number between 0 - 1: ",0,1);
    std::cout << "What is the index number of the device (usually 0):";
    getInputLong(cardNbr, "You must enter a number: ");
    break;
  case 2: 
    portname = "SERIAL"; 
    std::cout << "What is the Com Port number: ";
    getInputLong(portNbr, "You must enter a number between 1 - 256: ",1,256);
    std::cout << "What is the BPS of the Com Port? 0=9600, 1=19200, 2=38400: ";
    getInputLong(portBPS, "You must enter a number between 0 - 2: ",0,2);
    std::cout << "What is the index number of the device (usually 0): ";
    getInputLong(cardNbr, "You must enter a number: ");
    break;
  case 3: 
    portname = "ETHERNET"; 
    std::cout << "What is the ip address of the device: ";
    std::cin >> ipaddr;
    std::cout << "What is the index number of the device (usually 0): ";
    getInputLong(cardNbr, "You must enter a number: ");
    break;
  case 4: 
    portname = "USB"; 
    std::cout << "What is the index number of the device (usually 0): ";
    getInputLong(cardNbr, "You must enter a number: ");
    break;
  default:
    portname = "Unknown"; 
    transport = 0;
    break;
  }  

  // Connect to Device 
  gStat->nBus = busType;
  gStat->nPort = portNbr;
  gStat->nBPS = bps[portBPS];
  gStat->bstrIP = _bstr_t(ipaddr.c_str());
  std::cout << "\nConnecting...";
  gStat->Connect(transport,cardNbr);
  if(gStat->isOffline){
    std::cout << "you have choosen not to connect, goodbye" << std::endl;
    return 0;
  }
  std::cout << "you are now connected using the " << portname << " port.\n\n";
  std::cout << "Use the Upper Case S key followed by <Enter> to stop watching a parameter.\n";
  std::cout << "Use the Upper Case Q key followed by <Enter> to quit.\n\n";
  // p6916 is the global system clock and will generate lots of events.
  std::cout << "What p-Parameter would you like to monitor (enter in the form P6916): ";
  std::cin >> pparm;

  // Initialize Status Event and add in Status request
  alert = new CStatEvent(gStat);
  // The AddACRCustom allows up to 32 p-Parameters per status request, but this
  // sample will only display the first value entered.
  long MessageID = gStat->AddACRCustom(_bstr_t(pparm.c_str()));
  std::cout << std::endl;
  std::cout << "Parameter " << pparm << " has been added under message id:" << MessageID << std::endl;

  // The interactive loop (i.e. type in stuff and hit enter to submit.)
  while ((std::cin >> input) && (input != "Q")){  
    if(input == "S"){
      gStat->DelStatus(MessageID);
      std::cout << "The pparm added under message id:" << MessageID << " has been stopped.\n\n";
      std::cout << "What p-Parameter would you like to monitor (enter in the form P6916): ";
      std::cin >> pparm;
      long MessageID = gStat->AddACRCustom(_bstr_t(pparm.c_str()));
      std::cout << "Parameter " << pparm << " has been added under message id:" << MessageID << std::endl;
    }
  }

  // Close the COM stuff down
  gStat->DelStatus(MessageID);
  gStat->Disconnect();
  delete alert;
  gStat = NULL;         // Setting smart pointers to NULL is *VERY IMPORTANT*
  CoUninitialize();

	return 0;

  // Error Handling - the errors specifically thrown by Communications Server
  // show up as COM exceptions and can be caught with the _com_error class.
  }catch(_com_error err){
    delete alert;
    gStat = NULL;  // Setting smart pointers to NULL is *VERY IMPORTANT*
    CoUninitialize();
    MessageBox(NULL, err.Description(), "COM Error", MB_OK);
    return 0;
  }catch(...){
    delete alert;
    gStat = NULL;  // Setting smart pointers to NULL is *VERY IMPORTANT*
    CoUninitialize();
    LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL);
    MessageBox(NULL, (LPCTSTR)lpMsgBuf, "General Error", MB_OK);
    LocalFree(lpMsgBuf);
    return 0;
  } 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -