CommandCtrl.cpp
上传用户:xaxinn
上传日期:2007-01-03
资源大小:39k
文件大小:15k
- // CommandCtrl.cpp : implementation file
- //
- // Release 1, Copyright (C) 1999 Ben Bryant
- // This is sample source code, nothing more is implied. Use it only as such.
- // This software is provided 'as-is', without warranty. In no event will the
- // author be held liable for any damages arising from the use of this software.
- // Permission is granted to anyone to use this software for any purpose.
- // The origin of this software must not be misrepresented; you must not claim
- // that you wrote the original software. Altered source versions must be plainly
- // marked as such, and must not be misrepresented as being the original software.
- // Ben Bryant bcbryant@firstobject.com
- //
- #include "stdafx.h"
- #include "CommandCtrl.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CCommand
- CCommand::CCommand()
- {
- m_pWnd = NULL;
- m_pOut = NULL;
- m_pIn = NULL;
- m_pDo = NULL;
- }
- CCommand::~CCommand()
- {
- }
- void CCommand::Init( CWnd* pWnd, CCmdOutCtrl* pOut, CCmdInCtrl* pIn, CButton* pDo )
- {
- // Store pointers
- m_pOut = pOut;
- m_pOut->Set( this );
- m_pIn = pIn;
- m_pIn->Set( this );
- m_pDo = pDo;
- m_pWnd = pWnd;
- }
- void CCommand::Resize()
- {
- if ( m_pWnd )
- {
- CRect rect;
- m_pWnd->GetClientRect( &rect );
- m_pWnd->SendMessage(
- WM_SIZE,
- SIZE_RESTORED,
- MAKELPARAM(rect.Width(),rect.Height())
- );
- }
- }
- void CCommand::MoveControls( CRect& rectBorder )
- {
- if ( m_pDo && m_pIn && m_pOut )
- {
- // Position controls inside rectBorder
- CRect rect;
- // Do button stays same size at upper right
- rect.SetRect(
- max( rectBorder.left, rectBorder.right - 16 ), // left
- rectBorder.top, // top
- rectBorder.right, // right
- min( rectBorder.bottom, rectBorder.top + 21 ) // bottom
- );
- m_pDo->MoveWindow( rect );
- m_pDo->Invalidate();
- // Command box is from left to button, height according to number of lines
- const int nPixelsPerLine = 13, nPixelsBorder = 8;
- int nLinesPossible = (rectBorder.Height() - nPixelsBorder) / nPixelsPerLine;
- int nLineCount = max( 1, min( nLinesPossible/2, m_pIn->GetLineCount() ) );
- int nInputHeight = nPixelsBorder + nPixelsPerLine * nLineCount;
- rect.SetRect(
- rectBorder.left, // left
- rectBorder.top, // top
- rectBorder.right - 16 - 3, // right
- min( rectBorder.bottom, rectBorder.top + nInputHeight ) // bottom
- );
- m_pIn->MoveWindow( rect );
- m_pIn->Invalidate();
- // Output
- rect.SetRect(
- rectBorder.left, // left
- rectBorder.top + rect.Height() + 3, // top
- rectBorder.right, // right
- rectBorder.bottom // bottom
- );
- m_pOut->MoveWindow( rect );
- m_pOut->Invalidate();
- }
- }
- void CCommand::ParseCommandDefn( CString csDefn, CCommand::ParsedCommand* pCmd )
- {
- //
- // Break csDefn into four pieces
- // format: service.command args#description
- //
- // Is there a description?
- int nPoundOffset = csDefn.Find("#");
- if ( nPoundOffset >= 0 )
- {
- pCmd->csDescription = csDefn.Mid(nPoundOffset+1);
- csDefn = csDefn.Left(nPoundOffset);
- }
- // Separate service, command and args
- int nCommandOffset = csDefn.Find(".") + 1;
- int nArgsOffset = csDefn.Find(" ") + 1;
- if ( nCommandOffset == 0 || nCommandOffset == csDefn.GetLength() )
- {
- pCmd->csCommand = csDefn;
- return;
- }
- pCmd->csService = csDefn.Left( nCommandOffset - 1 );
- // Are there any arguments
- if ( nArgsOffset == 0 )
- {
- // No arguments
- pCmd->csCommand = csDefn.Mid( nCommandOffset );
- }
- else
- {
- // Has arguments
- pCmd->csArgDefns = csDefn.Mid( nArgsOffset );
- pCmd->csCommand = csDefn.Mid( nCommandOffset, nArgsOffset - nCommandOffset - 1 );
- }
- }
- void CCommand::ParseCommandLine( LPCTSTR szCommand, const char* szaCommandDefns[] )
- {
- //
- // Parse command according to command definitions
- // If it starts with a valid command, set csCommand
- // If the arguments do not fit the command's definition, set m_csSyntaxError
- // If there are arguments, fill m_csaArgs
- // Apply default arguments and set m_csProcessedCommandLine
- // If the command was not found, leave entire line in m_csProcessedCommandLine
- //
- m_parsedcommand = ParsedCommand(); // empty ParsedCommand member
- m_parsedcommand.csCommand = szCommand;
- m_parsedcommand.csCommand.TrimLeft();
- m_parsedcommand.csCommand.TrimRight();
- m_csSyntaxError.Empty();
- m_csaArgs.RemoveAll();
- // Separate command from operand
- CString csOperand;
- int iSpace = m_parsedcommand.csCommand.Find( " " );
- if ( iSpace > -1 && iSpace + 1 < m_parsedcommand.csCommand.GetLength() )
- {
- csOperand = m_parsedcommand.csCommand.Mid( iSpace + 1 );
- m_parsedcommand.csCommand = m_parsedcommand.csCommand.Left( iSpace );
- m_parsedcommand.csCommand.MakeLower();
- }
- // Look for command definition in array, set m_parsedcommand.csService etc
- int iCmd = 0;
- while ( szaCommandDefns[iCmd][0] )
- {
- ParsedCommand parsed;
- ParseCommandDefn( szaCommandDefns[iCmd], &parsed );
- if ( m_parsedcommand.csCommand == parsed.csCommand )
- {
- m_parsedcommand = parsed;
- break;
- }
- ++iCmd;
- }
- // Command not found?
- if ( m_parsedcommand.csService.IsEmpty() )
- {
- m_csSyntaxError = "unknown command";
- m_csProcessedCommandLine = szCommand;
- m_parsedcommand.csCommand.Empty();
- }
- else
- m_csProcessedCommandLine = m_parsedcommand.csCommand;
- // Parse argument definitions plus user's arguments into m_csaArgs
- // Build m_csProcessedCommandLine
- CString csRemainingDefns = m_parsedcommand.csArgDefns;
- BOOL bEndOfDefns = FALSE;
- while ( ! m_parsedcommand.csService.IsEmpty() && ! bEndOfDefns )
- {
- // Get argument definition
- CString csDefn;
- int iComma = csRemainingDefns.Find( ',' );
- if ( iComma > -1 )
- {
- // take up to comma
- csDefn = csRemainingDefns.Left( iComma );
- csRemainingDefns = csRemainingDefns.Mid( iComma + 1 );
- }
- else
- {
- // last argument definition
- csDefn = csRemainingDefns;
- csRemainingDefns.Empty();
- bEndOfDefns = TRUE;
- }
- // Are there are no arguments in command?
- if ( csDefn.IsEmpty() )
- {
- // csOperand must be empty
- if ( ! csOperand.IsEmpty() )
- {
- m_csSyntaxError = "syntax: no arguments";
- m_parsedcommand.csService.Empty();
- }
- // Do not create any items in csaArgs[]
- break;
- }
- // Get user's argument
- CString csArg;
- iComma = csOperand.Find( ',' );
- if ( iComma > -1 && ! bEndOfDefns )
- {
- // take up to comma
- csArg = csOperand.Left( iComma );
- csOperand = csOperand.Mid( iComma + 1 );
- }
- else
- {
- // last argument
- csArg = csOperand;
- csOperand.Empty();
- }
- // Get argument default
- // Argument is required unless default is provided
- // For empty argument default in defn just specify =
- // empty user value for arg is not accepted unless default is empty
- CString csDefault;
- BOOL bRequired = TRUE;
- int iEqual = csDefn.Find('=');
- if ( iEqual > -1 )
- {
- csDefault = csDefn.Mid( iEqual + 1 );
- bRequired = FALSE;
- }
- // Make sure there is a value if required
- csArg.TrimLeft();
- csArg.TrimRight();
- if ( csArg.IsEmpty() && bRequired )
- {
- m_csSyntaxError.Format( "syntax: %s %s", m_parsedcommand.csCommand, m_parsedcommand.csArgDefns );
- m_parsedcommand.csService.Empty();
- break;
- }
- // Use default arg if none supplied by user
- if ( csArg.IsEmpty() )
- csArg = csDefault;
- // Add to arg array
- m_csaArgs.Add( csArg );
- // Add to parsed command string
- if ( m_csaArgs.GetSize() == 1 )
- m_csProcessedCommandLine += " ";
- else
- m_csProcessedCommandLine += ",";
- m_csProcessedCommandLine += csArg;
- }
- }
- CString CCommand::GetTimeDate()
- {
- SYSTEMTIME systemtime;
- GetLocalTime( &systemtime );
- CString csTimeDate;
- csTimeDate.Format( "%02d:%02d:%02d %s",
- systemtime.wHour,
- systemtime.wMinute,
- systemtime.wSecond,
- // systemtime.wMilliseconds,
- CTime::GetCurrentTime().Format("%b %d")
- );
- return csTimeDate;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CCmdOutCtrl
- //
- // Don't forget AfxInitRichEdit() in App.InitInstance()
- // or the app will just hang silently
- //
- CCmdOutCtrl::CCmdOutCtrl()
- {
- m_bEraseBackground = FALSE;
- m_pCmd = NULL;
- SetFontFace();
- }
- void CCmdOutCtrl::SetFontFace( CString csFaceName )
- {
- if ( csFaceName.IsEmpty() )
- m_csFaceName = "MS Sans Serif";
- else
- m_csFaceName = csFaceName;
- }
- CCmdOutCtrl::~CCmdOutCtrl()
- {
- }
- #define ID_RUN_SELECTION 33000
- #define ID_COPY_TOCMDENTRY 33001
- #define ID_COPY_SELECTION 33002
- BEGIN_MESSAGE_MAP(CCmdOutCtrl, CRichEditCtrl)
- ON_COMMAND(ID_RUN_SELECTION, OnRunSelection)
- ON_COMMAND(ID_COPY_TOCMDENTRY, OnCopyToCmdEntry)
- ON_COMMAND(ID_COPY_SELECTION, OnCopySelection)
- //{{AFX_MSG_MAP(CCmdOutCtrl)
- ON_WM_SYSCOLORCHANGE()
- ON_WM_ERASEBKGND()
- ON_WM_RBUTTONDOWN()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- void CCmdOutCtrl::OnSysColorChange()
- {
- CRichEditCtrl::OnSysColorChange();
- SetBackgroundColor( FALSE, GetSysColor(COLOR_BTNFACE) );
- }
- BOOL CCmdOutCtrl::OnEraseBkgnd(CDC* pDC)
- {
- if ( ! m_bEraseBackground )
- {
- SetBackgroundColor( FALSE, GetSysColor(COLOR_BTNFACE) );
- SetTargetDevice(NULL, 0);
- m_bEraseBackground = TRUE;
- }
- return CRichEditCtrl::OnEraseBkgnd(pDC);
- }
- void CCmdOutCtrl::OnRButtonDown(UINT nFlags, CPoint point)
- {
- // Make sure there is a selection
- DWORD dwHit = SendMessage( EM_CHARFROMPOS, 0, (LPARAM)&point );
- WORD nChar = LOWORD( dwHit );
- long nStartChar, nEndChar;
- GetSel( nStartChar, nEndChar );
- if ( GetSelText().IsEmpty() ||
- ((nChar < nStartChar || nChar > nEndChar ) && (nChar > 0 || nChar > -1)) )
- {
- int nLine = LineFromChar( nChar );
- nStartChar = LineIndex( nLine );
- nEndChar = GetLineCount() > nLine + 1? LineIndex(nLine+1)-1: -1;
- SetSel( nStartChar, nEndChar );
- }
- SetFocus();
- // Make popup menu
- CMenu menu;
- menu.CreatePopupMenu();
- menu.AppendMenu( MF_STRING, ID_RUN_SELECTION, "&Run" );
- menu.AppendMenu( MF_STRING, ID_COPY_TOCMDENTRY, "Copy to Command &Entry" );
- menu.AppendMenu( MF_STRING, ID_COPY_SELECTION, "&Copy" );
- ClientToScreen(&point);
- menu.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );
- }
- void CCmdOutCtrl::OnRunSelection()
- {
- OnCopyToCmdEntry();
- if ( m_pCmd && m_pCmd->m_pDo )
- {
- // Simulate clicking of Do button
- int idDo = m_pCmd->m_pDo->GetDlgCtrlID();
- m_pCmd->m_pWnd->PostMessage( WM_COMMAND, idDo, BN_CLICKED );
- }
- }
- void CCmdOutCtrl::OnCopyToCmdEntry()
- {
- if ( m_pCmd && m_pCmd->m_pIn )
- {
- // Copy text to the command input control, and set focus there
- m_pCmd->m_pIn->SetCommandText( GetSelText() );
- m_pCmd->m_pIn->SetFocus();
- }
- }
- void CCmdOutCtrl::OnCopySelection()
- {
- Copy();
- }
- void CCmdOutCtrl::Output( CString csOut, int nEffect, CString* pcsRolledOver )
- {
- // Create csCRLF line by line to convert n to rn
- // And add crlf at the end
- CString csCRLF;
- CString csLine = csOut.SpanExcluding( "n" );
- while ( csOut.GetLength() )
- {
- // Extract csLine from csOut
- int iNextLine = csLine.GetLength() + 1;
- if ( iNextLine >= csOut.GetLength() )
- csOut.Empty(); // last line
- else
- csOut = csOut.Mid( iNextLine );
- // Fix ending of line
- if ( csLine.GetLength() && csLine.Right(1) != 'r' )
- csLine += 'r';
- csLine += 'n';
- csCRLF += csLine;
- csLine = csOut.SpanExcluding( "n" );
- }
- // Clear output after roll-over limit of chars
- const int nRollOverChar = 25000;
- long nStartChar, nEndChar;
- if ( ::IsWindow(m_hWnd) )
- {
- // Query formatting the first time
- static CHARFORMAT format;
- static BOOL bFirstCheck = FALSE;
- static LONG yInitialHeight;
- static LONG yStandardHeight;
- if ( ! bFirstCheck )
- {
- format.cbSize = sizeof(CHARFORMAT);
- format.dwMask = CFM_SIZE;
- GetDefaultCharFormat( format );
- yInitialHeight = format.yHeight;
- yStandardHeight = format.yHeight * 5 / 4;
- bFirstCheck = TRUE;
- }
- // Set selection for inserting text
- SetSel( nRollOverChar,-1 );
- GetSel( nStartChar, nEndChar );
- if ( nStartChar >= nRollOverChar )
- {
- // roll-over
- SetSel( 0,-1 );
- if ( pcsRolledOver )
- GetWindowText( *pcsRolledOver );
- csCRLF = "rnreached max outputrn" + csCRLF;
- }
- // Set char formatting
- format.cbSize = sizeof(CHARFORMAT);
- format.dwMask = CFM_BOLD | CFM_SIZE | CFM_ITALIC | CFM_UNDERLINE | CFM_FACE;
- format.dwEffects = 0;
- format.yHeight = yStandardHeight;
- strcpy( format.szFaceName, m_csFaceName );
- if ( nEffect & Bold )
- format.dwEffects |= CFE_BOLD;
- if ( nEffect & Underline )
- format.dwEffects |= CFE_UNDERLINE;
- if ( nEffect & Italic )
- format.dwEffects |= CFE_ITALIC;
- if ( nEffect & Large )
- format.yHeight = yStandardHeight * 7 / 4;
- if ( nEffect & Small )
- format.yHeight = yStandardHeight * 2 / 3;
- SetSelectionCharFormat( format );
- // Insert text
- ReplaceSel( csCRLF );
- // Scroll so most recent text is in view
- // Start at top visible line and find last visible line
- CRect rect;
- GetRect( &rect );
- if ( rect.Width() > 20 )
- {
- int nLineCount = GetLineCount();
- int nLine = GetFirstVisibleLine();
- while ( nLine < nLineCount )
- {
- long lChar = LineIndex( nLine );
- if ( GetCharPos( lChar ).y > rect.bottom - 10 )
- break;
- nLine++;
- }
- LineScroll( nLineCount - nLine );
- }
- }
- }
- void CCmdOutCtrl::OutputHelp( CString csCommand, const char* szaCommandDefns[] )
- {
- // Output help directly to the control
- // If csCommand is *, show help on all commands in aCommandDefns
- BOOL bAll = csCommand == "*";
- int iCmd = 0;
- CString csServiceHeading;
- for ( iCmd = 0; szaCommandDefns[iCmd][0]; ++iCmd )
- {
- CCommand::ParsedCommand parsed;
- CCommand::ParseCommandDefn( szaCommandDefns[iCmd], &parsed );
- if ( bAll || csCommand == parsed.csCommand || csCommand == parsed.csService )
- {
- // Service heading if needed
- if ( parsed.csService != csServiceHeading )
- {
- csServiceHeading = parsed.csService;
- CString csServiceTitle;
- csServiceTitle.Format( "%s commandsn", csServiceHeading );
- Output( csServiceTitle, Underline );
- }
- // Line containing syntax and description
- CString csLine,csDescription;
- if ( ! parsed.csDescription.IsEmpty() )
- csDescription.Format( " (%s)", parsed.csDescription );
- csLine.Format( "%s %s%s", parsed.csCommand, parsed.csArgDefns, csDescription );
- Output( csLine );
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CCmdInCtrl
- CCmdInCtrl::CCmdInCtrl()
- {
- m_pCmd = NULL;
- m_nLines = 1;
- }
- CCmdInCtrl::~CCmdInCtrl()
- {
- }
- BEGIN_MESSAGE_MAP(CCmdInCtrl, CEdit)
- //{{AFX_MSG_MAP(CCmdInCtrl)
- ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- void CCmdInCtrl::CheckLines()
- {
- int nPrevNewLines = m_nLines;
- m_nLines = GetLineCount();
- if ( nPrevNewLines != m_nLines && m_pCmd )
- m_pCmd->Resize();
- }
- void CCmdInCtrl::OnChange()
- {
- CheckLines();
- }