Click here to Skip to main content
15,881,248 members
Articles / Desktop Programming / MFC

Creating an Input for a Console using a Combo Box

Rate me:
Please Sign up or sign in to vote.
3.89/5 (4 votes)
25 Jan 2005CPOL3 min read 48.5K   1.1K   29   1
A simple way to use a combo box for an input field for a console

Introduction

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.

The Problem

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.

The Solution

First of all, I derived a class from CComboBox called CConsoleCombo. I added member variables, CString m_current and int m_nPos. 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 CComboBox's PreTranslateMessage() function. The overridden function looks like this:

C++
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);
}

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 WM_KEYDOWN's 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 the sake of simplicity, 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.

History

  • 25th January, 2005 - Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
I am 20 years old and I live in Kitchener, Ontario. I have been programming since I was 10 years old. I started with QBasic, then up to Visual Basic, and finally C++. I am an avid programmer of Windows as well. Besides that, I am also interested in automation, PLCs, and electronics. I will be attending Conestoga College in Sept. 2005 for their Mechanical Engineering: Automation and Robotics program. I hope to someday have a job where I can incorporate my skills with programming Windows with the skills I learn in that program.

Comments and Discussions

 
GeneralNot bad !! Pin
WREY25-Jan-05 13:51
WREY25-Jan-05 13:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.