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

📄 cppterminal.cpp

📁 介绍控制器运动的例子
💻 CPP
字号:
// CPPTerminal.cpp : Simple Terminal using a console.
// The application asks the user for connection information and then allows line by
// line input to the device.  Data returned is signaled by a read event and sent to
// the standard output.  This is an example of how a non-MFC C++ program can directly 
// use the Terminal Interface, and by inference, all other interfaces.  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 ReadAlertInfo = {CC_STDCALL, VT_EMPTY, 0, {VT_EMPTY}};

//-----------------------------------------------------------------------------
// 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 CReadEvent:
	public IDispEventSimpleImpl<1, CReadEvent, &DIID__ITerminalEvents>
{
  // The CReadEvent will provide a callback for the DataWaiting Event on the Terminal
  // 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:
  CReadEvent(ITerminalPtr term)
  {
    // 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_Term = term;
    HRESULT hr = DispEventAdvise((IUnknown*)m_Term);
  }
  virtual ~CReadEvent()
  {
    DispEventUnadvise((IUnknown*)m_Term);
    m_Term = NULL;  // Setting smart pointers to NULL is *VERY IMPORTANT*
  }
  void __stdcall ReadAlert()
  {
    // Data is waiting to be read, send it to the std out
  try{
    m_Read = m_Term->Read();
    std::cout << _com_util::ConvertBSTRToString(m_Read);
  }catch(...){ return; /*ignore errors here*/ }
  }

  // The IDL used for this event is:
  //
	//  [ uuid(A1C9E9E2-49BB-40A8-8A9B-301051D224F2),
	//    helpstring("_ITerminalEvents Interface")]
	//    dispinterface _ITerminalEvents
	//  {	properties:
	//    methods:
	//    [id(1), helpstring("Data Waiting to be Read")] HRESULT DataWaiting();
  //  };
  //
  // Information mapped by the ATL class (above) supports Connection Points.
  //
BEGIN_SINK_MAP(CReadEvent)
	SINK_ENTRY_INFO(1, DIID__ITerminalEvents, 1, ReadAlert, &ReadAlertInfo)
END_SINK_MAP()

private:
  ITerminalPtr m_Term;  // smart pointer from #import
  _bstr_t m_Read;       // hold data read from device
};

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 Terminal Interface pointer is 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. 
  ITerminalPtr gTerm;
  CReadEvent* alert = NULL;

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

  // Establish Communication Server
  gTerm.CreateInstance(CLSID_Terminal);
  std::string ver = std::string(_com_util::ConvertBSTRToString(gTerm->bstrVersion)); // Version
  std::cout << "--------Simple Terminal 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::cout << "How are we connecting.  Type in a number and press <enter>\n1=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 
  gTerm->nBus = busType;
  gTerm->nPort = portNbr;
  gTerm->nBPS = bps[portBPS];
  gTerm->bstrIP = _bstr_t(ipaddr.c_str());
  std::cout << "\nConnecting...";
  gTerm->Connect(transport,cardNbr);
  if(gTerm->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\nEnter the word QUIT (in UPPER CASE) to exit.\n\n";

  // Initialize Read Event
  gTerm->Write(_bstr_t("echo0\r"));       // data is echoed locally in this terminal
  Sleep(100);
  _bstr_t dummy = gTerm->Read();          // clear out read buffer           
  alert = new CReadEvent(gTerm);          // start reading
  gTerm->Write(_bstr_t("ver\r"));         // display device version

  // The Terminal - line based data entry (i.e. type in stuff and hit enter to submit.)
  while ((std::cin >> input) && (input != "QUIT")){  
    input += '\r';
    gTerm->Write(_bstr_t(input.c_str())); // write out characters
  }

  // Close the COM stuff down
  gTerm->Disconnect();
  delete alert;
  gTerm = 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;
    gTerm = NULL;  // Setting smart pointers to NULL is *VERY IMPORTANT*
    CoUninitialize();
    MessageBox(NULL, err.Description(), "COM Error", MB_OK);
    return 0;
  }catch(...){
    delete alert;
    gTerm = 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 + -