Because of the needs of the subject needs to do MFC serial Port program, read the interface style of Baidu download serial assistant, found this design is very good
The baud rate combo box gives only 5 selectable values, and the 6th option is custom, which is entered manually.
In fact, the BaudRate optional value of the DCB structure is too much, to make the drop-down box will be very long, this approach is to choose the most common options, do not need to manually enter the user, and do not need to be in a long list to choose.
As you can see from the Properties box of VS, there are 3 styles of combo box controls, which is the ability to switch from drop list to dropdown when you click the Custom option.
From MSDN, you can see that the corresponding macros are cbs_dropdownlist and Cbs_dropdown, respectively.
Reference: Https://msdn.microsoft.com/en-us/library/12h9x0ch.aspx
So I originally wanted to use the Cwnd::modify () method to modify the style, but failed, the reason for the search, the drop-down style can only be determined at the time of creation, cannot be changed after creation.
It is therefore reasonable to manually create an identical control and then use the CWnd::ShowWindow () method to automatically switch.
-----------------------------------------------------------------------------------Split Line----------------------------------- -----------------------------------------------
The following is a detailed implementation method starting from 0, a new MFC-based dialog box Program (Set dialog Class Ccombotestdlg), manually drag a ComboBox control up. Set type and ID
Add an associated variable of type CComboBox to the control in the Class Wizard, or add it manually as follows:
1. In ComboTestDlg.h, define the public variable in the Cxxxdlg class
CComboBox M_cmbold;
2. In ComboTestDlg.cpp, Cxxxdlg: Add a row of associated statements:D the Odataexchange () method
DDX_Control (PDX, Idc_combo_old, m_cmbold);
Now define the public variable m_cmbnew in the Ccombotestdlg class, but do not modify the DoDataExchange () method, as you will manually create the drop-down box
CComboBox m_cmbnew;
Modify the Ccombotestdlg::oninitdialog () method to add the following code
//gets the location of the original drop-down boxCRect rect; M_cmbold.getwindowrect (&rect); This->screentoclient (&rect); //gets the font of the original drop-down boxcfont* Pfont =M_cmbold.getfont (); //Gets the style of the original drop- down box (change the Drop list to dropdown)DWORD dwstyle =M_cmbold.getstyle (); Dwstyle^=cbs_dropdownlist; Dwstyle|=Cbs_dropdown; //Create a new drop-down box that is identicalM_cmbnew.create (Dwstyle, Rect, This, idc_combo_new); //set the same fontM_cmbnew.setfont (Pfont); //Hide New drop-down box by defaultM_cmbnew.showwindow (Sw_hide);
There are two points to note in the above code (that is, the pit I stepped on ...). )
1. Coordinate conversion screentoclient, because GetWindowRect gets the position relative to the entire parent control (including the title bar), and create requires a position relative to the client area (excluding the title bar), so it needs to be converted;
2. GetFont and SetFont set the font, without this step, the font created by the Create drop-down box may not be the same as the automatically created drop-down box font.
PS: Macro idc_combo_new need to be added manually in resource.h, be careful not to be the same as other macros to avoid conflicts.
That's all you need to do to switch, assuming my drop-down box contains 4 items: CPP, Java, Python, custom, click Custom to switch to manual input mode.
Add a global variable in ComboTestDlg.cpp (the syntax for list initialization is c++11) so that it can be accessed directly by subscript
#include <vector>std::vector<CString> g_strtext = {_t ("cpp"), _t ( " Java "), _t ("python"), _t ("custom")};
Continue adding initialization code after the code that you just added in Ccombotestdlg::oninitdialog ()
for 0; I < g_strtext.size (); i++) { // c++11 can be used in <type_traits> std::extent<decltype (text);:: Value gets the text array size m_cmbold.addstring (G_strtext[i]); M_cmbnew.addstring (G_strtext[i]); } M_cmbold.setcursel (0// Select first item by default ("CPP")
Then add response events to each of the 2 controls, and for the default control M_cmbold, you can add a method with the Class wizard
Actually did these things:
1. In ComboTestDlg.h, add the declaration of the member function in the Ccombotestdlg class
void Oncbnselchangecomboold ();
2. In ComboTestDlg.cpp, add between message map macro Begin_message_map (Ccombotestdlg, CDialog) and End_message_map ()
On_cbn_selchange (Idc_combo_old, &ccombotestdlg::oncbnselchangecomboold)
3. In CComboTestDlg.cpp, add a specific definition of the member function
void Ccombotestdlg::oncbnselchangecomboold () { // TODO: Add control notification handler code here }
After knowing these points, divert, add the corresponding code in the same position as the above 3 steps, and if you select an existing item, the original drop-down box will be displayed.
void Oncbnselchangecombonew ();
On_cbn_selchange (Idc_combo_new, &ccombotestdlg::oncbnselchangecombonew)
void ccombotestdlg::oncbnselchangecombonew () {}
When you enter custom data, you need to respond to the carriage return message, and Use the Class Wizard (for example, click Add Function) to give Ccombotestdlg overloaded virtual function PreTranslateMessage ()
This step actually does these things:
1. In ComboTestDlg.h, add a declaration of a virtual function in the Ccombotestdlg class
Virtual BOOL PreTranslateMessage (msg* pMsg);
2. In ComboTestDlg.cpp, add the definition of the virtual function
BOOL Ccombotestdlg::P retranslatemessage (msg* pMsg) { // TODO: Add private code here and/or call base class return CDialog::P retranslatemessage (PMSG);}
Now that the framework has been set up, just add the specific switching logic in the added functions
void Ccombotestdlg::oncbnselchangecomboold () { CString text; M_cmbold.getwindowtext (text); if (Text = = _t ("custom")) { // switch to Manual edit drop-down box M_cmbold.showwindow (sw_hide); M_cmbnew.showwindow (sw_show); M_cmbnew.setfocus (); } Else { MessageBox (text); }}
voidccombotestdlg::oncbnselchangecombonew () {CString text; M_cmbnew.getwindowtext (text); if(Text = = _t ("Custom")) { //re-enterM_cmbnew.setwindowtext (_t ("")); } Else { //switch to the original drop-down boxM_cmbnew.showwindow (sw_hide); M_cmbold.showwindow (Sw_show); M_cmbold.setcursel (M_cmbold.findstring (0, text)); MessageBox (text); }}
BOOL Ccombotestdlg::P retranslatemessage (msg*PMSG) { //TODO: Add private code here and/or call base class if(Pmsg->message = =wm_keydown) { if(Pmsg->wparam = = Vk_return)//Enter { if(M_cmbnew.getfocus ()) {//adding control information to the listCString text; M_cmbnew.getwindowtext (text); intNselect = m_cmbnew.findstring (0, text); if(Nselect = =-1) { //Add control information to the drop-down box if it does not exist in the list itemg_strtext.push_back (text); M_cmbold.addstring (text); M_cmbnew.addstring (text); } Else { //Displays the original drop-down box and navigates to the list item if it already existsM_cmbnew.showwindow (sw_hide); M_cmbold.showwindow (Sw_show); M_cmbold.setcursel (Nselect); } MessageBox (text); } } } returnCDialog::P retranslatemessage (PMSG);}
This completes the function, can be based on the actual needs of some code encapsulation, after all, MFC API encapsulation is very shallow.
Features are described below
1. The initial dialog box displays a combo box of the drop list type.
2. When a list item other than custom is selected, a pop-up window displays the text of the list item.
3. When custom is selected, it enters edit mode and the drop-down box becomes the dropdown type.
4. Press ENTER when finished editing, and if the text is already in the list item, a pop-up window displays the text and the combo box changes back to the drop list type, otherwise the input text is added to the end of the list item.
5. When the combo box is a dropdown type, if a list item other than custom is selected, the combo box is then drop list type.
MFC combo Box (ComboBox) Control toggle drop-down style