?? commandctrl.cpp
字號(hào):
// 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 \r\n
// 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 = "\r\nreached max output\r\n" + 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 commands\n", 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();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -