home *** CD-ROM | disk | FTP | other *** search
- // mainfrm.cpp : implementation of the CMainFrame class
- //
-
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #include "vcterm.h"
- #include "mainfrm.h"
- #include "setdlg.h"
- #include "inputdlg.h"
-
- #include "io.h"
- #include "candlg.h"
- #include "winnls.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame
-
- IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
-
- BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
- //{{AFX_MSG_MAP(CMainFrame)
- ON_WM_CREATE()
- ON_WM_ACTIVATE()
- ON_WM_CLOSE()
- ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_OPENLOG, ID_FILE_TRANSMIT, OnUpdateFile)
- ON_COMMAND(ID_FILE_OPENLOG, OnFileOpenlog)
- ON_COMMAND(ID_FILE_CLOSELOG, OnFileCloselog)
- ON_COMMAND(ID_FILE_TRANSMIT, OnFileTransmit)
- ON_UPDATE_COMMAND_UI_RANGE(ID_COMM_OPEN, ID_COMM_HANGUP, OnUpdateCommPort)
- ON_COMMAND_RANGE(ID_COMM_OPEN, ID_COMM_HANGUP, OnCommPort)
- ON_UPDATE_COMMAND_UI(ID_PROP_DTRENABLE, OnUpdatePropDTREnable)
- ON_COMMAND_RANGE(ID_PROP_INPUTLEN, ID_PROP_DSRHOLDING, OnProperties)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- // add eventsink map to hook OnComm event
- BEGIN_EVENTSINK_MAP(CMainFrame, CFrameWnd)
- ON_EVENT(CMainFrame, ID_COMMCTRL, 1 /* OnComm */, OnCommEvent, VTS_NONE)
- END_EVENTSINK_MAP()
-
- static UINT indicators[] =
- {
- ID_SEPARATOR, // status line indicator
- ID_INDICATOR_CAPS,
- ID_INDICATOR_NUM,
- ID_INDICATOR_SCRL,
- };
-
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame construction/destruction
-
- CMainFrame::CMainFrame()
- {
- m_strPhoneNum.Empty();
- m_strLogFile.Empty();
- }
-
- CMainFrame::~CMainFrame()
- {
- }
-
- int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- if (!m_wndToolBar.Create(this) ||
- !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
- {
- TRACE0("Failed to create toolbar\n");
- return -1; // fail to create
- }
-
- if (!m_wndStatusBar.Create(this) ||
- !m_wndStatusBar.SetIndicators(indicators,
- sizeof(indicators)/sizeof(UINT)))
- {
- TRACE0("Failed to create status bar\n");
- return -1; // fail to create
- }
-
- m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
- CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
-
- m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
- EnableDocking(CBRS_ALIGN_ANY);
- DockControlBar(&m_wndToolBar);
-
- // Create the MSCOMM32 OLE Control.
- if (!m_commctrl.Create(NULL,0,CRect(0,0,0,0),this,ID_COMMCTRL))
- {
- TRACE0("Failed to create OLE Communications Control\n");
- return -1; // fail to create
- }
-
- // Set RThreshold property to 1. The default RThreshold value (0)
- // causes the OnComm event to NOT fire when a character is detected
- // in the serial port.
- m_commctrl.SetRThreshold(1);
-
- // Create the Edit control that sits in the mainframe window.
- if (!m_edit.Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_WANTRETURN|
- ES_MULTILINE|ES_AUTOVSCROLL,rectDefault,this,AFX_IDW_PANE_FIRST))
- {
- TRACE0("Failed to create edit control\n");
- return -1; // fail to create
- }
- // fix up 3D styles
- ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
- m_edit.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED);
-
- return 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame diagnostics
-
- #ifdef _DEBUG
- void CMainFrame::AssertValid() const
- {
- CFrameWnd::AssertValid();
- }
-
- void CMainFrame::Dump(CDumpContext& dc) const
- {
- CFrameWnd::Dump(dc);
- }
-
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame message handlers
-
- void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
- {
- CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
-
- // Set focus to edit control in main window.
- m_edit.SetFocus();
- }
-
- void CMainFrame::OnUpdateFile(CCmdUI* pCmdUI)
- {
- switch(pCmdUI->m_nID)
- {
- // Enable if there is no logfile currently open.
- case ID_FILE_OPENLOG:
- pCmdUI->Enable(m_strLogFile.IsEmpty());
- break;
- // Enable if a log file is currently open.
- case ID_FILE_CLOSELOG:
- pCmdUI->Enable(!m_strLogFile.IsEmpty());
- break;
- // Enable if comm port is open.
- case ID_FILE_TRANSMIT:
- pCmdUI->Enable(m_commctrl.GetPortOpen());
- break;
- }
- }
-
- void CMainFrame::OnFileOpenlog()
- {
- ASSERT(m_strLogFile.IsEmpty());
-
- CFileDialog dlg(TRUE,_T("log"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
- _T("Log Files (*.log) | *.log | All Files (*.*) | *.* ||"),this);
-
- if (dlg.DoModal()==IDOK)
- {
- m_strLogFile = dlg.GetPathName();
-
- if (!m_file.Open(m_strLogFile,CFile::modeCreate|CFile::modeWrite,NULL))
- {
- AfxMessageBox(IDS_FILEOPENFAILED);
- m_strLogFile.Empty();
- return;
- }
-
- // Update mainframe window caption.
- CString str;
- str.Format(_T("VCTerm - %s"),m_strLogFile);
- SetWindowText(str);
- }
- }
-
- void CMainFrame::OnFileCloselog()
- {
- m_file.Flush();
- m_file.Close();
- m_strLogFile.Empty();
- SetWindowText(_T("VCTerm"));
- }
-
- void CMainFrame::OnFileTransmit()
- {
- CFileDialog dlg(TRUE,_T("txt"),NULL,OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,
- _T("Text Files (*.txt) | *.txt | All Files (*.*) | *.* ||"),this);
-
- if (dlg.DoModal()!=IDOK)
- return;
-
- CFile file(dlg.GetPathName(),CFile::modeRead);
-
- // Display cancel dialog.
- EnableWindow(FALSE);
- m_bCancel = FALSE;
-
- CCancelDlg* pDlg = new CCancelDlg(this);
- pDlg->Create(IDD_CANCELDLG,this);
-
- int nBlockSize = m_commctrl.GetOutBufferSize();
- int nFileSize = file.GetLength();
- LPSTR pchBuffer = new char[nBlockSize];
- LPWSTR pchData = new WCHAR[nBlockSize];
-
- VARIANT var;
-
- // Read/Transmit the file in blocks the size of the transmit buffer.
- for (int nRxTx = 0; nRxTx<(nFileSize/nBlockSize) && !m_bCancel; nRxTx++)
- {
- file.Read(pchBuffer,nBlockSize);
-
- // Convert the ASCII text string to a UNICODE string.
- MultiByteToWideChar(CP_ACP,0,pchBuffer,nBlockSize,pchData,nBlockSize);
- var.vt = VT_BSTR;
- var.bstrVal = ::SysAllocStringLen(pchData,nBlockSize);
-
- // Send data to comm port.
- m_commctrl.SetOutput(var);
- SysFreeString(var.bstrVal);
-
- // Wait for the transmit buffer to empty.
- while ((m_commctrl.GetOutBufferCount() > 0) && !m_bCancel)
- DoEvents();
- }
-
- // Dump last bit of file to the transmit buffer.
- int nLeftOver = nFileSize % nBlockSize;
-
- // If file size is identical to Output Buffer size.
- if (!nLeftOver)
- nLeftOver = nBlockSize;
-
- // Read/Transmit the last chunk of the file.
- if (nLeftOver && !m_bCancel)
- {
- file.Read(pchBuffer,nLeftOver);
-
- // Convert the ASCII text string to a UNICODE string.
- MultiByteToWideChar(CP_ACP,0,pchBuffer,nLeftOver,pchData,nLeftOver);
- var.vt = VT_BSTR;
- var.bstrVal = ::SysAllocStringLen(pchData,nLeftOver);
-
- // Send data to comm port.
- m_commctrl.SetOutput(var);
- SysFreeString(var.bstrVal);
-
- // Wait for the transmit buffer to empty.
- while ((m_commctrl.GetOutBufferCount() > 0) && !m_bCancel)
- DoEvents();
- }
-
- // Close out the Cancel dialog.
- if (!m_bCancel)
- pDlg->OnCancel();
-
- delete pchBuffer;
- delete pchData;
- file.Close();
- EnableWindow(TRUE);
- m_edit.SetFocus();
- }
-
- void CMainFrame::OnClose()
- {
- if (m_commctrl.GetPortOpen())
- {
- // Set timeout period for 10 seconds from current time.
- BOOL bTimedOut = FALSE;
- CTime timeOut = CTime::GetCurrentTime() + CTimeSpan(0,0,0,10);
-
- while (m_commctrl.GetOutBufferCount())
- {
- // Process all pending messages.
- m_bCancel=FALSE;
- DoEvents();
-
- if ( (CTime::GetCurrentTime() > timeOut) || bTimedOut)
- {
- int ret = AfxMessageBox(IDS_DATASENDFAILED,MB_ABORTRETRYIGNORE);
-
- switch (ret)
- {
- // Attempt to send data for another 10 seconds.
- case IDRETRY:
- timeOut = CTime::GetCurrentTime() + CTimeSpan(0,0,0,10);
- break;
- // Ignore timeout and exit.
- case IDIGNORE:
- bTimedOut = TRUE;
- break;
- // Abort attempt to exit application.
- case IDABORT:
- return;
- }
- }
- }
- m_commctrl.SetPortOpen(FALSE);
- }
-
- // Close log file if it's currently open.
- if (!m_strLogFile.IsEmpty())
- OnFileCloselog();
-
- CFrameWnd::OnClose();
- }
-
- void CMainFrame::OnUpdateCommPort(CCmdUI* pCmdUI)
- {
- switch(pCmdUI->m_nID)
- {
- case ID_COMM_OPEN:
- if (m_commctrl.GetPortOpen())
- pCmdUI->SetText(_T("&Port Close"));
- else
- pCmdUI->SetText(_T("&Port Open"));
- pCmdUI->Enable();
- break;
-
- case ID_COMM_SETTINGS:
- if (m_commctrl.GetPortOpen())
- pCmdUI->Enable(FALSE);
- else
- pCmdUI->Enable();
- break;
-
- case ID_COMM_DIAL:
- case ID_COMM_HANGUP:
- pCmdUI->Enable(m_commctrl.GetPortOpen());
- break;
- }
- }
-
- void CMainFrame::OnCommPort(UINT nID)
- {
- switch(nID)
- {
- case ID_COMM_OPEN:
- if (m_commctrl.GetPortOpen())
- m_commctrl.SetPortOpen(FALSE);
- else
- m_commctrl.SetPortOpen(TRUE);
- break;
-
- case ID_COMM_SETTINGS:
- {
- // Invoke settings dialog. NOTE: see CSettingsDlg::OnOk()
- // for processing of the selected dialog settings.
- CSettingsDlg dlg(this);
- dlg.DoModal();
- }
- break;
-
- case ID_COMM_DIAL:
- {
- CInputDlg dlg(this);
- dlg.m_strPrompt.LoadString(IDS_PHONEPROMPT);
- dlg.m_strEdit = m_strPhoneNum;
- if (dlg.DoModal()==IDOK)
- {
- // NOTE: Modem command string will differ according to
- // modem type. Check documentation included with modem to
- // determine the correct command string to autodial.
-
- CString str;
- m_strPhoneNum = dlg.m_strEdit;
- str.Format(IDS_DIALCOMMAND,m_strPhoneNum);
-
- VARIANT var;
- var.vt = VT_BSTR;
- var.bstrVal = str.AllocSysString();
- m_commctrl.SetOutput(var);
- SysFreeString(var.bstrVal);
- }
- }
- break;
-
- case ID_COMM_HANGUP:
-
- // Toggle DTR line to signal modem to hang up. NOTE: Not all
- // modems are automatically configured to hang up when the DTR
- // line goes cold. A special modem command may be required to
- // force modem to monitor the DTR line. Check documentation
- // included with modem to determine the correct command string
- // to send to the modem.
-
- BOOL bEnabled = m_commctrl.GetDTREnable();
- m_commctrl.SetDTREnable(TRUE);
- m_commctrl.SetDTREnable(FALSE);
- m_commctrl.SetDTREnable(bEnabled);
- break;
- }
- }
-
- // Toggle check box on DTREnable menu item.
- void CMainFrame::OnUpdatePropDTREnable(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck(m_commctrl.GetDTREnable());
- pCmdUI->Enable();
- }
-
- void CMainFrame::OnProperties(UINT nID)
- {
- CInputDlg dlg(this);
- TCHAR buff[40];
-
- switch(nID)
- {
- case ID_PROP_INPUTLEN:
- dlg.m_strPrompt.LoadString(IDS_INPUTLENPROMPT);
- _itot(m_commctrl.GetInputLen(),buff,10);
- dlg.m_strEdit = buff;
- if (dlg.DoModal()==IDOK)
- m_commctrl.SetInputLen(_ttoi(dlg.m_strEdit));
- break;
-
- case ID_PROP_RTHRESHOLD:
- dlg.m_strPrompt.LoadString(IDS_RTHRESHOLDPROMPT);
- _itot(m_commctrl.GetRThreshold(),buff,10);
- dlg.m_strEdit = buff;
- if (dlg.DoModal()==IDOK)
- m_commctrl.SetRThreshold(_ttoi(dlg.m_strEdit));
- break;
-
- case ID_PROP_STHRESHOLD:
- dlg.m_strPrompt.LoadString(IDS_STHRESHOLDPROMPT);
- _itot(m_commctrl.GetSThreshold(),buff,10);
- dlg.m_strEdit = buff;
- if (dlg.DoModal()==IDOK)
- m_commctrl.SetSThreshold(_ttoi(dlg.m_strEdit));
- break;
-
- case ID_PROP_PARITYREPLACE:
- dlg.m_strPrompt.LoadString(IDS_PARITYREPLACEPROMPT);
- dlg.m_strEdit = m_commctrl.GetParityReplace();
- if (dlg.DoModal()==IDOK)
- m_commctrl.SetParityReplace(dlg.m_strEdit);
- break;
-
- case ID_PROP_DTRENABLE:
- m_commctrl.SetDTREnable(!m_commctrl.GetDTREnable());
- break;
-
- case ID_PROP_CDHOLDING:
- if (m_commctrl.GetCDHolding())
- AfxMessageBox(IDS_CDHOLDINGTRUE);
- else
- AfxMessageBox(IDS_CDHOLDINGFALSE);
- break;
-
- case ID_PROP_CTSHOLDING:
- if (m_commctrl.GetCTSHolding())
- AfxMessageBox(IDS_CTSHOLDINGTRUE);
- else
- AfxMessageBox(IDS_CTSHOLDINGFALSE);
- break;
-
- case ID_PROP_DSRHOLDING:
- if (m_commctrl.GetDSRHolding())
- AfxMessageBox(IDS_DSRHOLDINGTRUE);
- else
- AfxMessageBox(IDS_DSRHOLDINGFALSE);
- break;
- }
- }
-
- void CMainFrame::ShowData(LPCTSTR pchData)
- {
- CString str;
- int nCharIndex;
- int nBackcount = 0;
-
- // Make sure existing text doesn't get too large.
- int len = m_edit.GetWindowTextLength();
- if (len >= 16384)
- {
- m_edit.GetWindowText(str);
- m_edit.SetWindowText(str.GetBuffer(len)+4097);
- len -= 4097;
- }
-
- // Handle backspace characters.
- str = pchData;
- while ((nCharIndex = str.Find(TCHAR(VK_BACK))) != -1)
- {
- if (nCharIndex == 0)
- {
- nBackcount++;
- str = str.Mid(nCharIndex+1);
- }
- else
- str = str.Left(nCharIndex-1) + str.Mid(nCharIndex+1);
- }
-
- // Set text insertion point according to number of backspaces
- // at the begining of strData.
- if (nBackcount>len)
- nBackcount = len;
- m_edit.SetSel(len-nBackcount,len);
-
- // Eliminate line feeds.
- while ((nCharIndex = str.Find(TCHAR('\n'))) != -1)
- str = str.Left(nCharIndex) + str.Mid(nCharIndex + 1);
-
- // Ensure all carriage returns have a line feed following.
- LPCTSTR pchStart = (LPCTSTR)str;
- LPTSTR pchIndex = _tcschr(pchStart,(TCHAR)'\r');
-
- while (pchIndex != NULL)
- {
- int nPos = pchIndex - pchStart;
-
- str = str.Left(nPos+1) + CString('\n') + str.Mid(nPos+1);
-
- // Above operation probably allocated a new string buffer.
- pchStart = (LPCTSTR)str;
- pchIndex = _tcschr(pchStart + nPos + 1,(TCHAR)'\r');
-
- }
-
- // Add filtered data to edit control.
- m_edit.ReplaceSel(str);
-
- // Log data to file if requested.
- if (!m_strLogFile.IsEmpty())
- m_file.Write(str,str.GetLength());
- }
-
- void CMainFrame::OnCommEvent()
- {
- CString strEvent, strError;
-
- switch(m_commctrl.GetCommEvent())
- {
- case 1: // vbMSCommEvSend:
- strEvent.LoadString(IDS_SENDING);
- break;
- case 2: // vbMSCommEvReceive:
- strEvent.LoadString(IDS_RECEIVING);
- ShowData(m_commctrl.GetInput());
- break;
- case 3: // vbMSCommEvCTS:
- strEvent.LoadString(IDS_CTSCHANGE);
- break;
- case 4: // vbMSCommEvDSR:
- strEvent.LoadString(IDS_DSRCHANGE);
- break;
- case 5: // vbMSCommEvCD:
- strEvent.LoadString(IDS_CDCHANGE);
- break;
- case 6: // vbMSCommEvRing:
- strEvent.LoadString(IDS_PHONERING);
- break;
- case 7: // vbMSCommEvEOF:
- strEvent.LoadString(IDS_EOFDETECTED);
- break;
-
- case 1001: // vbMSCommErBreak:
- strError.LoadString(IDS_BREAKRECEIVED);
- break;
- case 1002: // vbMSCommErCTSTO:
- strError.LoadString(IDS_CTSTIMEOUT);
- break;
- case 1003: // vbMSCommErDSRTO:
- strError.LoadString(IDS_DSRTIMEOUT);
- break;
- case 1004: // vbMSCommErFrame:
- strError.LoadString(IDS_FRAMEERROR);
- break;
- case 1006: // vbMSCommErOverrun:
- strError.LoadString(IDS_OVERRUNERROR);
- break;
- case 1007: // vbMSCommErCDTO:
- strError.LoadString(IDS_CDTIMEOUT);
- break;
- case 1008: // vbMSCommErRxOver:
- strError.LoadString(IDS_RBUFFEROVERFLOW);
- break;
- case 1009: // vbMSCommErRxParity:
- strError.LoadString(IDS_PARITYERROR);
- break;
- case 1010: // vbMSCommErTxFull:
- strError.LoadString(IDS_TBUFFERFULL);
- break;
- }
-
- if (!strEvent.IsEmpty())
- m_wndStatusBar.SetPaneText(0,strEvent);
- else
- if (!strError.IsEmpty())
- {
- MessageBeep(MB_ICONEXCLAMATION);
- strError += _T("\nOK to ignore, Cancel to quit");
- int ret = AfxMessageBox(strError,MB_OKCANCEL|MB_ICONEXCLAMATION);
- if (ret==IDCANCEL)
- m_commctrl.SetPortOpen(FALSE);
- }
- }
-
- void CMainFrame::DoEvents()
- {
- MSG msg;
-
- // Process existing messages in the application's message queue.
- // When the queue is empty, do clean up and return.
- while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) && !m_bCancel)
- {
- if (!AfxGetThread()->PumpMessage())
- return;
- }
- }
-