// Chapt12Dlg.cpp : implementation file // #include #include #include #include #include #include "Chapt12.h" #include "Chapt12Dlg.h" #include "MyWin32Port.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CChapt12Dlg dialog CChapt12Dlg::CChapt12Dlg(CWnd* pParent /*=NULL*/) : CDialog(CChapt12Dlg::IDD, pParent) { //{{AFX_DATA_INIT(CChapt12Dlg) //}}AFX_DATA_INIT m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_hConsoleOutput = INVALID_HANDLE_VALUE; m_hConsoleInput = INVALID_HANDLE_VALUE; m_hCloseConsoleEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); m_pPort = 0; } void CChapt12Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CChapt12Dlg) DDX_Control(pDX, IDC_SPEW, m_SpewButton); DDX_Control(pDX, IDC_FLUSH_TX, m_FlushTxButton); DDX_Control(pDX, IDC_FLUSH_RX, m_FlushRxButton); DDX_Control(pDX, IDC_PEEK_BUFFER, m_PeekBufferButton); DDX_Control(pDX, IDC_SEND_BREAK, m_SendBreakButton); DDX_Control(pDX, IDC_DUMP_STATUS, m_DumpStatusButton); DDX_Control(pDX, IDC_SEND_BUFFER, m_SendBufferButton); DDX_Control(pDX, IDC_READ_CHAR, m_ReadCharButton); DDX_Control(pDX, IDC_UPDATE, m_UpdateButton); DDX_Control(pDX, IDC_PORT, m_PortComboBox); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CChapt12Dlg, CDialog) //{{AFX_MSG_MAP(CChapt12Dlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_OPEN_OR_CLOSE, OnOpenOrClose) ON_WM_DESTROY() ON_BN_CLICKED(IDC_SEND_BUFFER, OnSendBuffer) ON_BN_CLICKED(IDC_UPDATE, OnUpdate) ON_CBN_EDITUPDATE(IDC_BAUD_RATE, OnEditupdateBaudRate) ON_CBN_SELCHANGE(IDC_BAUD_RATE, OnSelchangeBaudRate) ON_CBN_EDITCHANGE(IDC_PARITY, OnEditchangeParity) ON_CBN_SELCHANGE(IDC_PARITY, OnSelchangeParity) ON_CBN_EDITUPDATE(IDC_STOP_BITS, OnEditupdateStopBits) ON_CBN_SELCHANGE(IDC_STOP_BITS, OnSelchangeStopBits) ON_CBN_EDITUPDATE(IDC_WORD_SIZE, OnEditupdateWordSize) ON_CBN_SELCHANGE(IDC_WORD_SIZE, OnSelchangeWordSize) ON_BN_CLICKED(IDC_RTS, OnRts) ON_BN_CLICKED(IDC_DTR, OnDtr) ON_BN_CLICKED(IDC_DTR_DSR, OnDtrDsr) ON_BN_CLICKED(IDC_XON_XOFF, OnXonXoff) ON_BN_CLICKED(IDC_RTS_CTS, OnRtsCts) ON_MESSAGE( WM_SERIAL_RX_NOTIFY,OnRxNotify) ON_MESSAGE( WM_FRAMING_ERROR_NOTIFY,OnFramingErrorNotify) ON_MESSAGE( WM_PARITY_ERROR_NOTIFY,OnParityErrorNotify) ON_MESSAGE( WM_HARDWARE_OVERRUN_ERROR_NOTIFY,OnHardwareOverrunErrorNotify) ON_MESSAGE( WM_SOFTWARE_OVERRUN_ERROR_NOTIFY,OnSoftwareOverrunErrorNotify) ON_MESSAGE( WM_BREAK_DETECT_NOTIFY,OnBreakDetectNotify) ON_MESSAGE( WM_CTS_NOTIFY,OnCtsNotify) ON_MESSAGE( WM_DSR_NOTIFY,OnDsrNotify) ON_MESSAGE( WM_CD_NOTIFY,OnCdNotify) ON_MESSAGE( WM_RI_NOTIFY,OnRiNotify) ON_MESSAGE( WM_TX_NOTIFY,OnTxNotify) ON_BN_CLICKED(IDC_READ_CHAR, OnReadChar) ON_BN_CLICKED(IDC_DUMP_STATUS, OnDumpStatus) ON_BN_CLICKED(IDC_ERROR_NOTIFICATION, OnErrorNotification) ON_BN_CLICKED(IDC_SEND_BREAK, OnSendBreak) ON_CBN_SELCHANGE(IDC_READ_TYPE, OnSelchangeReadType) ON_BN_CLICKED(IDC_PEEK_BUFFER, OnPeekBuffer) ON_BN_CLICKED(IDC_FLUSH_RX, OnFlushRx) ON_BN_CLICKED(IDC_FLUSH_TX, OnFlushTx) ON_BN_CLICKED(IDC_SPEW, OnSpew) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChapt12Dlg message handlers BOOL CChapt12Dlg::OnInitDialog() { CDialog::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here SetDlgItemText( IDC_PORT, "COM1" ); SetDlgItemText( IDC_BAUD_RATE, "9600" ); SetDlgItemText( IDC_PARITY, "None" ); SetDlgItemText( IDC_WORD_SIZE, "8" ); SetDlgItemText( IDC_STOP_BITS, "1" ); SetDlgItemText( IDC_BREAK_DURATION, "250" ); SendDlgItemMessage( IDC_DTR, BM_SETCHECK, BST_CHECKED, 0 ); SendDlgItemMessage( IDC_RTS, BM_SETCHECK, BST_CHECKED, 0 ); m_eReading = READ_BYTES; SendDlgItemMessage( IDC_READ_TYPE, CB_SETCURSEL, 1, 0 ); m_bErrorNotification = true; SendDlgItemMessage( IDC_ERROR_NOTIFICATION, BM_SETCHECK, BST_CHECKED, 0 ); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CChapt12Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } HCURSOR CChapt12Dlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CChapt12Dlg::OnOpenOrClose() { if ( m_hConsoleOutput == INVALID_HANDLE_VALUE ) { CString port_name; GetDlgItemText( IDC_PORT, port_name ); int baud_rate = GetDlgItemInt( IDC_BAUD_RATE ); int word_size = GetDlgItemInt( IDC_WORD_SIZE ); int stop_bits = GetDlgItemInt( IDC_STOP_BITS ); int xon_xoff = SendDlgItemMessage( IDC_XON_XOFF, BM_GETCHECK, 0, 0 ) == BST_CHECKED; int rts_cts = SendDlgItemMessage( IDC_RTS_CTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; int dtr_dsr = SendDlgItemMessage( IDC_DTR_DSR, BM_GETCHECK, 0, 0 ) == BST_CHECKED; m_iFramingErrorCount = 0; m_iParityErrorCount = 0; m_iHardwareOverrunErrorCount = 0; m_iSoftwareOverrunErrorCount = 0; m_iBreakDetectCount = 0; m_iTxNotifyCount = 0; m_bSpewing = false; SetDlgItemInt( IDC_FRAMING_ERROR_COUNT, 0 ); SetDlgItemInt( IDC_PARITY_ERROR_COUNT, 0 ); SetDlgItemInt( IDC_HARDWARE_OVERRUN_ERROR_COUNT, 0 ); SetDlgItemInt( IDC_SOFTWARE_OVERRUN_ERROR_COUNT, 0 ); SetDlgItemInt( IDC_BREAK_DETECT_COUNT, 0 ); SetDlgItemInt( IDC_TX_EMPTY_COUNT, 0 ); CString parity; GetDlgItemText( IDC_PARITY, parity ); m_pPort = new MyWin32Port( this->m_hWnd, (const char *) port_name, baud_rate, parity[ 0 ], word_size, stop_bits, UNCHANGED, UNCHANGED, xon_xoff, rts_cts, dtr_dsr ); if ( m_pPort->ErrorStatus() == RS232_SUCCESS ) { m_PortComboBox.EnableWindow( FALSE ); SetDlgItemText( IDC_OPEN_OR_CLOSE, "Close" ); m_SendBufferButton.EnableWindow( TRUE ); m_ReadCharButton.EnableWindow( TRUE ); m_PeekBufferButton.EnableWindow( TRUE ); m_SendBreakButton.EnableWindow( TRUE ); m_SpewButton.EnableWindow( TRUE ); m_SpewButton.SetWindowText( "Start Spew" ); m_DumpStatusButton.EnableWindow( TRUE ); m_FlushRxButton.EnableWindow( TRUE ); m_FlushTxButton.EnableWindow( TRUE ); m_iRingCount = -1; SetDlgItemText( IDC_CTS, "" ); SetDlgItemText( IDC_DSR, "" ); SetDlgItemText( IDC_CD, "" ); SetDlgItemText( IDC_RI, "" ); int check_state = BST_INDETERMINATE; switch ( m_pPort->Dtr() ) { case 0 : check_state = BST_UNCHECKED; break; case 1 : check_state = BST_CHECKED; break; } SendDlgItemMessage( IDC_DTR, BM_SETCHECK, check_state, 0 ); check_state = BST_INDETERMINATE; switch ( m_pPort->Rts() ) { case 0 : check_state = BST_UNCHECKED; break; case 1 : check_state = BST_CHECKED; break; } SendDlgItemMessage( IDC_RTS, BM_SETCHECK, check_state, 0 ); AllocConsole(); m_hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE ); m_hConsoleInput = GetStdHandle( STD_INPUT_HANDLE ); SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); SetConsoleMode( m_hConsoleInput, 0 ); ResetEvent( m_hCloseConsoleEvent ); _beginthread( ConsoleInputThread, 0, (void *) this ); } else { string msg = "Port Error: "; msg += m_pPort->ErrorName( m_pPort->ErrorStatus() ); AfxMessageBox( msg.c_str() ); delete m_pPort; m_pPort = 0; } } else { m_SendBufferButton.EnableWindow( FALSE ); m_ReadCharButton.EnableWindow( FALSE ); m_PeekBufferButton.EnableWindow( FALSE ); m_SendBreakButton.EnableWindow( FALSE ); m_SpewButton.EnableWindow( FALSE ); m_DumpStatusButton.EnableWindow( FALSE ); m_FlushRxButton.EnableWindow( FALSE ); m_FlushTxButton.EnableWindow( FALSE ); delete m_pPort; m_pPort = 0; m_hConsoleInput = INVALID_HANDLE_VALUE; m_hConsoleOutput = INVALID_HANDLE_VALUE; SetEvent( m_hCloseConsoleEvent ); FreeConsole(); m_PortComboBox.EnableWindow( TRUE ); m_UpdateButton.EnableWindow( FALSE ); SetDlgItemText( IDC_OPEN_OR_CLOSE, "Open" ); } } void CChapt12Dlg::ConsoleInputThread(void * arglist) { CChapt12Dlg *obj = (CChapt12Dlg *) arglist; TRACE( "Entering console input thread\n" ); HANDLE handles[ 2 ] = { obj->m_hConsoleInput, obj->m_hCloseConsoleEvent }; for ( ; ; ) { DWORD wait_result = WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); if ( wait_result == 1 ) break; DWORD result; INPUT_RECORD record; BOOL ret_val = ReadConsoleInput( obj->m_hConsoleInput, &record, 1, &result ); if ( record.EventType == KEY_EVENT ) { if ( record.Event.KeyEvent.bKeyDown && record.Event.KeyEvent.uChar.AsciiChar ) { char c = record.Event.KeyEvent.uChar.AsciiChar; obj->m_pPort->Write( c ); if ( c == '\r' ) obj->m_pPort->Write( '\n' ); } } } TRACE( "Exiting console input thread, error = %x\n", GetLastError() ); } void CChapt12Dlg::OnDestroy() { CDialog::OnDestroy(); if ( m_hConsoleOutput != INVALID_HANDLE_VALUE ) { m_hConsoleInput = INVALID_HANDLE_VALUE; m_hConsoleOutput = INVALID_HANDLE_VALUE; SetEvent( m_hCloseConsoleEvent ); FreeConsole(); } if ( m_pPort ) { delete m_pPort; m_pPort = 0; } } void CChapt12Dlg::OnSendBuffer() { m_pPort->Write( "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\r\n", 38 ); } void CChapt12Dlg::OnUpdate() { int baud_rate = GetDlgItemInt( IDC_BAUD_RATE ); int word_size = GetDlgItemInt( IDC_WORD_SIZE ); int stop_bits = GetDlgItemInt( IDC_STOP_BITS ); CString parity; GetDlgItemText( IDC_PARITY, parity ); RS232Error err = m_pPort->Set( baud_rate, parity[ 0 ], word_size, stop_bits ); if ( err < RS232_SUCCESS ) { string msg = "Port Error: "; msg += m_pPort->ErrorName( err ); AfxMessageBox( msg.c_str() ); } } void CChapt12Dlg::OnEditupdateBaudRate() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnSelchangeBaudRate() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnEditchangeParity() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnSelchangeParity() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnEditupdateStopBits() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnSelchangeStopBits() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnEditupdateWordSize() { if ( m_pPort ) m_UpdateButton.EnableWindow( TRUE ); } void CChapt12Dlg::OnSelchangeWordSize() { // TODO: Add your control notification handler code here } void CChapt12Dlg::OnRts() { if ( !m_pPort ) return; int check_state = BST_INDETERMINATE; switch ( m_pPort->Rts( SendDlgItemMessage( IDC_RTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) ) { case 0 : check_state = BST_UNCHECKED; break; case 1 : check_state = BST_CHECKED; break; } SendDlgItemMessage( IDC_RTS, BM_SETCHECK, check_state, 0 ); } void CChapt12Dlg::OnDtr() { if ( !m_pPort ) return; int check_state = BST_INDETERMINATE; switch ( m_pPort->Dtr( SendDlgItemMessage( IDC_DTR, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) ) { case 0 : check_state = BST_UNCHECKED; break; case 1 : check_state = BST_CHECKED; break; } SendDlgItemMessage( IDC_DTR, BM_SETCHECK, check_state, 0 ); } void CChapt12Dlg::OnDtrDsr() { if ( !m_pPort ) return; bool val = SendDlgItemMessage( IDC_DTR_DSR, BM_GETCHECK, 0, 0 ) == BST_CHECKED; m_pPort->DtrDsrHandshaking( val ); if ( val == 0 ) OnDtr(); } void CChapt12Dlg::OnRtsCts() { if ( !m_pPort ) return; bool val = SendDlgItemMessage( IDC_RTS_CTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; m_pPort->RtsCtsHandshaking( val ); if ( val == 0 ) OnRts(); } void CChapt12Dlg::OnXonXoff() { if ( !m_pPort ) return; bool val = SendDlgItemMessage( IDC_XON_XOFF, BM_GETCHECK, 0, 0 ) == BST_CHECKED; m_pPort->XonXoffHandshaking( val ); } LRESULT CChapt12Dlg::OnRxNotify( WPARAM wParam, LPARAM lParam ) { if ( m_eReading == SUPPRESS_READING || !m_pPort || m_hConsoleOutput == INVALID_HANDLE_VALUE ) return 0; if ( m_eReading == READ_BYTES ) { for ( ; ; ) { int c = m_pPort->Read(); if ( c < 0 ) break; char c1 = c; DWORD written = 0; WriteConsole( m_hConsoleOutput, &c1, 1, &written, 0 ); } } else { for ( ; ; ) { char buffer[ 129 ]; int result = m_pPort->Read( buffer, 128 ) ; if ( m_pPort->ByteCount == 0 ) break; DWORD written = 0; WriteConsole( m_hConsoleOutput, &buffer, m_pPort->ByteCount, &written, 0 ); } } return 1; } void CChapt12Dlg::OnReadChar() { int c = m_pPort->Read(); ostringstream s; s << "\nRead <"; if ( c > 0 ) s << (char) c; else s << c; s << ">\n"; DWORD written = 0; WriteConsole( m_hConsoleOutput, s.str().c_str(), s.str().size(), &written, 0 ); } void CChapt12Dlg::OnDumpStatus() { char buffer[ 82 ]; DWORD written = 0; for ( int i = 0 ; i < m_pPort->DebugLineCount() ; i++ ) { m_pPort->FormatDebugOutput( buffer, i ); strcat( buffer, "\n" ); WriteConsole( m_hConsoleOutput, buffer, strlen( buffer ), &written, 0 ); } } LRESULT CChapt12Dlg::OnParityErrorNotify( WPARAM, LPARAM ) { if ( !m_bErrorNotification ) return 0; int result = m_pPort->ParityError( true ); if ( result ) SetDlgItemInt( IDC_PARITY_ERROR_COUNT, ++m_iParityErrorCount ); return 1; } LRESULT CChapt12Dlg::OnFramingErrorNotify( WPARAM, LPARAM ) { if ( !m_bErrorNotification ) return 0; int result = m_pPort->FramingError( true ); if ( result ) SetDlgItemInt( IDC_FRAMING_ERROR_COUNT, ++m_iFramingErrorCount ); return 1; } LRESULT CChapt12Dlg::OnHardwareOverrunErrorNotify( WPARAM, LPARAM ) { if ( !m_bErrorNotification ) return 0; int result = m_pPort->HardwareOverrunError( true ); if ( result ) SetDlgItemInt( IDC_HARDWARE_OVERRUN_ERROR_COUNT, ++m_iHardwareOverrunErrorCount ); return 1; } LRESULT CChapt12Dlg::OnSoftwareOverrunErrorNotify( WPARAM, LPARAM ) { if ( !m_bErrorNotification ) return 0; int result = m_pPort->SoftwareOverrunError( true ); if ( result ) SetDlgItemInt( IDC_SOFTWARE_OVERRUN_ERROR_COUNT, ++m_iSoftwareOverrunErrorCount ); return 1; } LRESULT CChapt12Dlg::OnBreakDetectNotify( WPARAM, LPARAM ) { if ( !m_bErrorNotification ) return 0; int result = m_pPort->BreakDetect( true ); if ( result ) SetDlgItemInt( IDC_BREAK_DETECT_COUNT, ++m_iBreakDetectCount ); return 1; } void CChapt12Dlg::OnErrorNotification() { m_bErrorNotification = SendDlgItemMessage( IDC_ERROR_NOTIFICATION, BM_GETCHECK, 0, 0 ) == BST_CHECKED; if ( m_bErrorNotification ) { OnParityErrorNotify( 0, 0 ); OnFramingErrorNotify( 0, 0 ); OnHardwareOverrunErrorNotify( 0, 0 ); OnSoftwareOverrunErrorNotify( 0, 0 ); OnBreakDetectNotify( 0, 0 ); } } void CChapt12Dlg::OnSendBreak() { int duration = GetDlgItemInt( IDC_BREAK_DURATION ); if ( duration == 0 ) duration = 250; m_pPort->Break( duration ); } LRESULT CChapt12Dlg::OnCtsNotify( WPARAM state, LPARAM ) { if ( state ) SetDlgItemText( IDC_CTS, "ON" ); else SetDlgItemText( IDC_CTS, "OFF" ); return 1; } LRESULT CChapt12Dlg::OnDsrNotify( WPARAM state, LPARAM ) { if ( state ) SetDlgItemText( IDC_DSR, "ON" ); else SetDlgItemText( IDC_DSR, "OFF" ); return 1; } LRESULT CChapt12Dlg::OnCdNotify( WPARAM state, LPARAM ) { if ( state ) SetDlgItemText( IDC_CD, "ON" ); else SetDlgItemText( IDC_CD, "OFF" ); return 1; } LRESULT CChapt12Dlg::OnRiNotify( WPARAM state, LPARAM ) { if ( state == 0 ) SetDlgItemInt( IDC_RI, ++m_iRingCount ); return 1; } LRESULT CChapt12Dlg::OnTxNotify( WPARAM state, LPARAM ) { if ( !m_bErrorNotification ) return 0; SetDlgItemInt( IDC_TX_EMPTY_COUNT, ++m_iTxNotifyCount ); if ( m_bSpewing ) { static int counter = 0; char buf[ 128 ]; sprintf( buf, "Packet %d: " "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n", counter++ ); m_pPort->Write( buf ); } return 1; } void CChapt12Dlg::OnSelchangeReadType() { int i = SendDlgItemMessage( IDC_READ_TYPE, CB_GETCURSEL, 0, 0 ); switch ( i ) { case 0 : m_eReading = SUPPRESS_READING; break; case 1 : m_eReading = READ_BYTES; break; case 2 : m_eReading = READ_BUFFERS; break; } OnRxNotify( 0,0 ); } void CChapt12Dlg::OnPeekBuffer() { char buffer[ 3001 ]; if ( m_pPort->Peek( buffer, 3000 ) == RS232_SUCCESS ) { ostringstream s; s << "\nPeek saw " << m_pPort->ByteCount << " bytes: <"; if ( m_pPort->ByteCount > 40 ) { buffer[ 40 ] = '\0'; s << buffer << "...>\n"; } else { s << buffer << ">\n"; } DWORD written = 0; WriteConsole( m_hConsoleOutput, s.str().c_str(), s.str().size(), &written, 0 ); } } void CChapt12Dlg::OnFlushRx() { m_pPort->FlushRXBuffer(); } void CChapt12Dlg::OnFlushTx() { m_pPort->FlushTXBuffer(); } void CChapt12Dlg::OnSpew() { if ( m_bSpewing ) { m_bSpewing = false; m_SpewButton.SetWindowText( "Start Spew" ); m_pPort->Write( "Stopping spew...\n" ); } else { m_bSpewing = true; m_SpewButton.SetWindowText( "Stop Spew" ); m_pPort->Write( "Starting to spew...\n" ); } }