Figure 1: The first editable item is selected. The edit field of the combo box can be edited.
Figure 2: A read-only item is selected. The edit field of the combo box is now read-only.
I was working on a trading application where it was possible to enter orders to buy shares in various stocks. When clicking on a stock, the window for entering orders was opened. There the trader, among other parameters, could enter a quantity. My client requested, it should be possible to have a default value there. Default value could either be whatever is available in the market, last order's quantity or some fixed number. Setting this default value could have been done by using several standard controls together, which would be used to enter a default quantity. For example, a couple of radio buttons to decide which kind of default quantity, and if fixed number was selected, another edit field could be enabled where an integer could be entered. Since screen space is valuable, several coupled controls are more complicated for users and developing custom controls are really fun, we decided to go for a custom control.
The read only combo box has one editable (non read-only item), the first item. When this item is selected, the edit field of the combo box becomes active and can be updated by the user. Whenever the text in the edit field is changed, the first item is changed as well. The other items are read only. When selected, the edit field of the combo box will become read only. The user can now either select one of the predefined values or select the editable item and enter any value.
Add a normal combo box resource to your window. Set the following properties on the resource:
Owner Draw: Fixed
Has Strings: checked
Next, add a control variable for the combo box resource using class wizard. In the h file, change the data type from
CReadOnlyComboBox. Then, after the control been created, call the
AddString-method which will add items, making the first item editable. The combo box is initialized in the method
CComboTestDlg::OnInitDialog() in this example. We use a data member called
m_combo belonging to
CComboTestDlg for the combo box.
CReadOnlyComboBox inherits publicly from
CComboBox, so all functionality of a normal combo box is available. Items should however be added with
The following three methods in
CReadOnlyComboBox do all the work. Below is a short explanation of each method and usage.
OnSelchange is called when the user changes the current selection in the list box of the combo box. Depending on if the user selected a read-only item or not, the edit field of the combo box is set to be read only or set to be active.
OnEditupdate is called after the user has taken an action that may have altered the text in the edit control portion of a combo box. This means that item zero was previously selected since this is the only way to enable the edit field, otherwise the edit field is read-only. We update the first item in the list box of the combo box to reflect the change.
void CReadOnlyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
Called by the framework when a visual aspect of an owner-draw combo box changes. This is called once per item that needs to be drawn. This function will draw the text of the item as well as change the color of the item's background. Different colors are used for the read only item and the editable item. Also, if the user selects an item, we need to highlight the item to display the selection.