I am making an application that has a console similar to the one found in AutoCAD. I want the commands to be input in a ComboBox that keeps a history in the dropdown. Commands are implemented by pressing the Enter key with a command typed in or selected from the dropdown. The user should also be able to use the arrow keys to scroll through previous commands. This is similar to consoles in video games such as Half-Life 2.
With the regular
CComboBox it is difficult to do an action when the user hits the Enter key. When the Enter key is pressed, I want the command to be put into the combobox's history (the dropdown) and the command to be parsed and implemented. Also, I noticed that when a user presses the arrow keys to scroll through previous commands they cannot go back to the original command they were working on. On top of that when the up arrow key is pressed it selects the previous command in the dropdown but when you press it again it does nothing.
First of all I derived a class from
CConsoleCombo. I added member variables
CString m_current and
m_current holds the command the user is working on so if they scroll through their previous commands they can always come back to it.
m_nPos is the current position in the history the user has scrolled to. I have to keep track of this position manually. The next thing I did was to override
PreTranslateMessage() function. The overridden function looks like this:
BOOL CConsoleCombo::PreTranslateMessage(MSG* pMsg)
if (pMsg->message == WM_KEYDOWN)
int nVirtKey = (int) pMsg->wParam;
if (m_nPos == -1)
m_current = str;
if (m_nPos + 1 < GetCount())
if (m_nPos - 1 == -1)
m_nPos = -1;
if (m_nPos - 1 >= 0)
if (str != "")
m_nPos = -1;
The function checks if the Windows message is
WM_KEYDOWN. Then if it is and the down key is pressed, it moves the position down (
m_nPos). For the up key it moves the position up. When the up key is first pressed the current command is stored (
m_current). When the down key is pressed and it is back to the starting position the current command is restored. Scrolling through previous commands displays them selected in the ComboBox's text field. If the
wParam is the Enter key and there is a command in the text field then that command is added to the history, the text field is cleared, and the
ParseCommand() function is performed. This is a
virtual member function which is explained in the Using the Code section of this article.
Using the code
To use this class effectively it is best to derive a class from it. In the demo this class is
CInput. You must then override the
ParseCommand(CString command) function. In this function you add the custom code you want to perform. For instance, parsing the command string and carrying out its instructions. For simplicities sake, in the demo all this function does is to send a custom user message (
WM_CCOMMAND) to the dialog with the command in its
wParam. The dialog then takes this command and adds it to a read only edit box (this edit box is a custom control as well, check out my article 'Changing the background color of a read-only edit control'). This is a task that all consoles perform. This is also a neat and simple example of user messages.
Note: The demo attached to this article has a dialog with an edit box and two ComboBoxes. One is normal while the other one is a
CConsoleCombo. I have put both to show a comparison of the two. They both add strings to the edit box but for the normal combobox you must hit the Add button.