MFC中制作一个似命令行的输入框

时间:2021-06-15 17:43:39

在做一个MFC软件的时候有一个这样的需求,就是要有类似与AutoCad的命令输入框,如下图所示:

 

MFC中制作一个似命令行的输入框

本着不重写已有功能的原则,在MFC中发掘了一圈,没发现有可用的现成控件,上网搜了一下,发现有人做过,但竟然还收费出售,so faint,只能自己动手做一个。

其实思路还是蛮简单的,就是放个Edit控件处理它的键盘输入事件,防止删除之前的记录和提示信息,还要处理结束命令,比如回车、空格之类的。主要有以下几个步骤:

1. 将输入框内的字符串分段,比如分成三段log, tip和command,前两段都不能被修改,command的内容为可修改的。在结束了command输入后,要同步各字符串,示例代码如下:

void CMainFrame::InitCommand(CString tip)
{
 // 记录老字符串,类似于UpdateData(true)

 this->GetText();

 // 设置新的log
 if(this->m_log != "")
  this->m_log += "\r\n";
 this->m_log += tip;

 // 更新字符串,类似与UpdataData(false)
 this->SetText();

 // 将光标置于字符串的尾部(否则光标会在一开始的位置)

 ((CEdit *)m_commandDialogBar.GetDlgItem(IDC_COMMAND))->SetSel(this->m_log.GetLength(),
  this->m_log.GetLength());
}

2. 重载PreTranslateMessage事件,处理键盘信息,示例代码如下:

 BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
 if(pMsg->message == WM_KEYDOWN) // 处理键盘按下事件
 {
  // 判断是否是在脚本输入框上输入的

  if(GetFocus() == m_commandDialogBar.GetDlgItem(IDC_COMMAND))
  {
   // 如果选择的是非正在输入的文字,抛弃这个事件

   DWORD selectedRegion = ((CEdit *)m_commandDialogBar.GetDlgItem(IDC_COMMAND))->GetSel();
   int selectedStart = LOWORD(selectedRegion);
   int selectedEnd   = HIWORD(selectedRegion);

   if(selectedStart != selectedEnd && selectedStart < m_log.GetLength())
    return true;

   if(pMsg->wParam == 8 && selectedStart <= m_log.GetLength()) // 阻止删除之前的文字
    return true;

   if(pMsg->wParam == 13 || pMsg->wParam == 32) // 当输入空格或回车是发送消息
    this->SendCommand();
  }
 }

 return CMDIFrameWnd::PreTranslateMessage(pMsg);
}

其中SendCommand的内容可自定义,处理完成后不要忘记执行1的操作,同步一下字符串就OK。实现效果如下:

MFC中制作一个似命令行的输入框

当然,这是一个最简单的实现,还有很多问题没有处理,比如自定义菜单,屏蔽系统菜单等;还有很多工作可以做,比如封装成一个自定义控件,做更好的显示效果等等。但基本的思路还是一样的,恩,如果谁有更好的实现方案,也欢迎留言,谢谢先:)