在Visual C++ 6.0中使用串行通訊控件

發表于:2007-07-14來源:作者:點擊數: 標簽:
山東科技大學智能工程研究所 楊在春 最近,在互聯網上發現許多Visual C++愛好者求助如何使用MSComm串行通訊控件,筆者也讀到過一些關于使用MSComm通訊控件的文章,大部分只是從表面上泛泛地做了介紹,沒有涉及到真正的程序實現,讀者仍然無法使通訊控件工作
山東科技大學智能工程研究所 楊在春  

最近,在互聯網上發現許多Visual C++愛好者求助如何使用MSComm串行通訊控件,筆者也讀到過一些關于使用MSComm通訊控件的文章,大部分只是從表面上泛泛地做了介紹,沒有涉及到真正的程序實現,讀者仍然無法使通訊控件工作起來。其實,在VC++6.0中使用通訊控件,還必須了解COleVariant與動態數組等一些知識?,F在我單位正與濟寧二號煤礦合作開發“井下采區變電所微機集中監控系統”,我所選用的開發環境即為Visual C++6.0,其中的通訊功能都是由MSComm通訊控件完成的,本人希望能通過本文將在程序開發過程中的一些體會和心得奉獻給廣大讀者。
在Visual C++6.0中使用串行通訊控件,至少應該從以下幾個方面進行考慮:
1.如何引入通訊控件
如果使用的是其他可視化程度較高編程語言,如VB、C++ Builder或Delphi等,通訊控件可以被直接引入到任意某個窗體之中,而使用Visual C++時,只有通過對話框資源編輯器來引入通訊控件到對話框中或由CFormView派生而來的視圖中。如果選擇的對話框是模態的,則在使用通訊控件時必須打開該對話框,這對于基于對話框的應用程序使用十分方便。如果不想使用對話框的話,則可將程序的視圖類設計為由CFormView派生而來的視圖。CFormView與相應的對話框資源相關聯,具有很多對話框的特點,這樣,我們可以將通訊控件直接引入到程序視圖之中。后面這種方法的缺點是視圖的使用受到了很大的限制。下面介紹另外一種使用比較方便,且更加有效的方法。
同樣,我們還是將通訊控件引入到對話框中,只是將對話框做成非模態的。如果沒有其他需要的話,對話框中只包含通訊控件一個元素,且在程序執行時,該對話框始終處于不可視狀態。設計時程序中任何地方,只要能訪問到該對話框,就可使用其中的通訊控件。下面介紹非模態對話框CCommDlg的制作及其使用方法,CCommDlg由CDialog派生而來。由于在程序執行過程中對話框是不可視的,用戶不可能對其進行任何操作,因此不需要處理對話框的確定和取消按鈕的響應消息。為了方便起見,只需向其中增加一個BOOL類型的成員函數Create(),定義如下:
BOOL CCommDlg::Create()
{
return CDialog::Create(CCommDlg::IDD);
}
另外,由于對話框是不可視的,必須通過對話框資源編輯器將其Visible屬性設置掉。
由于主框架窗口CMainFrame是程序的主窗口,程序其他部分的代碼很容易通過函數AfxGetMainWnd或其他方法訪問到CMainFrame類型的成員,并程序的主窗口的C++對象和其窗口對象在程序的運行過程中總是有效的,直到程序運行結束才將其釋放和析夠。因此,我們可以在CMainFrame中增加一個指向CCommDlg類型的指針變量:CCommDlg * m_pCommDlg,在CMainFrame的OnCreate成員函數構造并創建該對話框,代碼如下所示:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
……
m_pCommDlg = new CCommDlg();
if(!m_pCommDlg)return -1;
m_pCommDlg->Create();
……
}
m_pCommDlg對象創建成功后,其C++對象和窗口對象一直處于有效狀態,直到程序結束時,才用下面的代碼在CMainFrame的析夠函數中將其釋放:
CMainFrame::~CMainFrame()
{
if(m_pCommDlg)
{
if(m_pCommDlg->GetSafeHwnd())
m_pCommDlg->DestroyWindow();
delete m_pCommDlg;  
}
……
}
這樣,在程序的執行過程中,我們就可以通過訪問m_pCommDlg來訪問通訊控件m_Comm,比如程序語句:m_pCommDlg->m_Comm.SetPortOpen(true)可以用來打開通訊端口。注意,上述存放通訊控件的對話框是不可視的,若想使其成為可視的,并能夠完成一些如設置通訊控件的功能的話,還需要做一些額外的工作。
2.發送通訊數據
在Visual C++ 中,通訊控件發送數據的任務是由其接口成員函數SetOutput來實現的,該函數使用的參數是const VARIANT &newValue。VARIANT其實是一個C++結構類型,COleVariant類型對VARIANT做了進一步的封裝和擴展,提供了許多新的功能和操作方法,支持OLE自動化,且更容易向其數據成員填入數據。由于COleVariant類型由VARIANT派生而來,因此將COleVariant類型的變量傳遞給SetOutput函數更為方便。另外,SetOutput的參數newValue類型必須是存放字節類型數據的動態數組。因此,可以利用Visual C++提供CByteArray類型來構造COleVariant類型的對象,并將其傳遞給SetOutput函數。對CByteArray類型變量的操作相對來說要容易的多,比如其成員函數SetSize可用來設置動態數組的大小,下標操作符[]可用來為其元素賦值等等。下面的程序代碼可實現將存放在緩沖區strBuf中的100個字節的數據通過通訊控件發送出去:
……
BYTE strBuf[128];
CByteArray OutBuf;
COleVariant varOutput;
……
OutBuf.SetSize(100);
for(i=0;i<100;i++)OutBuf[i] = strBuf[i];
varOutput = OutBuf;
m_pCommDlg->m_Comm.SetOutput(varOutput);
……
利用通訊控件發送數據的關鍵在于構造COleVariant類型的變量,并向其中填入通訊數據,使其能滿足通訊控件的成員函數SetOutput的需要。上面的程序語句varOutput = OutBuf可以直接寫成:
COleVariant varOutput(OutBuf);
但這樣必須將變量varOutput的定義語句COleVariant varOutput刪除掉。
3.接收通訊數據
通訊控件接收通訊數據的任務是通過其接口成員函數GetInput來實現的,該函數的返回值的類型為VARIANT,同樣我們可以將其賦值給COleVariant類型的變量。進一步,我們必須知道,該函數返回值變量的有效成員為parray,其類型定義為SAFEARRAY FAR*,即parray為一個安全數組指針,且數組的元素類型為BYTE。因此,對GetInput函數返回值的訪問,可以通過安全數組操作函數來實現,比如:讀取數組的維數、下邊界、上邊界以及各個元素的實際的值等。該返回值變量所對應的安全數組的維數為1,下邊界為0。根據上述分析,下面的程序代碼基本能夠實現利用通訊控件接收通訊數據:
CByteArray ByteBuf;
COleVariant varInput;
long ix,l,u;
BYTE bit;
……
varInput = m_pCommDlg->m_Comm.GetInput();
if(varInput.parray!=NULL)
{
SafeArrayGetLBound(varInput.parray,1,&l);
SafeArrayGetUBound(varInput.parray,1,&u);
for(ix=l;ix<=u;ix++)
{
SafeArrayGetElement(varInput.parray,&ix,&bit);
ByteBuf.Add(bit);
}
}
……
4.小結
本文講述的利用通訊控件發送與接收通訊數據都是基于二進制來實現的,基于文本的情況基本與此類似。要想利用好通訊控件還有其他一些應該注意的地方,比如波特率的設置、接收與發送緩沖區的設置以及通訊過程中的延時問題的處理等等。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97