1. 程式人生 > >VC6.0利用Active X控制元件開發串列埠通訊軟體

VC6.0利用Active X控制元件開發串列埠通訊軟體

 MSComm控制元件

  Visual C++為我們提供了一種好用的ActiveX控制元件Microsoft Communications Control(即MSComm)來支援應用程式對串列埠的訪問,在應用程式中插入MSComm控制元件後就可以較為方便地實現對通過計算機串列埠收發資料。

  要使用ActiveX控制元件MSComm,程式設計師必須將其新增入工程,其方法是:

  (1)單擊主選單project的子選單Add To project的Components and Controls選項;

  (2)在彈出的"Components and Controls Gallery"對話方塊中選擇Registered ActiveX Controls資料夾中的"Microsoft Communications Control,version 6.0"選項,如下圖:


  單擊其中的"Insert"按鈕,MSComm控制元件就被增加到工程中了。與此同時,類CMSComm的相關檔案mscomm.h和mscomm.cpp也一併被加入Project的Header Files和Source Files中。當然,程式設計師可以自己修改檔名,如下圖:


  直接分析mscomm.h標頭檔案就可以完備地獲取這個控制元件的使用方法(主要是public型別的介面函式),下面我們摘取了標頭檔案的主要程式碼並對其關鍵部分給出了註釋:

#if !defined(AFX_MSCOMM_H__)
#define AFX_MSCOMM_H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++

// NOTE: Do not modify the contents of this file. If this class is regenerated by
// Microsoft Visual C++, your modifications will be overwritten.

/////////////////////////////////////////////////////////////////////////////
// CMSComm wrapper class

class CMSComm : public CWnd
{
protected:
 DECLARE_DYNCREATE(CMSComm)
public:
 CLSID const& GetClsid()
 {
  static CLSID const clsid = { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } };
  return clsid;
 }
 virtual BOOL Create(LPCTSTR lpszClassName,
   LPCTSTR lpszWindowName, DWORD dwStyle,
   const RECT& rect,
   CWnd* pParentWnd, UINT nID,
   CCreateContext* pContext = NULL)
 { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }

 BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,
   const RECT& rect, CWnd* pParentWnd, UINT nID,
   CFile* pPersist = NULL, BOOL bStorage = FALSE,
   BSTR bstrLicKey = NULL)
 { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
  pPersist, bStorage, bstrLicKey); }

  // Attributes
 public:

  // Operations
 public:
  void SetCDHolding(BOOL bNewValue);
  BOOL GetCDHolding();
  void SetCommID(long nNewValue);
  long GetCommID();
  void SetCommPort(short nNewValue);
  //設定埠號,如nNewValue =1表示COM1
  short GetCommPort();
  void SetCTSHolding(BOOL bNewValue);
  BOOL GetCTSHolding();
  void SetDSRHolding(BOOL bNewValue);
  BOOL GetDSRHolding();
  void SetDTREnable(BOOL bNewValue);
  BOOL GetDTREnable();
  void SetHandshaking(long nNewValue);
  long GetHandshaking();
  void SetInBufferSize(short nNewValue);
  short GetInBufferSize();
  void SetInBufferCount(short nNewValue);
  short GetInBufferCount();
  void SetBreak(BOOL bNewValue);
  BOOL GetBreak();
  void SetInputLen(short nNewValue);
  short GetInputLen();
  void SetNullDiscard(BOOL bNewValue);
  BOOL GetNullDiscard();
  void SetOutBufferSize(short nNewValue);
  short GetOutBufferSize();
  void SetOutBufferCount(short nNewValue);
  short GetOutBufferCount();
  void SetParityReplace(LPCTSTR lpszNewValue);
  CString GetParityReplace();
  void SetPortOpen(BOOL bNewValue);
  //開啟或關閉串列埠,TRUE:開啟,FALSE:關閉
  BOOL GetPortOpen();
  //串列埠是否已開啟,TRUE:開啟,FALSE:關閉
  void SetRThreshold(short nNewValue);
  //如果設定為1,表示一接收到字元就傳送2號事件
  short GetRThreshold();
  void SetRTSEnable(BOOL bNewValue);
  //硬體握手使能?
  BOOL GetRTSEnable();
  void SetSettings(LPCTSTR lpszNewValue);
  //Settings由4部分組成,其格式為:"BBBB,P,D,S",即"波特率,是否奇偶校驗,資料位 //個數,停止位",如設定為:"9600,n,8,1"
  CString GetSettings();
  void SetSThreshold(short nNewValue);
  //如果保持預設值0不變,則表示傳送資料的過程中串列埠上不發生事件
  short GetSThreshold();
  void SetOutput(const VARIANT& newValue);
  //一個非常重要的函式,用於寫串列埠,注意其接收的輸入引數為VARIANT型別物件,
  //我們需要將字串轉化為VARIANT型別物件
  VARIANT GetOutput();
  void SetInput(const VARIANT& newValue);
  VARIANT GetInput();
  //一個非常重要的函式,用於讀串列埠,注意其返回的是VARIANT型別物件,我們需要
  //將其轉化為字串
  void SetCommEvent(short nNewValue);
  short GetCommEvent();
  //一個非常重要的函式,獲得串列埠上剛發生的事件("事件"可以理解為軟體意義上的
  //"訊息"或硬體意義上的"中斷"),事件的傳送會導致OnComm訊息的誕生!
  void SetEOFEnable(BOOL bNewValue);
  BOOL GetEOFEnable();
  void SetInputMode(long nNewValue);
  long GetInputMode();
 };

 //{{AFX_INSERT_LOCATION}}
 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif


  分析上述原始碼可知,基本上,MSComm的諸多介面可以分為如下幾類:

  (1)開啟與設定串列埠介面函式;

  (2)獲得串列埠設定和串列埠狀態介面函式;

  (3)設定串列埠傳送資料方式、緩衝區介面及傳送資料介面函式;

  (4)設定串列埠接收資料方式、緩衝區介面及接收資料介面函式;

  (5)設定與獲取串列埠上發生的事件介面函式。

摘要:本文介紹了在Microsoft Visual C++ 6.0環境下通過對Active X控制元件的程式設計來實現串列埠的通訊的一般方法。

  一、 引言

  當我們在Windows作業系統下開發序列通訊程式時通常不得不面對許多複雜的API函式,因為在Windows作業系統下不能直接對裝置埠進行操作,也不能在系統級(Ring 3級別)使用任何DOS或BIOS中斷,如要對埠進行程式設計則只能以檔案的形式來對埠進行操作,這就使開發人員不得不面對非常煩瑣的API函式程式設計。本文對此提出了另外一種封裝性很好的使用Microsoft Visual C++ 6.0自帶的"Microsoft Communications Control,version 6.0"Active X控制元件的程式設計方法,通過對該控制元件的正確使用,我們可以比較輕鬆地編寫出所需的序列通訊程式。

  下面,我們將結合一個實際的程式示例來對此方法進行說明。本程式的程式設計環境是Windows 98和Microsoft Visual C++ 6.0。在本程式示例中對為避免阻塞而對執行緒的使用以及在使用中遇到的一些問題也做了詳細的介紹。

  二、 程式的設計實現

  在開始進行程式碼程式設計前,首先以在工程中插入元件或控制元件的方式將Active X控制元件"Microsoft Communications Control,version 6.0"加入到工程中來,此時將會在工程中新增一個關於此控制元件的新類。使用該控制元件的一些方法和屬性時不能象使用類一樣簡單的宣告一個例項物件,而要通ClassWizard為該控制元件和一個成員變數建立起繫結關係,在此我們將該控制元件同變數m_Comm相繫結後就可以通過該控制元件提供的方法來對串列埠的各種通訊引數進行設定了。為了程式設計方便起見,也可以在資源檢視中直接對該控制元件的屬性進行設定,如無特別要求,對下表所列屬性進行設定就基本可以滿足程式設計要求了。現將常用的屬性列表如下:

屬性 設定值 屬性說明
CommPort  1  串列埠號,一般從1到4
InBufferSize 30720 接收緩衝區大小,為保持程式的穩定,建議設得值足夠大
InputMode 0-Text  接收資料的型別,0表示文字型別,1表示二進位制型別
InputLen 0  從接收緩衝區讀取的位元組數,0表示全部讀取 
OutBufferSize 512  傳送緩衝區大小
Settings  4800,n,8,1 串列埠的引數設定,依次為波特率、奇偶校驗(n-無校驗,e-偶校驗,o-奇校驗)、資料位數、停止位數
RThreshold 1  設定當接收幾個字元時觸發OnComm事件,0表示不產生事件,
1表示每接收一個字元就產生一個事件 
SThreshold  0  設定在觸發OnComm事件前,傳送緩衝區內所允許的最少的字元數,
0表示傳送資料時不產生事件,1表示當傳送緩衝區空時產生OnComm事件

  我們要求能在程式啟動的同時就開啟串列埠以便即時對從串列埠到達的資料進行接收、處理。一般來說可以將下面的開啟埠的程式碼寫在OnCreate()、OnInitialUpdate()、InitInstance ()等程式入口函式中:

……
if(!m_Comm.GetPortOpen()) //檢測是否已經開啟過埠
m_Comm.SetPortOpen(TRUE); //如沒有開啟則將埠開啟
 

接下來的工作就是對資料的傳送與接收了,這也是本文所要介紹的重點所在。傳送資料的程式碼原則上是可以寫到一個成員函式中被直接呼叫的,但這並不是一個良好的程式設計習慣:我們應當把比較耗時的操作,如檔案拷貝、列印、埠傳輸等工作放到一個單獨的執行緒當中,以避免其在工作時會引起整個程序的阻塞,以提高整個系統對CPU的利用率。例如我們可以在視類中選單或按鈕的響應函式中用AfxBeginThread(WriteProc,this)函式來開啟一個名為"WriteProc"的執行緒,由於線上程中還需要使用視類的函式和變數,為了不產生新的視類的例項物件,我們通過該函式的第二個引數將指向當前的視類的指標this作為引數傳遞給執行緒。線上程中可以用如下兩種方法之中的一種呼叫視類的成員函式:

((COLECommView*) pParam)->DoSendProc();

  或是:

COLECommView* view=(COLECommView*) pParam;
View->DoSendProc();
 

  其中從pParam傳來的變數就是指向視類的指標。線上程中通過呼叫視類中的DoSendProc函式來完成對資料的傳送,正是由於該函式是被全域性的執行緒所呼叫的,我們就不可以使用取編輯框上的資料時通常所用的UpdateData()函數了,取而帶之的是API 函式GetDlgItemText(),取到輸入的資料後通過控制元件的SetOutput() 方法就把資料從串列埠發出去了,其中傳送資料必須經ColeVariant類將其轉換為通用的VARIANT型變數。實現
主要程式碼如下:

……
char a[255];
HWND hwnd=GetSafeHwnd();
::GetDlgItemText(hwnd,IDC_EDIT1,a,255);
int i=0;
CString str;
while(a[i]!='\0')
{
str.Format("%c",a[i]);
m_SendData+=str;
i++;
}
str.Format("%c",10);
m_SendData+=str;
m_Comm.SetOutput(COleVariant(m_SendData));
……

  至於資料的接收,我們可以通過讓MS Comm控制元件響應其OnComm事件來完成,通過ClassWizard加入其對事件的響應後,通過下面的事件對映,當有字元到達時便會通知 OnComm()函式去處理,從而實現資料的非同步接收:

……
BEGIN_EVENTSINK_MAP(COLECommView, CFormView)
//{{AFX_EVENTSINK_MAP(COLECommView)
ON_EVENT(COLECommView, IDC_MSCOMM1, 1 /* OnComm */, OnComm, VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
……
void COLECommView::OnComm()
{
VARIANT Input;
if(m_Comm.GetCommEvent()==2)//接收緩衝區內有字元
{
Input=m_Comm.GetInput();//讀取緩衝區內的資料
CString msg=Input.bstrVal;
CString str;
str.Format("%c",10);
if(msg.Right(1)==str)
{
m_RecvData+=msg;
m_History.AddString(m_RecvData);
m_RecvData="";
}
else
m_RecvData+=msg;
}
}
 

  當資料被接收到接收緩衝區後,對於字元可以從VARIANT型結構變數的bstrVal成員變數中獲取,VARIANT資料結構相當複雜,並牽扯到COM(Component Object Model,元件物件模型)中的一些概念,具體詳情請參閱Microsoft Corpration釋出的MSDN中的有關論述。

  三、 測試與實驗

  編譯執行程式之前有必要對機器的埠做一番檢查,以確保埠的完好,可以用常見的DOS程式Comdebug來檢查。在確認串列埠工作正常後,可用串列埠線將兩臺機器的串列埠相連,同時在兩臺機子上執行該程式,如果沒有條件也可只用一臺微機,將其串列埠的2腳和3腳短接,使其處於自發自收狀態。經過資料的傳輸實驗證明該程式是可靠、正確的。

  小結:利用通訊控制元件可以很容易的編寫出序列通訊程式。但相對來說通訊控制元件在VC中的使用要比在VB、Delphi中複雜的多,要想對串列埠通訊開發出更多更靈活的使用方法還需要不斷的實踐中摸索。本程式在
Windows 98下,由Microsoft Visual C++ 6.0編譯通過。

相關推薦

VC6.0利用Active X控制元件開發串列通訊軟體

 MSComm控制元件   Visual C++為我們提供了一種好用的ActiveX控制元件Microsoft Communications Control(即MSComm)來支援應用程式對串列埠的訪問,在應用程式中插入MSComm控制元件後就可以較為方便地實現對通過計算機

MFC中利用MSComm控制元件實現串列通訊的例子

第一步:建工程 第二步:設定基本對話方塊 第三步:設定串列埠ID號 第四步:設定串列埠引數選項 第五步:設定其他控制元件ID號 第六步:新增串列埠控制元件 project->

MFC串列通訊(二)——使用MSComm控制元件實現串列通訊

  由於專案需要,最近在寫一個簡單的串列埠通訊,基於MFC框架,寫完之後特此回顧記錄一下學習的過程: 串列埠通訊主體框架 (1) 初始化介面(自動獲取全部可用串列埠) (2) 開啟串列埠 (讀取串列埠號,初始化串列埠引數(波特率、校驗位、資料位等),若

什麼是Active X控制元件

一個典型的空間包括設計時和執行時的使用者介面,唯一的IDispatch介面定義控制元件的方法和屬 性,唯一的IConnectionPoint介面用於控制元件可引發的事件。除此之外,一個控制元件還可以包含對 其整個生命週期的一執性支援,以及對剪貼,拖放等使用者介面特性的支援。從結構上看,一 個控制元件有大量必須

基於VC6.0 MFC的簡單串列通訊軟體程式設計總結

想想上回玩VC是幾年前搞畢設時的事了,這回編這個串列埠軟體也花了好幾天時間,做個小結積累一下吧: (一)基於對話方塊程式設計基本步驟: 1.新建基於對話方塊的工程; 2.拖曳所需的基本控制元件,構成介面; 3.使用類嚮導(CLASS WIZARD)建立與基本控制元件對應的成員

QT開發串列通訊軟體(基於qextserialport工具)

研一上了楊迎澤老師的一門《列車網路與通訊》課程,課程的最後老師給我們分配的小作業居然是寫上位機控制一臺程控電流源,我在查閱了這臺程控電流源的手冊後,發現它的通訊方式是串列埠,而且在串列埠通訊的基礎上指定了一套詳細的通訊協議,基於此,我花了小半天的時間做了一個上位機,完成了任務,這裡主要分享一下基

如何用Delphi開發串列通訊程式

       Delphi 是新一代視覺化開發工具,它具有功能強大、簡便易用和程式碼執行速度快等特點,Delphi系列開發工具在國際各媒體上曾獲得過三十多項大獎,是全球公認的快速應用開發工具技術的先驅者,他越來越在構架企業資訊系統方面發揮著重要作用。 它的功能很強大,但在對串列埠通訊的控制上Delphi的幫助

VC6.0利用ado元件 向oracle資料庫插入圖片

oracle 資料庫中用Bolb儲存圖片 一、資料庫表設定 1、建立表 create table epoliceadmin.ep_image(image_id number(10) not null primary key, image blob); 2、建立序列 crea

VC++6.0 MFC將列表控制元件中內容儲存到EXCEL

1、獲取工作路徑  //獲取工作路徑 CString GetWorkDir() { char pFileName[MAX_PATH]; int nPos=GetCurrentDirectory( MAX_PATH, pFileName); CString csF

Android 開發之自定義控制元件開發-01

最近一直在忙於公司的專案,因為要去現場測試正式使用,專案不大但是經手了三個人,到我這裡只能去填坑了,不說這個了,說一下今天得主題,自定義控制元件之基本圖形繪製。 我們平時畫圖需要兩種工具:紙和筆。在Android中 Paint 就是畫筆,而Canvas類就是紙,在這裡叫做畫布。 所以

Android CardView的使用詳解(和RecycView一樣5.0以後出現的控制元件)

一、引入CardView    CardView和 RecyclerView 一樣是Android5.0以後新出現的控制元件,伴隨著Material Design設計而誕生。   在AS新建專案中需要使用CardView元件

vs2010怎麼在2.0下使用ReportViewer控制元件

請問如何登陸這樣的網站傳遞引數接受結果並獲取cookie請教如何高效篩選出兩個陣列共同部分請問如何登陸這樣的網站傳遞引數接受結果並獲取cookie請教如何高效篩選出兩個陣列共同部分 生成機器碼和註冊碼給軟體加密。遠端桌面連線的問題生成機器碼和註冊碼給軟體加密。遠端桌面連線的問

基於python3.6+pyQT5利用Graphics View 控制元件顯示影象並實現其縮放

     利用eric6+QTdesigner 實現了軟體介面的編寫,軟體介面如圖所示,一共有三個控制元件(放大按鈕、縮小按鈕以及Graphics View),具體佈置如圖所示,將按鈕項式名稱改為“放大”、“縮小”。 然後編譯介面,生成程式碼如下: from Py

JavaScript日曆控制元件開發

概述 本文的目的除了詳細說明開發一款具備基本功能的網頁日曆的方法與細節以外,還附加說明了如何合理的組織日曆特效的程式碼和因此帶來的好處。 按照本文的教程開發出來的效果如下 他具有選擇年月日、選擇今天、清空文字框這些日曆的基本功能,能滿足日常專案中出現的普通日期選擇需求, 算的上是五臟俱全的小麻雀。 本文主

wpf控制元件開發基礎(3) -屬性系統(2)

原文: wpf控制元件開發基礎(3) -屬性系統(2)     上篇說明了屬性存在的一系列問題. 屬性預設值,可以保證屬性的有效性. 屬性驗證有效性,可以對輸入的屬性進行校驗 屬性強制回撥, 即不管屬性有無發生變化,都要做出通知. 屬性變更通知,當屬性發生變

wpf控制元件開發基礎(4) -屬性系統(3)

原文: wpf控制元件開發基礎(4) -屬性系統(3) 知識回顧 接上篇,上篇我們真正接觸到了依賴屬性的用法,以及依賴屬性的屬性元資料的用法,並且也實實在在地解決了之前第二篇提到的一系列問題.來回顧一下 屬性預設值 屬性變更通知 屬性強制回撥 本篇將繼續討論上一篇提到的問題,主題依然是

wpf控制元件開發基礎(5) -依賴屬性實踐

原文: wpf控制元件開發基礎(5) -依賴屬性實踐 知識回顧 接上篇,回顧這三篇講了什麼東西 首先說明了屬性的現存問題,然後介紹了依賴屬性的基本用法及其解決方案,由於依賴屬性以靜態屬性的方式存在,進而又介紹了可重寫的屬性元資料的使用.這是以上三篇所說明的問題.當然依賴屬性的特性依然沒有說完整.這兩天也

[前端控制元件開發]freemarker框架下編寫自己的分頁器

對於web系統來說,分頁器就好像是一個器官,是無論如何都必須要具備的一項功能,而分頁器呢,是既通用又無怪乎那麼幾種樣子,所以我們這裡就利用添加了freemarker框架的一個系統來做自己的分頁器。先看下結果樣子: 具體的展示樣式是可以自己隨意調整的,這裡我採取的是每一頁

註解學習之利用註解查詢控制元件

轉自:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 學習註解之前首先要理解元註解,元註解是用來註解自定義註解的註解 Java5.0定義了4個標準的meta-annotation型別,它們被用來提供對其它 annotation

利用File Input控制元件修改name屬性

接著:【FE】File Input多次新增檔案,動態刪除檔案,用來實現上傳等操作 一文 1.想方設法 我們首先查閱資料後發現 fileList的name屬性是隻讀的MDN 修改只讀屬性: