CommandCtrl.cpp
上传用户:xaxinn
上传日期:2007-01-03
资源大小:39k
文件大小:15k
源码类别:

Oracle数据库

开发平台:

Visual C++

  1. // CommandCtrl.cpp : implementation file
  2. //
  3. // Release 1, Copyright (C) 1999 Ben Bryant
  4. // This is sample source code, nothing more is implied. Use it only as such.
  5. // This software is provided 'as-is', without warranty. In no event will the
  6. // author be held liable for any damages arising from the use of this software.
  7. // Permission is granted to anyone to use this software for any purpose.
  8. // The origin of this software must not be misrepresented; you must not claim
  9. // that you wrote the original software. Altered source versions must be plainly
  10. // marked as such, and must not be misrepresented as being the original software.
  11. // Ben Bryant bcbryant@firstobject.com
  12. //
  13. #include "stdafx.h"
  14. #include "CommandCtrl.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CCommand
  22. CCommand::CCommand()
  23. {
  24. m_pWnd = NULL;
  25. m_pOut = NULL;
  26. m_pIn = NULL;
  27. m_pDo = NULL;
  28. }
  29. CCommand::~CCommand()
  30. {
  31. }
  32. void CCommand::Init( CWnd* pWnd, CCmdOutCtrl* pOut, CCmdInCtrl* pIn, CButton* pDo )
  33. {
  34. // Store pointers
  35. m_pOut = pOut;
  36. m_pOut->Set( this );
  37. m_pIn = pIn;
  38. m_pIn->Set( this );
  39. m_pDo = pDo;
  40. m_pWnd = pWnd;
  41. }
  42. void CCommand::Resize()
  43. {
  44. if ( m_pWnd )
  45. {
  46. CRect rect;
  47. m_pWnd->GetClientRect( &rect );
  48. m_pWnd->SendMessage(
  49. WM_SIZE,
  50. SIZE_RESTORED,
  51. MAKELPARAM(rect.Width(),rect.Height())
  52. );
  53. }
  54. }
  55. void CCommand::MoveControls( CRect& rectBorder )
  56. {
  57. if ( m_pDo && m_pIn && m_pOut )
  58. {
  59. // Position controls inside rectBorder
  60. CRect rect;
  61. // Do button stays same size at upper right
  62. rect.SetRect(
  63. max( rectBorder.left, rectBorder.right - 16 ), // left
  64. rectBorder.top, // top
  65. rectBorder.right, // right
  66. min( rectBorder.bottom, rectBorder.top + 21 ) // bottom
  67. );
  68. m_pDo->MoveWindow( rect );
  69. m_pDo->Invalidate();
  70. // Command box is from left to button, height according to number of lines
  71. const int nPixelsPerLine = 13, nPixelsBorder = 8;
  72. int nLinesPossible = (rectBorder.Height() - nPixelsBorder) / nPixelsPerLine;
  73. int nLineCount = max( 1, min( nLinesPossible/2, m_pIn->GetLineCount() ) );
  74. int nInputHeight = nPixelsBorder + nPixelsPerLine * nLineCount;
  75. rect.SetRect(
  76. rectBorder.left, // left
  77. rectBorder.top, // top
  78. rectBorder.right - 16 - 3, // right
  79. min( rectBorder.bottom, rectBorder.top + nInputHeight ) // bottom
  80. );
  81. m_pIn->MoveWindow( rect );
  82. m_pIn->Invalidate();
  83. // Output
  84. rect.SetRect(
  85. rectBorder.left, // left
  86. rectBorder.top + rect.Height() + 3, // top
  87. rectBorder.right, // right
  88. rectBorder.bottom // bottom
  89. );
  90. m_pOut->MoveWindow( rect );
  91. m_pOut->Invalidate();
  92. }
  93. }
  94. void CCommand::ParseCommandDefn( CString csDefn, CCommand::ParsedCommand* pCmd )
  95. {
  96. //
  97. // Break csDefn into four pieces
  98. // format: service.command args#description
  99. //
  100. // Is there a description?
  101. int nPoundOffset = csDefn.Find("#");
  102. if ( nPoundOffset >= 0 )
  103. {
  104. pCmd->csDescription = csDefn.Mid(nPoundOffset+1);
  105. csDefn = csDefn.Left(nPoundOffset);
  106. }
  107. // Separate service, command and args
  108. int nCommandOffset = csDefn.Find(".") + 1;
  109. int nArgsOffset = csDefn.Find(" ") + 1;
  110. if ( nCommandOffset == 0 || nCommandOffset == csDefn.GetLength() )
  111. {
  112. pCmd->csCommand = csDefn;
  113. return;
  114. }
  115. pCmd->csService = csDefn.Left( nCommandOffset - 1 );
  116. // Are there any arguments
  117. if ( nArgsOffset == 0 )
  118. {
  119. // No arguments
  120. pCmd->csCommand = csDefn.Mid( nCommandOffset );
  121. }
  122. else
  123. {
  124. // Has arguments
  125. pCmd->csArgDefns = csDefn.Mid( nArgsOffset );
  126. pCmd->csCommand = csDefn.Mid( nCommandOffset, nArgsOffset - nCommandOffset - 1 );
  127. }
  128. }
  129. void CCommand::ParseCommandLine( LPCTSTR szCommand, const char* szaCommandDefns[] )
  130. {
  131. //
  132. // Parse command according to command definitions
  133. // If it starts with a valid command, set csCommand
  134. // If the arguments do not fit the command's definition, set m_csSyntaxError
  135. // If there are arguments, fill m_csaArgs
  136. // Apply default arguments and set m_csProcessedCommandLine
  137. // If the command was not found, leave entire line in m_csProcessedCommandLine
  138. //
  139. m_parsedcommand = ParsedCommand(); // empty ParsedCommand member
  140. m_parsedcommand.csCommand = szCommand;
  141. m_parsedcommand.csCommand.TrimLeft();
  142. m_parsedcommand.csCommand.TrimRight();
  143. m_csSyntaxError.Empty();
  144. m_csaArgs.RemoveAll();
  145. // Separate command from operand
  146. CString csOperand;
  147. int iSpace = m_parsedcommand.csCommand.Find( " " );
  148. if ( iSpace > -1 && iSpace + 1 < m_parsedcommand.csCommand.GetLength() )
  149. {
  150. csOperand = m_parsedcommand.csCommand.Mid( iSpace + 1 );
  151. m_parsedcommand.csCommand = m_parsedcommand.csCommand.Left( iSpace );
  152. m_parsedcommand.csCommand.MakeLower();
  153. }
  154. // Look for command definition in array, set m_parsedcommand.csService etc
  155. int iCmd = 0;
  156. while ( szaCommandDefns[iCmd][0] )
  157. {
  158. ParsedCommand parsed;
  159. ParseCommandDefn( szaCommandDefns[iCmd], &parsed );
  160. if ( m_parsedcommand.csCommand == parsed.csCommand )
  161. {
  162. m_parsedcommand = parsed;
  163. break;
  164. }
  165. ++iCmd;
  166. }
  167. // Command not found?
  168. if ( m_parsedcommand.csService.IsEmpty() )
  169. {
  170. m_csSyntaxError = "unknown command";
  171. m_csProcessedCommandLine = szCommand;
  172. m_parsedcommand.csCommand.Empty();
  173. }
  174. else
  175. m_csProcessedCommandLine = m_parsedcommand.csCommand;
  176. // Parse argument definitions plus user's arguments into m_csaArgs
  177. // Build m_csProcessedCommandLine
  178. CString csRemainingDefns = m_parsedcommand.csArgDefns;
  179. BOOL bEndOfDefns = FALSE;
  180. while ( ! m_parsedcommand.csService.IsEmpty() && ! bEndOfDefns )
  181. {
  182. // Get argument definition
  183. CString csDefn;
  184. int iComma = csRemainingDefns.Find( ',' );
  185. if ( iComma > -1 )
  186. {
  187. // take up to comma
  188. csDefn = csRemainingDefns.Left( iComma );
  189. csRemainingDefns = csRemainingDefns.Mid( iComma + 1 );
  190. }
  191. else
  192. {
  193. // last argument definition
  194. csDefn = csRemainingDefns;
  195. csRemainingDefns.Empty();
  196. bEndOfDefns = TRUE;
  197. }
  198. // Are there are no arguments in command?
  199. if ( csDefn.IsEmpty() )
  200. {
  201. // csOperand must be empty
  202. if ( ! csOperand.IsEmpty() )
  203. {
  204. m_csSyntaxError = "syntax: no arguments";
  205. m_parsedcommand.csService.Empty();
  206. }
  207. // Do not create any items in csaArgs[]
  208. break;
  209. }
  210. // Get user's argument
  211. CString csArg;
  212. iComma = csOperand.Find( ',' );
  213. if ( iComma > -1 && ! bEndOfDefns )
  214. {
  215. // take up to comma
  216. csArg = csOperand.Left( iComma );
  217. csOperand = csOperand.Mid( iComma + 1 );
  218. }
  219. else
  220. {
  221. // last argument
  222. csArg = csOperand;
  223. csOperand.Empty();
  224. }
  225. // Get argument default
  226. // Argument is required unless default is provided
  227. // For empty argument default in defn just specify =
  228. // empty user value for arg is not accepted unless default is empty
  229. CString csDefault;
  230. BOOL bRequired = TRUE;
  231. int iEqual = csDefn.Find('=');
  232. if ( iEqual > -1 )
  233. {
  234. csDefault = csDefn.Mid( iEqual + 1 );
  235. bRequired = FALSE;
  236. }
  237. // Make sure there is a value if required
  238. csArg.TrimLeft();
  239. csArg.TrimRight();
  240. if ( csArg.IsEmpty() && bRequired )
  241. {
  242. m_csSyntaxError.Format( "syntax: %s %s", m_parsedcommand.csCommand, m_parsedcommand.csArgDefns );
  243. m_parsedcommand.csService.Empty();
  244. break;
  245. }
  246. // Use default arg if none supplied by user
  247. if ( csArg.IsEmpty() )
  248. csArg = csDefault;
  249. // Add to arg array
  250. m_csaArgs.Add( csArg );
  251. // Add to parsed command string
  252. if ( m_csaArgs.GetSize() == 1 )
  253. m_csProcessedCommandLine += " ";
  254. else
  255. m_csProcessedCommandLine += ",";
  256. m_csProcessedCommandLine += csArg;
  257. }
  258. }
  259. CString CCommand::GetTimeDate()
  260. {
  261. SYSTEMTIME systemtime;
  262. GetLocalTime( &systemtime );
  263. CString csTimeDate;
  264. csTimeDate.Format( "%02d:%02d:%02d %s",
  265. systemtime.wHour,
  266. systemtime.wMinute,
  267. systemtime.wSecond,
  268. // systemtime.wMilliseconds,
  269. CTime::GetCurrentTime().Format("%b %d")
  270. );
  271. return csTimeDate;
  272. }
  273. /////////////////////////////////////////////////////////////////////////////
  274. // CCmdOutCtrl
  275. //
  276. // Don't forget AfxInitRichEdit() in App.InitInstance()
  277. // or the app will just hang silently
  278. //
  279. CCmdOutCtrl::CCmdOutCtrl()
  280. {
  281. m_bEraseBackground = FALSE;
  282. m_pCmd = NULL;
  283. SetFontFace();
  284. }
  285. void CCmdOutCtrl::SetFontFace( CString csFaceName )
  286. {
  287. if ( csFaceName.IsEmpty() )
  288. m_csFaceName = "MS Sans Serif";
  289. else
  290. m_csFaceName = csFaceName;
  291. }
  292. CCmdOutCtrl::~CCmdOutCtrl()
  293. {
  294. }
  295. #define ID_RUN_SELECTION 33000
  296. #define ID_COPY_TOCMDENTRY 33001
  297. #define ID_COPY_SELECTION 33002
  298. BEGIN_MESSAGE_MAP(CCmdOutCtrl, CRichEditCtrl)
  299. ON_COMMAND(ID_RUN_SELECTION, OnRunSelection)
  300. ON_COMMAND(ID_COPY_TOCMDENTRY, OnCopyToCmdEntry)
  301. ON_COMMAND(ID_COPY_SELECTION, OnCopySelection)
  302. //{{AFX_MSG_MAP(CCmdOutCtrl)
  303. ON_WM_SYSCOLORCHANGE()
  304. ON_WM_ERASEBKGND()
  305. ON_WM_RBUTTONDOWN()
  306. //}}AFX_MSG_MAP
  307. END_MESSAGE_MAP()
  308. void CCmdOutCtrl::OnSysColorChange() 
  309. {
  310. CRichEditCtrl::OnSysColorChange();
  311. SetBackgroundColor( FALSE, GetSysColor(COLOR_BTNFACE) );
  312. }
  313. BOOL CCmdOutCtrl::OnEraseBkgnd(CDC* pDC) 
  314. {
  315. if ( !  m_bEraseBackground )
  316. {
  317. SetBackgroundColor( FALSE, GetSysColor(COLOR_BTNFACE) );
  318. SetTargetDevice(NULL, 0);
  319. m_bEraseBackground = TRUE;
  320. }
  321. return CRichEditCtrl::OnEraseBkgnd(pDC);
  322. }
  323. void CCmdOutCtrl::OnRButtonDown(UINT nFlags, CPoint point) 
  324. {
  325. // Make sure there is a selection
  326. DWORD dwHit = SendMessage( EM_CHARFROMPOS, 0, (LPARAM)&point );
  327. WORD nChar = LOWORD( dwHit );
  328. long nStartChar, nEndChar;
  329. GetSel( nStartChar, nEndChar );
  330. if ( GetSelText().IsEmpty() ||
  331. ((nChar < nStartChar || nChar > nEndChar ) && (nChar > 0 || nChar > -1)) )
  332. {
  333. int nLine = LineFromChar( nChar );
  334. nStartChar = LineIndex( nLine );
  335. nEndChar = GetLineCount() > nLine + 1? LineIndex(nLine+1)-1: -1;
  336. SetSel( nStartChar, nEndChar );
  337. }
  338. SetFocus();
  339. // Make popup menu
  340. CMenu menu;
  341. menu.CreatePopupMenu();
  342. menu.AppendMenu( MF_STRING, ID_RUN_SELECTION, "&Run" );
  343. menu.AppendMenu( MF_STRING, ID_COPY_TOCMDENTRY, "Copy to Command &Entry" );
  344. menu.AppendMenu( MF_STRING, ID_COPY_SELECTION, "&Copy" );
  345. ClientToScreen(&point);
  346. menu.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );
  347. }
  348. void CCmdOutCtrl::OnRunSelection()
  349. {
  350. OnCopyToCmdEntry();
  351. if ( m_pCmd && m_pCmd->m_pDo )
  352. {
  353. // Simulate clicking of Do button
  354. int idDo = m_pCmd->m_pDo->GetDlgCtrlID();
  355. m_pCmd->m_pWnd->PostMessage( WM_COMMAND, idDo, BN_CLICKED );
  356. }
  357. }
  358. void CCmdOutCtrl::OnCopyToCmdEntry()
  359. {
  360. if ( m_pCmd && m_pCmd->m_pIn )
  361. {
  362. // Copy text to the command input control, and set focus there
  363. m_pCmd->m_pIn->SetCommandText( GetSelText() );
  364. m_pCmd->m_pIn->SetFocus();
  365. }
  366. }
  367. void CCmdOutCtrl::OnCopySelection()
  368. {
  369. Copy();
  370. }
  371. void CCmdOutCtrl::Output( CString csOut, int nEffect, CString* pcsRolledOver )
  372. {
  373. // Create csCRLF line by line to convert n to rn
  374. // And add crlf at the end
  375. CString csCRLF;
  376. CString csLine = csOut.SpanExcluding( "n" );
  377. while ( csOut.GetLength() )
  378. {
  379. // Extract csLine from csOut
  380. int iNextLine = csLine.GetLength() + 1;
  381. if ( iNextLine >= csOut.GetLength() )
  382. csOut.Empty(); // last line
  383. else
  384. csOut = csOut.Mid( iNextLine );
  385. // Fix ending of line
  386. if ( csLine.GetLength() && csLine.Right(1) != 'r' )
  387. csLine += 'r';
  388. csLine += 'n';
  389. csCRLF += csLine;
  390. csLine = csOut.SpanExcluding( "n" );
  391. }
  392. // Clear output after roll-over limit of chars
  393. const int nRollOverChar = 25000;
  394. long nStartChar, nEndChar;
  395. if ( ::IsWindow(m_hWnd) )
  396. {
  397. // Query formatting the first time
  398. static CHARFORMAT format;
  399. static BOOL bFirstCheck = FALSE;
  400. static LONG yInitialHeight;
  401. static LONG yStandardHeight;
  402. if ( ! bFirstCheck )
  403. {
  404. format.cbSize = sizeof(CHARFORMAT);
  405. format.dwMask = CFM_SIZE;
  406. GetDefaultCharFormat( format );
  407. yInitialHeight = format.yHeight;
  408. yStandardHeight = format.yHeight * 5 / 4;
  409. bFirstCheck = TRUE;
  410. }
  411. // Set selection for inserting text
  412. SetSel( nRollOverChar,-1 );
  413. GetSel( nStartChar, nEndChar );
  414. if ( nStartChar >= nRollOverChar )
  415. {
  416. // roll-over
  417. SetSel( 0,-1 );
  418. if ( pcsRolledOver )
  419. GetWindowText( *pcsRolledOver );
  420. csCRLF = "rnreached max outputrn" + csCRLF;
  421. }
  422. // Set char formatting
  423. format.cbSize = sizeof(CHARFORMAT);
  424. format.dwMask = CFM_BOLD | CFM_SIZE | CFM_ITALIC | CFM_UNDERLINE | CFM_FACE;
  425. format.dwEffects = 0;
  426. format.yHeight = yStandardHeight;
  427. strcpy( format.szFaceName, m_csFaceName );
  428. if ( nEffect & Bold )
  429. format.dwEffects |= CFE_BOLD;
  430. if ( nEffect & Underline )
  431. format.dwEffects |= CFE_UNDERLINE;
  432. if ( nEffect & Italic )
  433. format.dwEffects |= CFE_ITALIC;
  434. if ( nEffect & Large )
  435. format.yHeight = yStandardHeight * 7 / 4;
  436. if ( nEffect & Small )
  437. format.yHeight = yStandardHeight * 2 / 3;
  438. SetSelectionCharFormat( format );
  439. // Insert text
  440. ReplaceSel( csCRLF );
  441. // Scroll so most recent text is in view
  442. // Start at top visible line and find last visible line
  443. CRect rect;
  444. GetRect( &rect );
  445. if ( rect.Width() > 20 )
  446. {
  447. int nLineCount = GetLineCount();
  448. int nLine = GetFirstVisibleLine();
  449. while ( nLine < nLineCount )
  450. {
  451. long lChar = LineIndex( nLine );
  452. if ( GetCharPos( lChar ).y > rect.bottom - 10 )
  453. break;
  454. nLine++;
  455. }
  456. LineScroll( nLineCount - nLine );
  457. }
  458. }
  459. }
  460. void CCmdOutCtrl::OutputHelp( CString csCommand, const char* szaCommandDefns[] )
  461. {
  462. // Output help directly to the control
  463. // If csCommand is *, show help on all commands in aCommandDefns
  464. BOOL bAll = csCommand == "*";
  465. int iCmd = 0;
  466. CString csServiceHeading;
  467. for ( iCmd = 0; szaCommandDefns[iCmd][0]; ++iCmd )
  468. {
  469. CCommand::ParsedCommand parsed;
  470. CCommand::ParseCommandDefn( szaCommandDefns[iCmd], &parsed );
  471. if ( bAll || csCommand == parsed.csCommand || csCommand == parsed.csService )
  472. {
  473. // Service heading if needed
  474. if ( parsed.csService != csServiceHeading )
  475. {
  476. csServiceHeading = parsed.csService;
  477. CString csServiceTitle;
  478. csServiceTitle.Format( "%s commandsn", csServiceHeading );
  479. Output( csServiceTitle, Underline );
  480. }
  481. // Line containing syntax and description
  482. CString csLine,csDescription;
  483. if ( ! parsed.csDescription.IsEmpty() )
  484. csDescription.Format( " (%s)", parsed.csDescription );
  485. csLine.Format( "%s %s%s", parsed.csCommand, parsed.csArgDefns, csDescription );
  486. Output( csLine );
  487. }
  488. }
  489. }
  490. /////////////////////////////////////////////////////////////////////////////
  491. // CCmdInCtrl
  492. CCmdInCtrl::CCmdInCtrl()
  493. {
  494. m_pCmd = NULL;
  495. m_nLines = 1;
  496. }
  497. CCmdInCtrl::~CCmdInCtrl()
  498. {
  499. }
  500. BEGIN_MESSAGE_MAP(CCmdInCtrl, CEdit)
  501. //{{AFX_MSG_MAP(CCmdInCtrl)
  502. ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
  503. //}}AFX_MSG_MAP
  504. END_MESSAGE_MAP()
  505. void CCmdInCtrl::CheckLines() 
  506. {
  507. int nPrevNewLines = m_nLines;
  508. m_nLines = GetLineCount();
  509. if ( nPrevNewLines != m_nLines && m_pCmd )
  510. m_pCmd->Resize();
  511. }
  512. void CCmdInCtrl::OnChange() 
  513. {
  514. CheckLines();
  515. }