home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / general / vcterm / mainfrm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  15.9 KB  |  637 lines

  1. // mainfrm.cpp : implementation of the CMainFrame class
  2. //
  3.  
  4. // This is a part of the Microsoft Foundation Classes C++ library.
  5. // Copyright (C) 1992-1998 Microsoft Corporation
  6. // All rights reserved.
  7. //
  8. // This source code is only intended as a supplement to the
  9. // Microsoft Foundation Classes Reference and related
  10. // electronic documentation provided with the library.
  11. // See these sources for detailed information regarding the
  12. // Microsoft Foundation Classes product.
  13.  
  14. #include "stdafx.h"
  15. #include "vcterm.h"
  16. #include "mainfrm.h"
  17. #include "setdlg.h"
  18. #include "inputdlg.h"
  19.  
  20. #include "io.h"
  21. #include "candlg.h"
  22. #include "winnls.h"
  23.  
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CMainFrame
  32.  
  33. IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
  34.  
  35. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  36.     //{{AFX_MSG_MAP(CMainFrame)
  37.     ON_WM_CREATE()
  38.     ON_WM_ACTIVATE()
  39.     ON_WM_CLOSE()
  40.     ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_OPENLOG, ID_FILE_TRANSMIT, OnUpdateFile)
  41.     ON_COMMAND(ID_FILE_OPENLOG, OnFileOpenlog)
  42.     ON_COMMAND(ID_FILE_CLOSELOG, OnFileCloselog)
  43.     ON_COMMAND(ID_FILE_TRANSMIT, OnFileTransmit)
  44.     ON_UPDATE_COMMAND_UI_RANGE(ID_COMM_OPEN, ID_COMM_HANGUP, OnUpdateCommPort)
  45.     ON_COMMAND_RANGE(ID_COMM_OPEN, ID_COMM_HANGUP, OnCommPort)
  46.     ON_UPDATE_COMMAND_UI(ID_PROP_DTRENABLE, OnUpdatePropDTREnable)
  47.     ON_COMMAND_RANGE(ID_PROP_INPUTLEN, ID_PROP_DSRHOLDING, OnProperties)
  48.     //}}AFX_MSG_MAP
  49. END_MESSAGE_MAP()
  50.  
  51. // add eventsink map to hook OnComm event
  52. BEGIN_EVENTSINK_MAP(CMainFrame, CFrameWnd)
  53.     ON_EVENT(CMainFrame, ID_COMMCTRL, 1 /* OnComm */, OnCommEvent, VTS_NONE)
  54. END_EVENTSINK_MAP()
  55.  
  56. static UINT indicators[] =
  57. {
  58.     ID_SEPARATOR,           // status line indicator
  59.     ID_INDICATOR_CAPS,
  60.     ID_INDICATOR_NUM,
  61.     ID_INDICATOR_SCRL,
  62. };
  63.  
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CMainFrame construction/destruction
  66.  
  67. CMainFrame::CMainFrame()
  68. {
  69.     m_strPhoneNum.Empty();
  70.     m_strLogFile.Empty();
  71. }
  72.  
  73. CMainFrame::~CMainFrame()
  74. {
  75. }
  76.  
  77. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  78. {
  79.     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  80.         return -1;
  81.  
  82.     if (!m_wndToolBar.Create(this) ||
  83.         !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  84.     {
  85.         TRACE0("Failed to create toolbar\n");
  86.         return -1;      // fail to create
  87.     }
  88.  
  89.     if (!m_wndStatusBar.Create(this) ||
  90.         !m_wndStatusBar.SetIndicators(indicators,
  91.           sizeof(indicators)/sizeof(UINT)))
  92.     {
  93.         TRACE0("Failed to create status bar\n");
  94.         return -1;      // fail to create
  95.     }
  96.  
  97.     m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
  98.         CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
  99.  
  100.     m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
  101.     EnableDocking(CBRS_ALIGN_ANY);
  102.     DockControlBar(&m_wndToolBar);
  103.  
  104.     // Create the MSCOMM32 OLE Control.
  105.     if (!m_commctrl.Create(NULL,0,CRect(0,0,0,0),this,ID_COMMCTRL))
  106.     {
  107.         TRACE0("Failed to create OLE Communications Control\n");
  108.         return -1;      // fail to create
  109.     }
  110.  
  111.     // Set RThreshold property to 1. The default RThreshold value (0)
  112.     // causes the OnComm event to NOT fire when a character is detected
  113.     // in the serial port.
  114.     m_commctrl.SetRThreshold(1);
  115.  
  116.     // Create the Edit control that sits in the mainframe window.
  117.     if (!m_edit.Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_WANTRETURN|
  118.         ES_MULTILINE|ES_AUTOVSCROLL,rectDefault,this,AFX_IDW_PANE_FIRST))
  119.     {
  120.         TRACE0("Failed to create edit control\n");
  121.         return -1;      // fail to create
  122.     }
  123.     // fix up 3D styles
  124.     ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
  125.     m_edit.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED);
  126.  
  127.     return 0;
  128. }
  129.  
  130. /////////////////////////////////////////////////////////////////////////////
  131. // CMainFrame diagnostics
  132.  
  133. #ifdef _DEBUG
  134. void CMainFrame::AssertValid() const
  135. {
  136.     CFrameWnd::AssertValid();
  137. }
  138.  
  139. void CMainFrame::Dump(CDumpContext& dc) const
  140. {
  141.     CFrameWnd::Dump(dc);
  142. }
  143.  
  144. #endif //_DEBUG
  145.  
  146. /////////////////////////////////////////////////////////////////////////////
  147. // CMainFrame message handlers
  148.  
  149. void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
  150. {
  151.     CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
  152.  
  153.     // Set focus to edit control in main window.
  154.     m_edit.SetFocus();
  155. }
  156.  
  157. void CMainFrame::OnUpdateFile(CCmdUI* pCmdUI)
  158. {
  159.     switch(pCmdUI->m_nID)
  160.     {
  161.         // Enable if there is no logfile currently open.
  162.         case ID_FILE_OPENLOG:
  163.             pCmdUI->Enable(m_strLogFile.IsEmpty());
  164.             break;
  165.         // Enable if a log file is currently open.
  166.         case ID_FILE_CLOSELOG:
  167.             pCmdUI->Enable(!m_strLogFile.IsEmpty());
  168.             break;
  169.         // Enable if comm port is open.
  170.         case ID_FILE_TRANSMIT:
  171.             pCmdUI->Enable(m_commctrl.GetPortOpen());
  172.             break;
  173.     }
  174. }
  175.  
  176. void CMainFrame::OnFileOpenlog()
  177. {
  178.     ASSERT(m_strLogFile.IsEmpty());
  179.  
  180.     CFileDialog dlg(TRUE,_T("log"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
  181.     _T("Log Files (*.log) | *.log | All Files (*.*) | *.* ||"),this);
  182.  
  183.     if (dlg.DoModal()==IDOK)
  184.     {
  185.         m_strLogFile = dlg.GetPathName();
  186.  
  187.         if (!m_file.Open(m_strLogFile,CFile::modeCreate|CFile::modeWrite,NULL))
  188.         {
  189.             AfxMessageBox(IDS_FILEOPENFAILED);
  190.             m_strLogFile.Empty();
  191.             return;
  192.         }
  193.  
  194.         // Update mainframe window caption.
  195.         CString str;
  196.         str.Format(_T("VCTerm - %s"),m_strLogFile);
  197.         SetWindowText(str);
  198.     }
  199. }
  200.  
  201. void CMainFrame::OnFileCloselog()
  202. {
  203.     m_file.Flush();
  204.     m_file.Close();
  205.     m_strLogFile.Empty();
  206.     SetWindowText(_T("VCTerm"));
  207. }
  208.  
  209. void CMainFrame::OnFileTransmit()
  210. {
  211.     CFileDialog dlg(TRUE,_T("txt"),NULL,OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,
  212.     _T("Text Files (*.txt) | *.txt | All Files (*.*) | *.* ||"),this);
  213.  
  214.     if (dlg.DoModal()!=IDOK)
  215.         return;
  216.  
  217.     CFile file(dlg.GetPathName(),CFile::modeRead);
  218.  
  219.     // Display cancel dialog.
  220.     EnableWindow(FALSE);
  221.     m_bCancel = FALSE;
  222.  
  223.     CCancelDlg* pDlg = new CCancelDlg(this);
  224.     pDlg->Create(IDD_CANCELDLG,this);
  225.  
  226.     int nBlockSize = m_commctrl.GetOutBufferSize();
  227.     int nFileSize = file.GetLength();
  228.     LPSTR pchBuffer = new char[nBlockSize];
  229.     LPWSTR pchData = new WCHAR[nBlockSize];
  230.  
  231.     VARIANT var;
  232.  
  233.     // Read/Transmit the file in blocks the size of the transmit buffer.
  234.     for (int nRxTx = 0; nRxTx<(nFileSize/nBlockSize) && !m_bCancel; nRxTx++)
  235.     {
  236.         file.Read(pchBuffer,nBlockSize);
  237.  
  238.         // Convert the ASCII text string to a UNICODE string.
  239.         MultiByteToWideChar(CP_ACP,0,pchBuffer,nBlockSize,pchData,nBlockSize);
  240.         var.vt = VT_BSTR;
  241.         var.bstrVal = ::SysAllocStringLen(pchData,nBlockSize);
  242.  
  243.         // Send data to comm port.
  244.         m_commctrl.SetOutput(var);
  245.         SysFreeString(var.bstrVal);
  246.  
  247.         // Wait for the transmit buffer to empty.
  248.         while ((m_commctrl.GetOutBufferCount() > 0) && !m_bCancel)
  249.             DoEvents();
  250.     }
  251.  
  252.     // Dump last bit of file to the transmit buffer.
  253.     int nLeftOver = nFileSize % nBlockSize;
  254.  
  255.     // If file size is identical to Output Buffer size.
  256.     if (!nLeftOver)
  257.         nLeftOver = nBlockSize;
  258.  
  259.     // Read/Transmit the last chunk of the file.
  260.     if (nLeftOver && !m_bCancel)
  261.     {
  262.         file.Read(pchBuffer,nLeftOver);
  263.  
  264.         // Convert the ASCII text string to a UNICODE string.
  265.         MultiByteToWideChar(CP_ACP,0,pchBuffer,nLeftOver,pchData,nLeftOver);
  266.         var.vt = VT_BSTR;
  267.         var.bstrVal = ::SysAllocStringLen(pchData,nLeftOver);
  268.  
  269.         // Send data to comm port.
  270.         m_commctrl.SetOutput(var);
  271.         SysFreeString(var.bstrVal);
  272.  
  273.         // Wait for the transmit buffer to empty.
  274.         while ((m_commctrl.GetOutBufferCount() > 0) && !m_bCancel)
  275.             DoEvents();
  276.     }
  277.  
  278.     // Close out the Cancel dialog.
  279.     if (!m_bCancel)
  280.         pDlg->OnCancel();
  281.  
  282.     delete pchBuffer;
  283.     delete pchData;
  284.     file.Close();
  285.     EnableWindow(TRUE);
  286.     m_edit.SetFocus();
  287. }
  288.  
  289. void CMainFrame::OnClose()
  290. {
  291.     if (m_commctrl.GetPortOpen())
  292.     {
  293.         // Set timeout period for 10 seconds from current time.
  294.         BOOL bTimedOut = FALSE;
  295.         CTime timeOut = CTime::GetCurrentTime() + CTimeSpan(0,0,0,10);
  296.  
  297.         while (m_commctrl.GetOutBufferCount())
  298.         {
  299.             // Process all pending messages.
  300.             m_bCancel=FALSE;
  301.             DoEvents();
  302.  
  303.             if ( (CTime::GetCurrentTime() > timeOut) || bTimedOut)
  304.             {
  305.                 int ret = AfxMessageBox(IDS_DATASENDFAILED,MB_ABORTRETRYIGNORE);
  306.  
  307.                 switch (ret)
  308.                 {
  309.                     // Attempt to send data for another 10 seconds.
  310.                     case IDRETRY:
  311.                         timeOut = CTime::GetCurrentTime() + CTimeSpan(0,0,0,10);
  312.                         break;
  313.                     // Ignore timeout and exit.
  314.                     case IDIGNORE:
  315.                         bTimedOut = TRUE;
  316.                         break;
  317.                     // Abort attempt to exit application.
  318.                     case IDABORT:
  319.                         return;
  320.                 }
  321.             }
  322.         }
  323.         m_commctrl.SetPortOpen(FALSE);
  324.     }
  325.  
  326.     // Close log file if it's currently open.
  327.     if (!m_strLogFile.IsEmpty())
  328.         OnFileCloselog();
  329.  
  330.     CFrameWnd::OnClose();
  331. }
  332.  
  333. void CMainFrame::OnUpdateCommPort(CCmdUI* pCmdUI)
  334. {
  335.     switch(pCmdUI->m_nID)
  336.     {
  337.     case ID_COMM_OPEN:
  338.         if (m_commctrl.GetPortOpen())
  339.             pCmdUI->SetText(_T("&Port Close"));
  340.         else
  341.             pCmdUI->SetText(_T("&Port Open"));
  342.         pCmdUI->Enable();
  343.         break;
  344.  
  345.     case ID_COMM_SETTINGS:
  346.         if (m_commctrl.GetPortOpen())
  347.             pCmdUI->Enable(FALSE);
  348.         else
  349.             pCmdUI->Enable();
  350.         break;
  351.  
  352.     case ID_COMM_DIAL:
  353.     case ID_COMM_HANGUP:
  354.         pCmdUI->Enable(m_commctrl.GetPortOpen());
  355.         break;
  356.     }
  357. }
  358.  
  359. void CMainFrame::OnCommPort(UINT nID)
  360. {
  361.     switch(nID)
  362.     {
  363.     case ID_COMM_OPEN:
  364.         if (m_commctrl.GetPortOpen())
  365.             m_commctrl.SetPortOpen(FALSE);
  366.         else
  367.             m_commctrl.SetPortOpen(TRUE);
  368.         break;
  369.  
  370.     case ID_COMM_SETTINGS:
  371.         {
  372.             // Invoke settings dialog. NOTE: see CSettingsDlg::OnOk()
  373.             // for processing of the selected dialog settings.
  374.             CSettingsDlg dlg(this);
  375.             dlg.DoModal();
  376.         }
  377.         break;
  378.  
  379.     case ID_COMM_DIAL:
  380.         {
  381.             CInputDlg dlg(this);
  382.             dlg.m_strPrompt.LoadString(IDS_PHONEPROMPT);
  383.             dlg.m_strEdit = m_strPhoneNum;
  384.             if (dlg.DoModal()==IDOK)
  385.             {
  386.                 // NOTE: Modem command string will differ according to
  387.                 // modem type. Check documentation included with modem to
  388.                 // determine the correct command string to autodial.
  389.  
  390.                 CString str;
  391.                 m_strPhoneNum = dlg.m_strEdit;
  392.                 str.Format(IDS_DIALCOMMAND,m_strPhoneNum);
  393.  
  394.                 VARIANT var;
  395.                 var.vt = VT_BSTR;
  396.                 var.bstrVal = str.AllocSysString();
  397.                 m_commctrl.SetOutput(var);
  398.                 SysFreeString(var.bstrVal);
  399.             }
  400.         }
  401.         break;
  402.  
  403.     case ID_COMM_HANGUP:
  404.  
  405.         // Toggle DTR line to signal modem to hang up. NOTE: Not all
  406.         // modems are automatically configured to hang up when the DTR
  407.         // line goes cold. A special modem command may be required to
  408.         // force modem to monitor the DTR line. Check documentation
  409.         // included with modem to determine the correct command string
  410.         // to send to the modem.
  411.  
  412.         BOOL bEnabled = m_commctrl.GetDTREnable();
  413.         m_commctrl.SetDTREnable(TRUE);
  414.         m_commctrl.SetDTREnable(FALSE);
  415.         m_commctrl.SetDTREnable(bEnabled);
  416.         break;
  417.     }
  418. }
  419.  
  420. // Toggle check box on DTREnable menu item.
  421. void CMainFrame::OnUpdatePropDTREnable(CCmdUI* pCmdUI)
  422. {
  423.     pCmdUI->SetCheck(m_commctrl.GetDTREnable());
  424.     pCmdUI->Enable();
  425. }
  426.  
  427. void CMainFrame::OnProperties(UINT nID)
  428. {
  429.     CInputDlg dlg(this);
  430.     TCHAR buff[40];
  431.  
  432.     switch(nID)
  433.     {
  434.     case ID_PROP_INPUTLEN:
  435.         dlg.m_strPrompt.LoadString(IDS_INPUTLENPROMPT);
  436.         _itot(m_commctrl.GetInputLen(),buff,10);
  437.         dlg.m_strEdit = buff;
  438.         if (dlg.DoModal()==IDOK)
  439.             m_commctrl.SetInputLen(_ttoi(dlg.m_strEdit));
  440.         break;
  441.  
  442.     case ID_PROP_RTHRESHOLD:
  443.         dlg.m_strPrompt.LoadString(IDS_RTHRESHOLDPROMPT);
  444.         _itot(m_commctrl.GetRThreshold(),buff,10);
  445.         dlg.m_strEdit = buff;
  446.         if (dlg.DoModal()==IDOK)
  447.             m_commctrl.SetRThreshold(_ttoi(dlg.m_strEdit));
  448.         break;
  449.  
  450.     case ID_PROP_STHRESHOLD:
  451.         dlg.m_strPrompt.LoadString(IDS_STHRESHOLDPROMPT);
  452.         _itot(m_commctrl.GetSThreshold(),buff,10);
  453.         dlg.m_strEdit = buff;
  454.         if (dlg.DoModal()==IDOK)
  455.             m_commctrl.SetSThreshold(_ttoi(dlg.m_strEdit));
  456.         break;
  457.  
  458.     case ID_PROP_PARITYREPLACE:
  459.         dlg.m_strPrompt.LoadString(IDS_PARITYREPLACEPROMPT);
  460.         dlg.m_strEdit = m_commctrl.GetParityReplace();
  461.         if (dlg.DoModal()==IDOK)
  462.             m_commctrl.SetParityReplace(dlg.m_strEdit);
  463.         break;
  464.  
  465.     case ID_PROP_DTRENABLE:
  466.         m_commctrl.SetDTREnable(!m_commctrl.GetDTREnable());
  467.         break;
  468.  
  469.     case ID_PROP_CDHOLDING:
  470.         if (m_commctrl.GetCDHolding())
  471.             AfxMessageBox(IDS_CDHOLDINGTRUE);
  472.         else
  473.             AfxMessageBox(IDS_CDHOLDINGFALSE);
  474.         break;
  475.  
  476.     case ID_PROP_CTSHOLDING:
  477.         if (m_commctrl.GetCTSHolding())
  478.             AfxMessageBox(IDS_CTSHOLDINGTRUE);
  479.         else
  480.             AfxMessageBox(IDS_CTSHOLDINGFALSE);
  481.         break;
  482.  
  483.     case ID_PROP_DSRHOLDING:
  484.         if (m_commctrl.GetDSRHolding())
  485.             AfxMessageBox(IDS_DSRHOLDINGTRUE);
  486.         else
  487.             AfxMessageBox(IDS_DSRHOLDINGFALSE);
  488.         break;
  489.     }
  490. }
  491.  
  492. void CMainFrame::ShowData(LPCTSTR pchData)
  493. {
  494.     CString str;
  495.     int nCharIndex;
  496.     int nBackcount = 0;
  497.  
  498.     // Make sure existing text doesn't get too large.
  499.     int len = m_edit.GetWindowTextLength();
  500.     if (len >= 16384)
  501.     {
  502.         m_edit.GetWindowText(str);
  503.         m_edit.SetWindowText(str.GetBuffer(len)+4097);
  504.         len -= 4097;
  505.     }
  506.  
  507.     // Handle backspace characters.
  508.     str = pchData;
  509.     while ((nCharIndex = str.Find(TCHAR(VK_BACK))) != -1)
  510.     {
  511.         if (nCharIndex == 0)
  512.         {
  513.             nBackcount++;
  514.             str = str.Mid(nCharIndex+1);
  515.         }
  516.         else
  517.             str = str.Left(nCharIndex-1) + str.Mid(nCharIndex+1);
  518.     }
  519.  
  520.     // Set text insertion point according to number of backspaces
  521.     // at the begining of strData.
  522.     if (nBackcount>len)
  523.         nBackcount = len;
  524.     m_edit.SetSel(len-nBackcount,len);
  525.  
  526.     // Eliminate line feeds.
  527.     while ((nCharIndex = str.Find(TCHAR('\n'))) != -1)
  528.         str = str.Left(nCharIndex) + str.Mid(nCharIndex + 1);
  529.  
  530.     // Ensure all carriage returns have a line feed following.
  531.     LPCTSTR pchStart = (LPCTSTR)str;
  532.     LPTSTR pchIndex = _tcschr(pchStart,(TCHAR)'\r');
  533.  
  534.     while (pchIndex != NULL)
  535.     {
  536.         int nPos = pchIndex - pchStart;
  537.  
  538.         str = str.Left(nPos+1) + CString('\n') + str.Mid(nPos+1);
  539.  
  540.         // Above operation probably allocated a new string buffer.
  541.         pchStart = (LPCTSTR)str;
  542.         pchIndex = _tcschr(pchStart + nPos + 1,(TCHAR)'\r');
  543.  
  544.     }
  545.  
  546.     // Add filtered data to edit control.
  547.     m_edit.ReplaceSel(str);
  548.  
  549.     // Log data to file if requested.
  550.     if (!m_strLogFile.IsEmpty())
  551.         m_file.Write(str,str.GetLength());
  552. }
  553.  
  554. void CMainFrame::OnCommEvent()
  555. {
  556.     CString strEvent, strError;
  557.  
  558.     switch(m_commctrl.GetCommEvent())
  559.     {
  560.         case 1: // vbMSCommEvSend:
  561.             strEvent.LoadString(IDS_SENDING);
  562.             break;
  563.         case 2: // vbMSCommEvReceive:
  564.             strEvent.LoadString(IDS_RECEIVING);
  565.             ShowData(m_commctrl.GetInput());
  566.             break;
  567.         case 3: // vbMSCommEvCTS:
  568.             strEvent.LoadString(IDS_CTSCHANGE);
  569.             break;
  570.         case 4: // vbMSCommEvDSR:
  571.             strEvent.LoadString(IDS_DSRCHANGE);
  572.             break;
  573.         case 5: // vbMSCommEvCD:
  574.             strEvent.LoadString(IDS_CDCHANGE);
  575.             break;
  576.         case 6: // vbMSCommEvRing:
  577.             strEvent.LoadString(IDS_PHONERING);
  578.             break;
  579.         case 7: // vbMSCommEvEOF:
  580.             strEvent.LoadString(IDS_EOFDETECTED);
  581.             break;
  582.  
  583.         case 1001: //  vbMSCommErBreak:
  584.             strError.LoadString(IDS_BREAKRECEIVED);
  585.             break;
  586.         case 1002: // vbMSCommErCTSTO:
  587.             strError.LoadString(IDS_CTSTIMEOUT);
  588.             break;
  589.         case 1003: // vbMSCommErDSRTO:
  590.             strError.LoadString(IDS_DSRTIMEOUT);
  591.             break;
  592.         case 1004: // vbMSCommErFrame:
  593.             strError.LoadString(IDS_FRAMEERROR);
  594.             break;
  595.         case 1006: // vbMSCommErOverrun:
  596.             strError.LoadString(IDS_OVERRUNERROR);
  597.             break;
  598.         case 1007: // vbMSCommErCDTO:
  599.             strError.LoadString(IDS_CDTIMEOUT);
  600.             break;
  601.         case 1008: // vbMSCommErRxOver:
  602.             strError.LoadString(IDS_RBUFFEROVERFLOW);
  603.             break;
  604.         case 1009: // vbMSCommErRxParity:
  605.             strError.LoadString(IDS_PARITYERROR);
  606.             break;
  607.         case 1010: // vbMSCommErTxFull:
  608.             strError.LoadString(IDS_TBUFFERFULL);
  609.             break;
  610.     }
  611.  
  612.     if (!strEvent.IsEmpty())
  613.         m_wndStatusBar.SetPaneText(0,strEvent);
  614.     else
  615.         if (!strError.IsEmpty())
  616.         {
  617.             MessageBeep(MB_ICONEXCLAMATION);
  618.             strError += _T("\nOK to ignore, Cancel to quit");
  619.             int ret = AfxMessageBox(strError,MB_OKCANCEL|MB_ICONEXCLAMATION);
  620.             if (ret==IDCANCEL)
  621.                 m_commctrl.SetPortOpen(FALSE);
  622.         }
  623. }
  624.  
  625. void CMainFrame::DoEvents()
  626. {
  627.     MSG msg;
  628.  
  629.     // Process existing messages in the application's message queue.
  630.     // When the queue is empty, do clean up and return.
  631.     while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) && !m_bCancel)
  632.     {
  633.         if (!AfxGetThread()->PumpMessage())
  634.             return;
  635.     }
  636. }
  637.