CommandLine.cpp
上传用户:sdzdgs
上传日期:2020-11-14
资源大小:1589k
文件大小:29k
源码类别:

编辑框

开发平台:

Visual C++

  1. //  CommandLine.cpp : implementation file
  2. /////////////////////////////////////////////////////////////////////////////
  3. /////////////////////////////////////////////////////////////////////////////
  4. //  CommandLine - a simple command line interface control with 
  5. //  a custom scrollbar
  6. //
  7. //  Author: Paul Grenz
  8. //  Email:  pgrenz@irlabs.com
  9. //
  10. //  You may freely use or modify this code provided this
  11. //  message is included in all derived versions.
  12. //
  13. //  History - 2004/10/28 Initial release to codeguru.com
  14. //
  15. //
  16. //  This class implements a command line interface with a custom 
  17. //  KDE/Unix-like scrollbar
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "MemDc.h"
  21. #include "CommandLine.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CommandLine
  29. /////////////////////////////////////////////////////////////////////////////
  30. BEGIN_MESSAGE_MAP(CCommandLine, CWnd)
  31. //{{AFX_MSG_MAP(CCommandLine)
  32. ON_WM_PAINT()
  33. ON_WM_SYSCOLORCHANGE()
  34. ON_WM_ERASEBKGND()
  35. ON_WM_KILLFOCUS()
  36. ON_WM_SETFOCUS()
  37. ON_WM_LBUTTONDOWN()
  38. ON_WM_LBUTTONUP()
  39. ON_WM_CHAR()
  40. ON_WM_KEYDOWN()
  41. ON_WM_TIMER()
  42. ON_WM_SIZE()
  43. ON_WM_GETDLGCODE()
  44. ON_WM_MOUSEMOVE()
  45. ON_WM_CREATE()
  46. ON_WM_MOUSEACTIVATE()
  47. //}}AFX_MSG_MAP
  48. END_MESSAGE_MAP()
  49. /////////////////////////////////////////////////////////////////////////////
  50. // Register the window class if it has not already been registered.
  51. bool CCommandLine::RegisterWindowClass()
  52. {
  53. WNDCLASS wndcls;
  54. HINSTANCE hInst = AfxGetInstanceHandle();
  55. //  HINSTANCE hInst = AfxGetResourceHandle();
  56. if (!(::GetClassInfo(hInst, COMMAND_LINE_CLASSNAME, &wndcls)))
  57. {
  58. //  otherwise we need to register a new class
  59. wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  60. wndcls.lpfnWndProc      = ::DefWindowProc;
  61. wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
  62. wndcls.hInstance        = hInst;
  63. wndcls.hIcon            = NULL;
  64. wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
  65. wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
  66. wndcls.lpszMenuName     = NULL;
  67. wndcls.lpszClassName    = COMMAND_LINE_CLASSNAME;
  68. if (!AfxRegisterClass(&wndcls))
  69. {
  70. AfxThrowResourceException();
  71. return FALSE;
  72. }
  73. }
  74. return TRUE;
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. CCommandLine::CCommandLine()
  78. {
  79. RegisterWindowClass();
  80. //  no reciever yet.
  81. m_pwndReceiver = NULL;
  82. //  create a default prompt.
  83. m_szPrompt = "Command: ";
  84. //  create the drawing objects to use.
  85. m_penArrows.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWTEXT));
  86. m_penShadow.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  87. m_brFace.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  88. //  create the font to use.
  89. LOGFONT lf;
  90. // Get a handle to the ANSI_FIXED_FONT.
  91. GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
  92. // Set the font attributes, as appropriate.
  93. lf.lfWeight = FW_NORMAL;
  94. //  make the font a bit bigger.
  95. lf.lfHeight *= 2;
  96. // Create the font, and then return its handle.
  97. m_fonText.CreateFontIndirect(&lf);
  98. //  set the input text.
  99. m_szInputLine = "";
  100. //  the initial caret position.
  101. m_nCaretPosX = 0;
  102. //  holds the position set for the caret by the mouse.
  103. m_ptCaret = CPoint(0, 0);
  104. //  was the caret positioned by the mouse?
  105. m_oCaretPositioned = false;
  106. //  set the command list index to -1.
  107. m_nInputPos = -1;
  108. //  there is no history yet.
  109. m_nLineIndex = -1;
  110. //  default number of spaces for each tab.
  111. m_nTabSpaces = 2;
  112. //  init last command.
  113. m_szLastCommand = "";
  114. //  how many lines can we see?
  115. m_nVisibleLines = 0;
  116. //  the default clear screen command.
  117. m_szClsCmd = "cls";
  118. //  the rectangles that hold the scroll buttons positions.
  119. m_rcScrollUpTop.SetRectEmpty();
  120. m_rcScrollUp.SetRectEmpty();
  121. m_rcScrollDn.SetRectEmpty();
  122. m_rcThumb.SetRectEmpty();
  123. m_rcScrollBar.SetRectEmpty();
  124. m_rcScrollTrack.SetRectEmpty();
  125. //  the scroll buttons are not pressed.
  126. m_oScrollUpTopPressed = false;
  127. m_oScrollUpPressed = false;
  128. m_oScrollDnPressed = false;
  129. //  the thumb is not being moved....
  130. m_oMouseDownThumb = false;
  131. //  where the thumb was dragged from.
  132. m_nThumbStartPos = 0;
  133. //  thumb min size.
  134. m_nMinThumbY = 0;
  135. //  not locked to start with.
  136. m_oIsLocked = false;
  137. }
  138. /////////////////////////////////////////////////////////////////////////////
  139. CCommandLine::~CCommandLine()
  140. {
  141. //  let go of the mouse
  142. ReleaseCapture();
  143. //  destroy the drawing objects.
  144. m_penArrows.DeleteObject();
  145. m_penShadow.DeleteObject();
  146. m_brFace.DeleteObject();
  147. }
  148. /////////////////////////////////////////////////////////////////////////////
  149. BOOL CCommandLine::Create(const RECT &rect, UINT uiFlags, CWnd *pParentWnd, UINT uiID)
  150. {
  151. return CWnd::Create(NULL, _T("CommandLine"), uiFlags, rect, pParentWnd, uiID);
  152. }
  153. /////////////////////////////////////////////////////////////////////////////
  154. BOOL CCommandLine::OnEraseBkgnd(CDC* pDC)
  155. {
  156. //  to eliminate flicker....
  157. return -1;
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. int CCommandLine::UpdateLine(int nIndex, CString szText)
  161. {
  162. if (nIndex<0 || nIndex>=m_vecLines.size())
  163. return -1;
  164. else
  165. {
  166. m_vecLines.at(nIndex) = szText;
  167. return nIndex;
  168. }
  169. }
  170. /////////////////////////////////////////////////////////////////////////////
  171. int CCommandLine::AddRecv(CString szText)
  172. {
  173. //  if display is full, remove the first line.
  174. if (m_vecLines.size()>MAX_DISPLAY_SIZE-1)
  175. {
  176. m_vecLines.erase(m_vecLines.begin());
  177. }
  178. //  add the line to the vector.
  179. m_vecLines.push_back(" < " + szText);
  180. //  set the current line.
  181. m_nLineIndex = m_vecLines.size()-1;
  182. //  update the screen pos.
  183. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  184. //  redraw the control.
  185. Invalidate(FALSE);
  186. //  finished okay.
  187. return m_nLineIndex;
  188. }
  189. /////////////////////////////////////////////////////////////////////////////
  190. int CCommandLine::AddRecv(char *pcText, ULONG unLength)
  191. {
  192. //  if display is full - remove the first line.
  193. if (m_vecLines.size()>MAX_DISPLAY_SIZE-1)
  194. {
  195. m_vecLines.erase(m_vecLines.begin());
  196. }
  197. //  copy the text from the array of char
  198. //  to a string, making sure to handle unprintable chars.
  199. CString szText;
  200. for (ULONG ii=0; ii<unLength; ii++)
  201. {
  202. int iCurr = (int)(pcText[ii]);
  203. switch (iCurr)
  204. {
  205. case 0: szText += "0x0 "; break;
  206. default: szText += (char)(iCurr);
  207. }
  208. }
  209. //  add the line to the vector.
  210. m_vecLines.push_back(" < " + szText);
  211. //  set the current line.
  212. m_nLineIndex = m_vecLines.size()-1;
  213. //  update the screen pos.
  214. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  215. //  redraw the control.
  216. Invalidate(FALSE);
  217. //  finished okay.
  218. return m_nLineIndex;
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. bool CCommandLine::ClearScreen()
  222. {
  223. //  clear the line vector.
  224. m_vecLines.clear();
  225. //  set the line index to reflect this.
  226. m_nLineIndex = -1;
  227. //  clear the line.
  228. m_szInputLine.Empty();
  229. //  caret at the front.
  230. m_nCaretPosX = 0;
  231. //  redraw the empty window.
  232. Invalidate(FALSE);
  233. return true;
  234. }
  235. /////////////////////////////////////////////////////////////////////////////
  236. int CCommandLine::AddSent(CString szText)
  237. {
  238. //  if display is full, remove the first line.
  239. if (m_vecLines.size()>MAX_DISPLAY_SIZE-1)
  240. {
  241. m_vecLines.erase(m_vecLines.begin());
  242. }
  243. //  add the line to the vector.
  244. m_vecLines.push_back(" > " + szText);
  245. //  is this the clear screen command?
  246. if (szText==m_szClsCmd)
  247. ClearScreen();
  248. //  set the current line.
  249. m_nLineIndex = m_vecLines.size()-1;
  250. //  update the screen pos.
  251. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  252. //  redraw the control.
  253. Invalidate(FALSE);
  254. //  finished okay.
  255. return m_nLineIndex;
  256. }
  257. /////////////////////////////////////////////////////////////////////////////
  258. int CCommandLine::AddSent(char *pcText, ULONG unLength)
  259. {
  260. //  if vector is full, remove the first line.
  261. if (m_vecLines.size()>MAX_DISPLAY_SIZE-1)
  262. {
  263. m_vecLines.erase(m_vecLines.begin());
  264. }
  265. //  copy the text from the array of char
  266. //  to a string, making sure to handle unprintable chars.
  267. CString szText;
  268. for (ULONG ii=0; ii<unLength; ii++)
  269. {
  270. int iCurr = (int)(pcText[ii]);
  271. switch (iCurr)
  272. {
  273. case 0: szText += "0x0 "; break;
  274. default: szText += (char)(iCurr);
  275. }
  276. }
  277. //  add the line to the vector.
  278. m_vecLines.push_back(" > " + szText);
  279. //  is this the clear screen command?
  280. if (szText==m_szClsCmd)
  281. ClearScreen();
  282. //  set the current line.
  283. m_nLineIndex = m_vecLines.size()-1;
  284. //  update the screen pos.
  285. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  286. //  redraw the control.
  287. Invalidate(FALSE);
  288. //  finished okay.
  289. return m_nLineIndex;
  290. }
  291. /////////////////////////////////////////////////////////////////////////////
  292. void CCommandLine::OnSysColorChange()
  293. {
  294. //  destroy the drawing objects.
  295. m_penArrows.DeleteObject();
  296. m_penShadow.DeleteObject();
  297. m_brFace.DeleteObject();
  298. //  recreate the drawing objects to use.
  299. m_penArrows.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWTEXT));
  300. m_penShadow.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  301. m_brFace.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  302. }
  303. /////////////////////////////////////////////////////////////////////////////
  304. void CCommandLine::OnPaint()
  305. {
  306. // device context for painting
  307. CPaintDC dc(this);
  308. //  create a memory dc.
  309. CMemDC dcMem(&dc);
  310. //  save their states.
  311. int nMemState = dcMem.SaveDC();
  312. int nDcState = dc.SaveDC();
  313. //  get the client rect.
  314. CRect rcClient;
  315. GetClientRect(rcClient);
  316. //  how wide & high is a scrollbar?
  317. SIZE siScroll;
  318. siScroll.cx = GetSystemMetrics(SM_CXVSCROLL);
  319. siScroll.cy = GetSystemMetrics(SM_CYVSCROLL);
  320. //  get the area to do the drawing in.
  321. CRect rcDisplay = rcClient;
  322. rcDisplay.DeflateRect(2, 2, siScroll.cx+2, 2);
  323. //  create the scrollbar rect.
  324. m_rcScrollBar = rcClient;
  325. m_rcScrollBar.DeflateRect(2, 2, 2, 2);
  326. m_rcScrollBar.left = rcDisplay.right;
  327. //  thumb min size in Y.
  328. m_nMinThumbY = siScroll.cy/2;
  329. //  create the scrollbar up top button rect
  330. m_rcScrollUpTop = m_rcScrollBar;
  331. m_rcScrollUpTop.top = m_rcScrollBar.top;
  332. m_rcScrollUpTop.bottom = m_rcScrollBar.top + siScroll.cy;
  333. //  create the scrollbar up button rect
  334. m_rcScrollUp = m_rcScrollBar;
  335. m_rcScrollUp.top = m_rcScrollBar.bottom - 2 * siScroll.cy;
  336. m_rcScrollUp.bottom = m_rcScrollBar.bottom - siScroll.cy;
  337. //  create the scrollbar dn button rect
  338. m_rcScrollDn = m_rcScrollBar;
  339. m_rcScrollDn.top = m_rcScrollBar.bottom - siScroll.cy;
  340. //  create a rect for the scroll track area.
  341. m_rcScrollTrack = m_rcScrollBar;
  342. m_rcScrollTrack.top += siScroll.cy + m_nMinThumbY;  //  one button on the top.
  343. m_rcScrollTrack.bottom -= 2 * siScroll.cy;  //  two buttons on the bottom.
  344. //  first select the font we want to use into the DC.
  345. CFont *pfonOld = dcMem.SelectObject(&m_fonText);
  346. //  then get the size of the input text.
  347. CSize siText = dcMem.GetTextExtent(m_szPrompt + m_szInputLine.Left(m_nCaretPosX));
  348. //  create a rect to hold the input line.
  349. CRect rcInputLine(rcDisplay);
  350. //  shrink the display so that it does not include the input line.
  351. rcDisplay.bottom -= siText.cy;
  352. //  shrink the input line so that it does not include the display.
  353. rcInputLine.top = rcInputLine.bottom - siText.cy;
  354. //  figure out how many whole lines will fit in the display area.
  355. m_nVisibleLines = (int)(rcDisplay.Height()/(siText.cy));
  356. //  what is the ratio of the track size to the number of lines?
  357. double xScrollRatio = (double)(m_rcScrollTrack.Height())/(double)(m_vecLines.size());
  358. //  calculate the number of visible lines in pixels = thumb size.
  359. int nThumbSize = m_nMinThumbY + (int)(xScrollRatio * (double)(m_nVisibleLines));
  360. //  is the the thumb at zero? (should be at the bottom, then)
  361. if (m_rcThumb.bottom == 0)
  362. m_rcThumb.bottom = m_rcScrollTrack.bottom;
  363. //  are there any lines at all?
  364. m_rcThumb.left = m_rcScrollTrack.left;
  365. m_rcThumb.right = m_rcScrollTrack.right;
  366. if (m_vecLines.size() > m_nVisibleLines)
  367. {
  368. m_rcThumb.top = m_rcThumb.bottom - nThumbSize;
  369. }
  370. else
  371. {
  372. m_rcThumb.bottom = m_rcScrollTrack.bottom;
  373. m_rcThumb.top = m_rcScrollTrack.top - m_nMinThumbY;
  374. }
  375. //  calculate a rect to hold one display line.
  376. CRect rcText(rcInputLine);
  377. rcText.OffsetRect(0, -siText.cy);
  378. //  if the mouse repositioned the caret,
  379. //  we must figure out where it should be drawn.
  380. if (m_oCaretPositioned==true)
  381. {
  382. CSize siPrompt = dcMem.GetTextExtent(m_szPrompt);
  383. CSize siInput = dcMem.GetTextExtent(m_szInputLine);
  384. int nChars = m_szInputLine.GetLength();
  385. int nAveCharWidth = (nChars>0) ? (siInput.cx / nChars) : (0);
  386. //  get the position in the input clicked on.
  387. int nPosX = m_ptCaret.x - siPrompt.cx;
  388. m_nCaretPosX = (nAveCharWidth>0) ? (nPosX / nAveCharWidth) : (0);
  389. m_nCaretPosX = (m_nCaretPosX>nChars) ? (nChars) : (m_nCaretPosX);
  390. m_oCaretPositioned = false;
  391. }
  392. //  draw the scrollbar background.
  393. dcMem.FillSolidRect(m_rcScrollBar, GetSysColor(COLOR_SCROLLBAR));
  394. //  select a pen & brush to draw the buttons.
  395. CPen *ppenOld = dcMem.SelectObject(&m_penShadow);
  396. CBrush *pbrOld = dcMem.SelectObject(&m_brFace);
  397. //  draw the thumb.
  398. dcMem.FillSolidRect(m_rcThumb, GetSysColor(COLOR_3DFACE));
  399. dcMem.DrawEdge(m_rcThumb, EDGE_RAISED, BF_RECT);
  400. //  draw the buttons as though they are down.
  401. dcMem.Rectangle(m_rcScrollUpTop);
  402. dcMem.Rectangle(m_rcScrollUp);
  403. dcMem.Rectangle(m_rcScrollDn);
  404. //  is the up top button NOT pressed (draw raised edge).
  405. if (m_oScrollUpTopPressed==false)
  406. dcMem.DrawEdge(m_rcScrollUpTop, EDGE_RAISED, BF_RECT);
  407. //  is the up bottom button NOT pressed (draw raised edge).
  408. if (m_oScrollUpPressed==false)
  409. dcMem.DrawEdge(m_rcScrollUp, EDGE_RAISED, BF_RECT);
  410. //  is the dn button NOT pressed (draw raised edge).
  411. if (m_oScrollDnPressed==false)
  412. dcMem.DrawEdge(m_rcScrollDn, EDGE_RAISED, BF_RECT);
  413. //  select the pen we wish to use for the arrows.
  414. dcMem.SelectObject(&m_penArrows);
  415. POINT ptCenter;
  416. //  draw the scrollbar up top arrow.
  417. ptCenter = m_rcScrollUpTop.CenterPoint();
  418. ptCenter.x += (m_oScrollUpTopPressed==true) ? (1) : (0);
  419. ptCenter.y += (m_oScrollUpTopPressed==true) ? (1) : (0);
  420. dcMem.MoveTo(ptCenter);
  421. dcMem.LineTo(ptCenter.x, ptCenter.y-1);
  422. dcMem.LineTo(ptCenter.x+2, ptCenter.y+1);
  423. dcMem.LineTo(ptCenter.x-2, ptCenter.y+1);
  424. dcMem.LineTo(ptCenter.x, ptCenter.y-1);
  425. //  draw the scrollbar up bottom arrow.
  426. ptCenter = m_rcScrollUp.CenterPoint();
  427. ptCenter.x += (m_oScrollUpPressed==true) ? (1) : (0);
  428. ptCenter.y += (m_oScrollUpPressed==true) ? (1) : (0);
  429. dcMem.MoveTo(ptCenter);
  430. dcMem.LineTo(ptCenter.x, ptCenter.y-1);
  431. dcMem.LineTo(ptCenter.x+2, ptCenter.y+1);
  432. dcMem.LineTo(ptCenter.x-2, ptCenter.y+1);
  433. dcMem.LineTo(ptCenter.x, ptCenter.y-1);
  434. //  draw the scrollbar dn arrow.
  435. ptCenter = m_rcScrollDn.CenterPoint();
  436. ptCenter.x += (m_oScrollDnPressed==true) ? (1) : (0);
  437. ptCenter.y += (m_oScrollDnPressed==true) ? (1) : (0);
  438. dcMem.MoveTo(ptCenter);
  439. dcMem.LineTo(ptCenter.x, ptCenter.y+1);
  440. dcMem.LineTo(ptCenter.x-2, ptCenter.y-1);
  441. dcMem.LineTo(ptCenter.x+2, ptCenter.y-1);
  442. dcMem.LineTo(ptCenter.x, ptCenter.y+1);
  443. //  paint the background.
  444. dcMem.FillSolidRect(rcDisplay, GetSysColor(COLOR_WINDOW));
  445. //  paint the input line.
  446. dcMem.FillSolidRect(rcInputLine, GetSysColor(COLOR_WINDOW));
  447. //  draw the sunken edge.
  448. dcMem.DrawEdge(rcClient, EDGE_SUNKEN, BF_RECT);
  449. //  set the color of all text.
  450. dcMem.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  451. //  print out the input line on the bottom.
  452. BOOL oResult = dcMem.ExtTextOut(rcInputLine.left, rcInputLine.top,
  453. ETO_CLIPPED, rcInputLine, m_szPrompt + m_szInputLine, NULL);
  454. //  is there any space left?
  455. if (m_nVisibleLines>0)
  456. {
  457. // print out the lines.
  458. CString szText;
  459. int ii = m_nLineIndex;
  460. while (rcText.top>rcDisplay.top && ii>=0)
  461. {
  462. if (ii>=0 && ii<m_vecLines.size())
  463. {
  464. szText = m_vecLines.at(ii);
  465. oResult = dcMem.ExtTextOut(rcText.left, rcText.top,
  466. ETO_CLIPPED, rcText, szText, NULL);
  467. //  move the rect.
  468. rcText.OffsetRect(0, -siText.cy);
  469. }
  470. ii--;
  471. }
  472. //  set the cursor position after the input text.
  473. CPoint ptCaret(siText.cx, rcInputLine.top);
  474. CreateSolidCaret(2, siText.cy);
  475. SetCaretPos(ptCaret);
  476. }
  477. //  select the old font back
  478. dcMem.SelectObject(pfonOld);
  479. //  select the old pen back.
  480. dcMem.SelectObject(ppenOld);
  481. //  select the old brush back.
  482. dcMem.SelectObject(pbrOld);
  483. //  restore their states.
  484. dcMem.RestoreDC(nMemState);
  485. dc.RestoreDC(nDcState);
  486. }
  487. /////////////////////////////////////////////////////////////////////////////
  488. int CCommandLine::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
  489. {
  490. SetFocus();
  491. return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
  492. }
  493. /////////////////////////////////////////////////////////////////////////////
  494. void CCommandLine::OnSetFocus(CWnd* pOldWnd)
  495. {
  496. CWnd::OnSetFocus(pOldWnd);
  497. SetCapture();
  498. ShowCaret();
  499. }
  500. ///////////////////////////////////////////////////////////////////
  501. void CCommandLine::OnKillFocus(CWnd* pNewWnd)
  502. {
  503. CWnd::OnKillFocus(pNewWnd);
  504. HideCaret();
  505. DestroyCaret();
  506. //  let go of the mouse
  507. ReleaseCapture();
  508. }
  509. ///////////////////////////////////////////////////////////////////
  510. UINT CCommandLine::OnGetDlgCode()
  511. {
  512. return CWnd::OnGetDlgCode() |
  513. //DLGC_WANTARROWS | 
  514. //DLGC_WANTCHARS |
  515. //DLGC_WANTMESSAGE |
  516. //DLGC_WANTTAB |
  517. DLGC_WANTALLKEYS;
  518. }
  519. ///////////////////////////////////////////////////////////////////
  520. void CCommandLine::SendChar(UINT uiChar, UINT uiRepCnt, UINT uiFlags)
  521. {
  522. OnChar(uiChar, uiRepCnt, uiFlags);
  523. }
  524. ///////////////////////////////////////////////////////////////////
  525. void CCommandLine::OnChar(UINT uiChar, UINT uiRepCnt, UINT uiFlags)
  526. {
  527. if (m_oIsLocked==false)
  528. {
  529. int nInputLength = m_szInputLine.GetLength();
  530. CString szLeft;
  531. CString szRight;
  532. int nRepeat = 1;
  533. int ii =0;
  534. switch (uiChar)
  535. {
  536. case VK_BACK:       //  backspace.
  537. break;
  538. case VK_RETURN:     //  return key
  539. break;
  540. case VK_TAB:        //  tab key - insert spaces.
  541. //  place the number spaces in the current caret position.
  542. nRepeat = m_nTabSpaces;
  543. uiChar = ' ';
  544. default:
  545. //  place the new char(s) in the current caret position.
  546. for (ii=0; ii<nRepeat; ii++)
  547. {
  548. szLeft = m_szInputLine.Left(m_nCaretPosX);
  549. szRight = m_szInputLine.Right(nInputLength-m_nCaretPosX);
  550. m_szInputLine = szLeft + CString(uiChar) + szRight;
  551. m_nCaretPosX++;
  552. }
  553. break;
  554. }
  555. Invalidate(FALSE);
  556. CWnd::OnChar(uiChar, uiRepCnt, uiFlags);
  557. }
  558. }
  559. /////////////////////////////////////////////////////////////////////////////
  560. void CCommandLine::OnKeyDown(UINT uiChar, UINT uiRepCnt, UINT uiFlags)
  561. {
  562. if (m_oIsLocked==false)
  563. {
  564. int nInputLength = m_szInputLine.GetLength();
  565. CString szLeft;
  566. CString szRight;
  567. int nCommands = m_vecInput.size();
  568. CString szCommand;
  569. int nThumbHeight = 0;
  570. switch (uiChar)
  571. {
  572. case VK_HOME:       // Home
  573. m_nCaretPosX = 0;
  574. break;
  575. case VK_END:        // End
  576. m_nCaretPosX = nInputLength;
  577. break;
  578. case VK_PRIOR:
  579. m_nLineIndex -= m_nVisibleLines;
  580. //  make sure it is safe.
  581. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  582. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  583. nThumbHeight = m_rcThumb.Height();
  584. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  585. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  586. break;
  587. case VK_NEXT:
  588. m_nLineIndex += m_nVisibleLines;
  589. //  make sure it is safe.
  590. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  591. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  592. //m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  593. nThumbHeight = m_rcThumb.Height();
  594. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  595. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  596. break;
  597. case VK_UP:      // command list up.
  598. case VK_F3:
  599. if (nCommands>0)
  600. {
  601. m_szInputLine = m_vecInput.at(m_nInputPos);
  602. m_nInputPos--;
  603. m_nInputPos = (m_nInputPos<0) ? (nCommands-1) : (m_nInputPos);
  604. m_nCaretPosX = m_szInputLine.GetLength();
  605. }
  606. break;
  607. case VK_DOWN:       // command list down.
  608. if (nCommands>=0)
  609. {
  610. m_szInputLine = m_vecInput.at(m_nInputPos);
  611. m_nInputPos++;
  612. m_nInputPos = (m_nInputPos>=nCommands) ? (0) : (m_nInputPos);
  613. m_nCaretPosX = m_szInputLine.GetLength();
  614. }
  615. break;
  616. case VK_LEFT:       // Left arrow
  617. m_nCaretPosX = m_nCaretPosX - uiRepCnt;
  618. m_nCaretPosX = (m_nCaretPosX>0) ? (m_nCaretPosX) : (0);
  619. break;
  620. case VK_RIGHT:      //  command buffer up.
  621. m_nCaretPosX = m_nCaretPosX + uiRepCnt;
  622. m_nCaretPosX = (m_nCaretPosX>nInputLength) ? (nInputLength) : (m_nCaretPosX);
  623. break;
  624. case VK_DELETE:     // Delete
  625. szLeft = m_szInputLine.Left(m_nCaretPosX);
  626. szRight = m_szInputLine.Right(nInputLength-m_nCaretPosX-1);
  627. m_szInputLine = szLeft + szRight;
  628. break;
  629. case VK_BACK:  //  backspace.
  630. szLeft = m_szInputLine.Left(m_nCaretPosX-1);
  631. szRight = m_szInputLine.Right(nInputLength-m_nCaretPosX);
  632. m_szInputLine = szLeft + szRight;
  633. m_nCaretPosX = (m_nCaretPosX>0) ? (m_nCaretPosX-1) : (0);
  634. break;
  635. case VK_RETURN:
  636. //  add the current input line to the command list.
  637. if (m_vecInput.size()>MAX_SCROLLBACK_SIZE-1)
  638. m_vecInput.erase(m_vecInput.begin());
  639. m_vecInput.push_back(m_szInputLine);
  640. //  set the command index to the end.
  641. m_nInputPos = m_vecInput.size()-1;
  642. //  add the entered text to the display buffer.
  643. AddSent(m_szInputLine);
  644. //  save as last command;
  645. m_szLastCommand = m_szInputLine;
  646. //  clear the line.
  647. m_szInputLine.Empty();
  648. m_nCaretPosX = 0;
  649. //  notify the receiver that a command was sent.
  650. EmitCommandSent();
  651. break;
  652. default:
  653. break;
  654. }
  655. Invalidate(FALSE);
  656. CWnd::OnKeyDown(uiChar, uiRepCnt, uiFlags);    
  657.   }
  658. }
  659. /////////////////////////////////////////////////////////////////////////////
  660. void CCommandLine::EmitCommandSent()
  661. {
  662. if (m_pwndReceiver != NULL)
  663. {
  664. NMHDR msgNotif;
  665. msgNotif.code = NM_COMMAND_SENT;
  666. msgNotif.hwndFrom = this->GetSafeHwnd();
  667. msgNotif.idFrom = this->GetDlgCtrlID();
  668. m_pwndReceiver->SendMessage(WM_NOTIFY, 0, (UINT)&msgNotif);
  669. }
  670. }
  671. /////////////////////////////////////////////////////////////////////////////
  672. void CCommandLine::OnLButtonDown(UINT nFlags, CPoint point)
  673. {
  674. CRect rcClient;
  675. GetClientRect(rcClient);
  676. SetFocus();
  677. SetCapture();
  678. // If outside client area, do nothing.
  679. if (rcClient.PtInRect(point)==TRUE)
  680. {
  681. m_ptCaret = point;
  682. m_oCaretPositioned = true;
  683. }
  684. if (m_rcThumb.PtInRect(point)==TRUE)
  685. {
  686. m_nThumbStartPos = point.y;
  687. m_oMouseDownThumb = true;
  688. }
  689. //  are we scrolling using the up top button?
  690. else if (m_rcScrollUpTop.PtInRect(point)==TRUE)
  691. {
  692. //  the button is down.
  693. m_oScrollUpTopPressed = true;
  694. //  decrement the index.
  695. m_nLineIndex--;
  696. //  make sure it is safe.
  697. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  698. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  699. //m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  700. int nThumbHeight = m_rcThumb.Height();
  701. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  702. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  703. //  start the timer to decrement.
  704. SetTimer(ID_EVENT_DECR, 500, NULL);
  705. }
  706. //  are we scrolling using the up button?
  707. else if (m_rcScrollUp.PtInRect(point)==TRUE)
  708. {
  709. //  the button is down.
  710. m_oScrollUpPressed = true;
  711. //  decrement the index.
  712. m_nLineIndex--;
  713. //  make sure it is safe.
  714. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  715. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  716. //m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  717. int nThumbHeight = m_rcThumb.Height();
  718. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  719. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  720. //  start the timer to decrement.
  721. SetTimer(ID_EVENT_DECR, 500, NULL);
  722. }
  723. //  are we scrolling using the down button?
  724. else if (m_rcScrollDn.PtInRect(point)==TRUE)
  725. {
  726. //  the button is down.
  727. m_oScrollDnPressed = true;
  728. //  decrement the index.
  729. m_nLineIndex++;
  730. //  make sure the index is safe.
  731. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  732. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  733. //m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  734. int nThumbHeight = m_rcThumb.Height();
  735. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  736. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  737. //  start the timer to decrement.
  738. SetTimer(ID_EVENT_INCR, 500, NULL);
  739. }
  740. //  are we on the scrollbar?
  741. else if (m_rcScrollBar.PtInRect(point)==TRUE)
  742. {
  743. //  are we above the thumb?
  744. if (point.y < m_rcThumb.top)
  745. {
  746. OnKeyDown(VK_PRIOR, 1, 0);
  747. }
  748. else if (point.y > m_rcThumb.bottom)
  749. {
  750. OnKeyDown(VK_NEXT, 1, 0);
  751. }
  752. }
  753. Invalidate(FALSE);
  754. CWnd::OnLButtonDown(nFlags, point);
  755. }
  756. /////////////////////////////////////////////////////////////////////////////
  757. void CCommandLine::OnLButtonUp(UINT nFlags, CPoint point)
  758. {
  759. //  end the scrolling....
  760. m_oScrollUpTopPressed = false;
  761. m_oScrollUpPressed = false;
  762. m_oScrollDnPressed = false;
  763. //  the thumb is not being moved....
  764. m_oMouseDownThumb = false;
  765. KillTimer(ID_EVENT_INCR);
  766. KillTimer(ID_EVENT_DECR);
  767. //  let go of the mouse
  768. ReleaseCapture();
  769. Invalidate(FALSE);
  770. CWnd::OnLButtonDown(nFlags, point);
  771. }
  772. /////////////////////////////////////////////////////////////////////////////
  773. void CCommandLine::OnTimer(UINT nIDEvent)
  774. {
  775. //  change the timer to a shorter interval.
  776. SetTimer(nIDEvent, 100, NULL);
  777. switch (nIDEvent)
  778. {
  779.     case ID_EVENT_INCR: m_nLineIndex++; break;
  780.     case ID_EVENT_DECR: m_nLineIndex--; break;
  781. }
  782. //  make sure it is safe.
  783. m_nLineIndex = min((int)(m_vecLines.size())-1, m_nLineIndex);
  784. m_nLineIndex = max(m_nVisibleLines-1, m_nLineIndex);
  785. int nThumbHeight = m_rcThumb.Height();
  786. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  787. m_rcThumb.top = m_rcThumb.bottom - nThumbHeight;
  788. TRACE ("Timer fired. Display pos is: %d.n", m_nLineIndex);
  789. Invalidate(FALSE);
  790. }
  791. /////////////////////////////////////////////////////////////////////////////
  792. void CCommandLine::OnSize(UINT nType, int cx, int cy)
  793. {
  794. CWnd::OnSize(nType, cx, cy);
  795. m_rcThumb.bottom = ScreenPosFromLineIndex(m_nLineIndex);
  796. Invalidate(FALSE);
  797. }
  798. /////////////////////////////////////////////////////////////////////////////
  799. void CCommandLine::OnMouseMove(UINT nFlags, CPoint point)
  800. {
  801. if (m_oMouseDownThumb==true)
  802. {
  803. //  get the new screen position.
  804. int nScreenDy = point.y - m_nThumbStartPos;
  805. if (nScreenDy!=0)
  806. {
  807. //  calculate a new position
  808. int nNewBottom = m_rcThumb.bottom + nScreenDy;
  809. //  make sure the new pos is within bounds.
  810. nNewBottom = min(m_rcScrollTrack.bottom, nNewBottom);
  811. nNewBottom = max(m_rcScrollTrack.top+m_rcThumb.Height()-m_nMinThumbY, nNewBottom);
  812. //  offset the thumb.
  813. m_rcThumb.top = nNewBottom - m_rcThumb.Height();
  814. m_rcThumb.bottom = nNewBottom;
  815. //  reset the thumb start pos.
  816. m_nThumbStartPos = point.y;
  817. //  calculate the line index.
  818. m_nLineIndex = LineIndexFromScreenPos(m_rcThumb.bottom);
  819. //  make sure we redraw the control.
  820. Invalidate(FALSE);
  821. }
  822. }
  823. CWnd::OnMouseMove(nFlags, point);
  824. }
  825. /////////////////////////////////////////////////////////////////////////////
  826. int CCommandLine::ScreenPosFromLineIndex(int nLineIndex)
  827. {
  828. //  what is the ratio of the position to the number of lines?
  829. double xPosRatio = (double)(nLineIndex)/(double)(m_vecLines.size());
  830. //  what is the ratio of the minimum to the number of lines?
  831. double xMinRatio = (double)(m_nVisibleLines)/(double)(m_vecLines.size());
  832. //  calculate the number of visible lines in pixels.
  833. int iTopPos = m_rcScrollTrack.top + //m_nMinThumbY +
  834. (int)(xMinRatio * (double)(m_rcScrollTrack.Height()));
  835. //  this is the bottom of the thumb.
  836. int iScreenPos =  m_rcScrollTrack.top + //m_nMinThumbY +
  837. (int)(xPosRatio * (double)(m_rcScrollTrack.Height()));
  838. //  make sure the new pos is within bounds.
  839. iScreenPos = min(m_rcScrollTrack.bottom, iScreenPos);
  840. iScreenPos = max(iTopPos, iScreenPos);
  841. TRACE("Calculated thumb bottom: %dn", iScreenPos);
  842. return iScreenPos;
  843. }
  844. /////////////////////////////////////////////////////////////////////////////
  845. int CCommandLine::LineIndexFromScreenPos(int nScreenPos)
  846. {
  847. //  what fraction of the total scroll distance was moved?
  848. double xRatio = (double)(nScreenPos - m_rcScrollTrack.top) / // - m_nMinThumbY) /
  849. (double)(m_rcScrollTrack.Height());
  850. //  calculate the new index
  851. int iPos = (int)(xRatio * (double)(m_vecLines.size()));
  852. //  make sure the new pos is within bounds.
  853. iPos = min(m_vecLines.size()-1, iPos);
  854. iPos = max(m_nVisibleLines-1, iPos);
  855. TRACE("Calculated display pos: %dn", iPos);
  856. return iPos;
  857. }
  858. /////////////////////////////////////////////////////////////////////////////