界面效果如下:
出自:- http://www.cppblog.com/aaxron 转载必须注明!
#pragma once
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
template<typename T>
class CShellImpl
{
public:
CShellImpl(void)
{
m_nCmdRet = 0;
m_strCmdPrompt = ">>>";
m_strCmdNotFound = "command not found";
InitInternalCmd();
}
virtual ~CShellImpl(void)
{
}
typedef BOOL (T::*CMDPROC)(int argc,const vector<string>* argv);
typedef struct __tag_CMD_ENTRY
{
string strCmd;
string strCmdUsage;
string strCmdDesc;
CMDPROC pfCmdProc;
}CMD_ENTRY;
void AddCmd(TCHAR* pszCmd,TCHAR* pszCmdUsage,TCHAR* pszCmdDesc,CMDPROC pfProc)
{
CMD_ENTRY cmdEntry;
cmdEntry.strCmd = pszCmd;
cmdEntry.strCmdUsage = pszCmdUsage;
cmdEntry.strCmdDesc = pszCmdDesc;
cmdEntry.pfCmdProc = pfProc;
m_ExternalCmdEntrys.push_back(cmdEntry);
}
private:
void AddInternalCmd(TCHAR* pszCmd,TCHAR* pszCmdUsage,TCHAR* pszCmdDesc,CMDPROC pfProc)
{
CMD_ENTRY cmdEntry;
cmdEntry.strCmd = pszCmd;
cmdEntry.strCmdUsage = pszCmdUsage;
cmdEntry.strCmdDesc = pszCmdDesc;
cmdEntry.pfCmdProc = pfProc;
m_InternalCmdEntrys.push_back(cmdEntry);
}
void InitInternalCmd()
{
AddInternalCmd("?","","Show All Commands",&T::CmdShowAllCmd);
AddInternalCmd("quit","","Quit",&T::CmdQuit);
AddInternalCmd("clear","","Clear Screen",&T::CmdClear);
AddInternalCmd("echo","","Echo Var Value",&T::CmdEcho);
}
int ShowCmdHelp(int argc,const vector<string>* argv)
{
}
int CmdEcho(int argc,const vector<string>* argv)
{
printf("%d\r\n",m_nCmdRet);
return 0;
}
int CmdClear(int argc,const vector<string>* argv)
{
HANDLE hOutput;
DWORD dwWritten;
COORD coord;
CONSOLE_SCREEN_BUFFER_INFO csbi;
// Open the currently active screen buffer
hOutput = CreateFile(TEXT("CONOUT$"),
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hOutput)
return GetLastError();
// Get the screen buffer information
GetConsoleScreenBufferInfo(hOutput, &csbi);
coord.X = coord.Y = 0;
// Clear the screen in the most efficient way
FillConsoleOutputCharacter(hOutput, (TCHAR)' ', csbi.dwSize.Y*csbi.dwSize.X, coord, &dwWritten);
// Move to (0,0)
SetConsoleCursorPosition(hOutput, coord);
// Close the handle
CloseHandle(hOutput);
return 0;
}
int CmdQuit(int argc,const vector<string>* argv)
{
exit(0);
}
int CmdShowAllCmd(int argc,const vector<string>* argv)
{
//查找内部命令
for (int i=0;i<m_InternalCmdNums;i++)
{
cout<<setiosflags(ios::left)<<setw(32);
if (m_InternalCmdEntrys[i].strCmdUsage.empty())
{
cout<<m_InternalCmdEntrys[i].strCmd;
}
else{
cout<<m_InternalCmdEntrys[i].strCmdUsage;
}
cout<<m_InternalCmdEntrys[i].strCmdDesc<<endl;
}
//查找外部命令
for (int i=0;i<m_ExternalCmdNums;i++)
{
cout<<setiosflags(ios::left)<<setw(32);
if (m_ExternalCmdEntrys[i].strCmdUsage.empty())
{
cout<<m_ExternalCmdEntrys[i].strCmd;
}
else{
cout<<m_ExternalCmdEntrys[i].strCmdUsage;
}
cout<<m_ExternalCmdEntrys[i].strCmdDesc<<endl;
}
return 0;
}
inline void ShowCmdPrompt(BOOL bListStyle=TRUE)
{
printf(m_strCmdPrompt.c_str());
}
inline void ShowCmdNotFound()
{
puts(m_strCmdNotFound.c_str());
}
inline void SetCmdPrompt(const char* szCmdPrompt)
{
m_strCmdPrompt = szCmdPrompt;
}
inline void SetCmdNotFound(const char* szCmdNotFound)
{
m_strCmdNotFound = szCmdNotFound;
}
public:
void ProcCmdLoop()
{
string strInput;
string strCmd;
BOOL doNextLoop = TRUE;
BOOL bCmdNotFound = TRUE;
vector<string> argv;
int argc = 0;
m_InternalCmdNums = m_InternalCmdEntrys.size();
m_ExternalCmdNums = m_ExternalCmdEntrys.size();
while(doNextLoop)
{
ShowCmdPrompt();
getline(cin,strInput);
Trim(strInput);
//命令为空
if (strInput.empty())
{
continue;
}
argc = CmdLineToArgv(strInput.c_str(),argv);
strCmd = argv[0];
if (strCmd == "?")
{
CmdShowAllCmd(argc,NULL);
continue;
}
bCmdNotFound = TRUE;
//查找内部命令
for (int i=0;i<m_InternalCmdNums;i++)
{
if (m_InternalCmdEntrys[i].strCmd == strCmd)
{
m_nCmdRet = (((T*)this)->*m_InternalCmdEntrys[i].pfCmdProc)(argc,&argv);
bCmdNotFound = FALSE;
break;
}
}
//命令不存在
if (bCmdNotFound)
{
//查找外部命令
for (int i=0;i<m_ExternalCmdNums;i++)
{
if (m_ExternalCmdEntrys[i].strCmd == strCmd)
{
m_nCmdRet = (((T*)this)->*m_ExternalCmdEntrys[i].pfCmdProc)(argc,&argv);
bCmdNotFound = FALSE;
break;
}
}
}
//命令不存在
if (bCmdNotFound)
{
ShowCmdNotFound();
}
}
}
string& TrimLeft(string &strInput)
{
string::iterator p=find_if(strInput.begin(),strInput.end(),not1(ptr_fun(isspace)));
strInput.erase(strInput.begin(),p);
return strInput;
}
string& TrimRight(string &strInput)
{
string::reverse_iterator p=find_if(strInput.rbegin(),strInput.rend(),not1(ptr_fun(isspace)));
strInput.erase(p.base(),strInput.end());
return strInput;
}
inline string& Trim(string &strInput)
{
TrimLeft(TrimRight(strInput));
return strInput;
}
DWORD CmdLineToArgv(const char* szCmdLine,std::vector<std::string>& argv)
{
LPWSTR *szArglist;
int argc;
szArglist = CommandLineToArgvW(CA2W(szCmdLine),&argc);
argv.clear();
if( NULL == szArglist )
{
return 0;
}
for(int i=0; i<argc; i++)
{
argv.push_back((LPCSTR)CW2A(szArglist[i]));
}
LocalFree(szArglist);
return argc;
}
private:
vector<CMD_ENTRY> m_ExternalCmdEntrys; //外部命令
private:
vector<CMD_ENTRY> m_InternalCmdEntrys; //内部命令
string m_strCmdPrompt;
string m_strCmdNotFound;
int m_nCmdRet;
DWORD m_InternalCmdNums;
DWORD m_ExternalCmdNums;
};
调用部分:
//main.cpp
#include "stdafx.h"
#include "ShellImpl.h"
class MyShell:public CShellImpl<MyShell>
{
public:
int ProcCmdOpen(int argc,const vector<string>* argv)
{
puts(argv->at(0).c_str());
system("pause");
return TRUE;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyShell shell;
shell.AddCmd("open","open <ip> [devid] [port]","open a remote device",&MyShell::ProcCmdOpen);
shell.ProcCmdLoop();
return 0;
}