为控制台创建带有组合框的输入






3.89/5 (4投票s)
使用组合框作为控制台输入字段的简单方法
引言
我正在制作一个应用程序,它有一个类似于 AutoCAD 中的控制台。我希望命令在一个 ComboBox
中输入,该控件在下拉列表中保持历史记录。通过按下 Enter 键并在其中输入或从下拉列表中选择一个命令来执行命令。用户还应该能够使用箭头键来滚动浏览以前的命令。这类似于视频游戏(如半条命 2)中的控制台。
问题
使用常规的 CComboBox
,在用户按下 Enter 键时执行操作比较困难。当按下 Enter 键时,我希望该命令被放入 combobox
的历史记录(下拉列表)中,并且该命令被解析和执行。此外,我注意到当用户按下箭头键来滚动浏览以前的命令时,他们无法返回到他们正在处理的原始命令。最重要的是,当按下向上箭头键时,它会选择下拉列表中的上一个命令,但当您再次按下它时,它什么也不做。
解决方案
首先,我从 CComboBox
派生了一个名为 CConsoleCombo
的类。我添加了成员变量 CString m_current
和 int m_nPos
。 m_current
保存用户正在处理的命令,以便他们可以随时返回到该命令,即使他们滚动浏览了以前的命令。 m_nPos
是用户滚动到的历史记录中的当前位置。我必须手动跟踪此位置。我做的下一件事是重写 CComboBox
的 PreTranslateMessage()
函数。重写的函数如下所示
BOOL CConsoleCombo::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here
// and/or call the base class
if (pMsg->message == WM_KEYDOWN)
{
CString str;
int nVirtKey = (int) pMsg->wParam;
switch (nVirtKey)
{
//checks if up arrow key is pressed
case VK_UP:
//if this is first position
// save current text
if (m_nPos == -1)
{
GetWindowText(str);
m_current = str;
}
//makes sure an invalid position
// isn't going to be set
if (m_nPos + 1 < GetCount())
{
//increase position
m_nPos++;
//get text at current position
// display it highlighted
GetLBText(m_nPos, str);
SetWindowText(str);
SetEditSel(0, str.GetLength());
}
return TRUE;
case VK_DOWN:
//if going back to bottom restore
// previously entered text
if (m_nPos - 1 == -1)
{
SetWindowText(m_current);
SetEditSel(m_current.GetLength(),
m_current.GetLength());
m_nPos = -1;
}
if (m_nPos - 1 >= 0)
{
//decrease position
m_nPos--;
//get text at current position
// display it highlighted
GetLBText(m_nPos, str);
SetWindowText(str);
SetEditSel(0, str.GetLength());
}
return TRUE;
//if enter key is pressed do following
case VK_RETURN:
GetWindowText(str);
//make sure there is something input
if (str != "")
{
//add string to the bottom of the list
InsertString(0, str);
m_nPos = -1;
SetWindowText("");
//function that must be customized
// for each program
ParseCommand(str);
}
break;
}
}
return CComboBox::PreTranslateMessage(pMsg);
}
该函数检查 Windows 消息是否为 WM_KEYDOWN
。然后,如果是并且按下向下键,则向下移动位置 (m_nPos
)。对于向上键,它会向上移动位置。当第一次按下向上键时,会存储当前命令 (m_current
)。当按下向下键并且回到起始位置时,会恢复当前命令。滚动浏览以前的命令会将它们显示为 ComboBox
文本字段中选定的命令。如果 WM_KEYDOWN
的 wParam
是 Enter 键并且文本字段中有一个命令,则该命令将被添加到历史记录中,清除文本字段,并执行 ParseCommand()
函数。这是一个 virtual
成员函数,将在本文的使用代码部分中进行解释。
Using the Code
要有效地使用这个类,最好从中派生一个类。在演示中,这个类是 CInput
。然后,您必须重写 ParseCommand(CString command)
函数。在此函数中,添加要执行的自定义代码。例如,解析命令字符串并执行其指令。为了简单起见,在演示中,此函数所做的只是将自定义用户消息 (WM_CCOMMAND
) 发送到对话框,并将命令放在其 wParam
中。然后,对话框获取此命令并将其添加到只读编辑框中(此编辑框也是一个自定义控件,请查看我的文章“更改只读编辑控件的背景颜色”)。这是所有控制台都执行的任务。这也是用户消息的一个简洁而简单的示例。
注意:附加到本文的演示程序有一个对话框,其中包含一个编辑框和两个 ComboBox
。一个是正常的,而另一个是 CConsoleCombo
。我同时放了这两个来显示它们的比较。它们都将 string
添加到编辑框中,但对于正常的 combobox
,您必须点击 添加 按钮。
历史
- 2005 年 1 月 25 日 - 初始发布