使用CComboBox控件

介绍 本教程将展示如

  

何在一个非常基本的基于对话框的应用程序中使用CComboBox类。它将包括下列各点: CComboBox添加到你的对话框下拉列表的高度变化的行为的差异3风格的CComboBox插入/将项目添加到CComboBox改变的宽度下拉列表中选择使用项目数据确定哪些项目选择物品处理CComboBox消息增强 ComboBox是由编辑控件和列表框控件组成的复合控件。本教程假设您已经熟悉使用vc++ 6类向导创建一个基于对话框的应用程序。如果您需要关于这个主题的信息,请参阅文章“基于对话框的应用程序初学者指南-第1部分”。 添加一个CComboBox到你的对话框 当您的基于对话框的应用程序生成后,转到工作区窗口中的资源。在对话框部分中选择对话框IDD_COMBOBOXTUTORIAL_DIALOG。要插入ComboBox控件,请从控件调色板中选择它。十字形光标表示组合框的编辑控制部分的中心位置。 更改下拉列表的高度 右键点击组合框的“下拉菜单”按钮。这将指示组合框的当前大小,包括扩展的列表框。然后像其他控件一样通过拖出矩形来调整它的大小。 三种风格CComboBox的不同行为 组合框有三种不同的样式和不同的选择属性。要更改组合框的样式,请右键单击它并选择Properties。然后选择Styles选项卡。 简单类型有一个永久打开的列表框,您可以在编辑控件中键入。下拉式有一个“关闭”的列表框,可以通过点击“下拉”按钮打开。编辑控件将接受输入。下拉列表类型有一个“关闭”的列表框,可以通过点击“下拉”按钮打开。编辑控件将不接受任何输入。 插入/添加项目到CComboBox 可以在编码时向组合框添加项。这对于那些永远不需要更改的数据来说非常方便。为此,选择Data选项卡并添加项,每行一个。使用Ctrl+Return转到下一行。 然而,在运行时将项目加载到组合框中更常见也更灵活。这样,就可以从资源中加载它们并进行本地化,或者根据其他用户选择进行更改。 在演示中,您将看到从string resources加载下拉组合,下拉列表最初使用Data选项卡中设置的列表,简单的组合框被保留为空。 为了确保简单的combobox是空的,我们只需调用CComboBox类ResetContent()函数。 隐藏,复制Code

m_Simple.ResetContent();

下拉列表是通过下面的for循环从字符串资源加载的,只需调用CComboBox类的AddString()成员函数。 隐藏,复制Code

CString tmp;
for( int i=0; i<6; i++ )
{
    tmp.LoadString(IDS_STRING102 + i);
    m_DropDown.AddString(tmp);
}

如果您随后点击插入长文本项目复选框,字符串“”将插入到下拉列表组合框的第三个选项之后。 首先,需要找到字符串的索引,我们只需调用CComboBox类的InsertString()成员函数。 隐藏,复制Code

int idx = m_DropList.FindString(0, "3rd Option");
CString str;
str.LoadString(IDS_STRING108);
// we add one because we want it after
m_DropList.InsertString(idx+1, str);

使用InsertString()时要注意的主要事情是,索引表示将插入它之前的位置。如果索引为-1,则插入将位于列表的末尾。(即。,与AddString()相同) 更改下拉列表的宽度 最好设计对话框,使组合框足够大,以充分显示最长的选项。然而,这并不总是可能的。在这种情况下,扩大下拉列表很方便,这样在选择时可以看到整个字符串。 为此,CComboBox类有一个函数SetDroppedWidth()。这个函数的输入参数是下拉列表的外部宽度,以像素为单位。首先,您需要组合框的关联设备。然后检查所有字符串的长度(以像素为单位),找出最长的字符串。 注意:我们还必须允许滚动条和窗口边框的宽度。 隐藏,复制Code

CDC* pDC = m_DropList.GetDC();
CSize sz;
int newWidth = 0;
int nWidth = m_DropList.GetDroppedWidth();
for( int i=0; i < m_DropList.GetCount();  i++ )
{
   m_DropList.GetLBText( i, str );
   sz = pDC->GetTextExtent(str);

   if(sz.cx > newWidth)
      newWidth = sz.cx;
}
// Add allowance for vertical scroll bar and edges
newWidth += (GetSystemMetrics(SM_CXVSCROLL) + 2*GetSystemMetrics(SM_CXEDGE));
nWidth = max(nWidth, newWidth);
m_DropList.SetDroppedWidth( nWidth );
m_DropList.ReleaseDC(pDC);

检查字符串是否比现有的下拉列表长,不要忘记调用ReleaseDC()。 调用m_DropList。GetWindowRect(及rc);将返回编辑框的宽度,因此可用于将下拉列表返回到其原始大小。 当使用一个简单,最好设置自动水平滚动样式。 确定选择哪个项目 有两种方法可以确定选择哪一项。您可以使用类向导将控件和数据变量与控件关联起来。 另外,用类向导为组合框添加一个OnSelChanged函数。 下拉列表组合框可以有一个整数数据变量,它返回所选项的索引,代码可以像下面这样简单。UpdateData ();转移指标to变量。 隐藏,复制Code

void CComboBoxTutorialDlg::OnDropListSelchange()
{
    UpdateData();

    if( m_nDropListIndex < 0 ) return;

    CString str;
    m_DropList.GetLBText( m_nDropListIndex, str );
    CString Out;
    Out.Format( "Drop List Selection => index %d\n%s", m_nDropListIndex, str );
    AfxMessageBox( Out );
}

下拉框和简单的组合框可以有一个CString数据变量,它返回选定的字符串。要获取字符串,您可以再次调用UpdateData();,或者调用GetCurSel()。 隐藏,复制Code

void CComboBoxTutorialDlg::OnSimpleSelchange()
{
    CString str;
    int idx = m_Simple.GetCurSel();
    if( idx < 0 ) return;

    m_Simple.GetLBText( idx, str );
    CString Out;
    Out.Format( "Drop List Selection => index %d\n%s", idx, str );
    AfxMessageBox( Out );
}

您会注意到,类向导只允许您将一个整型变量附加到下拉列表组合框,将一个CString变量附加到下拉列表和简单组合框。 您可以添加数据交换条目来手动附加备用变量类型,但是条目和变量声明必须放在AFX_DATA_MAP和AFX_DATA标签之外,这样类向导就不会删除它们。 隐藏,复制Code

.
.
	int		m_nDropListIndex;
	//}}AFX_DATA
	CString	m_strDropList;
.
.

隐藏,复制Code

.
.
	DDX_CBIndex(pDX, IDC_COMBO2, m_nDropListIndex);
	//}}AFX_DATA_MAP
	DDX_CBString(pDX, IDC_COMBO2, m_strDropList);
}

在调用UpdateData()之后,检查CBN_SELCHANGE处理程序中的字符串。 选择项目 选择一个项目可以通过设置如下索引来完成。如果使用整型变量,则调用UpdateData(FALSE); 可以使用SetCurSel(索引) 或者使用SelectString(after, str),其中after是开始搜索的索引。从演示中可以看到,项目以不同的顺序添加,数据仍然匹配。 隐藏,复制Code

m_nDropListIndex = 2;
UpdateData(FALSE);
m_Simple.SetCurSel(2);

CString str;
str.LoadString(IDS_STRING104);
m_DropDown.SelectString(0,str);

如果您知道索引永远不能设置为大于列表中的项数的值,那么代码可以保持原样。但是,如果存在这样的风险,那么明智的做法是检查并将索引设置为默认项,或者向用户发送一个警告错误的消息框。 隐藏,复制Code

if( m_Simple.GetCount() <= 2 )
{
    m_Simple.SetCurSel(0);
    AfxMessageBox( "Index is out of range, selecting default" );
}

使用项目的数据 组合框返回所选项或字符串的基于0的索引,如上所示。通常,程序实际上使用的不是字符串或索引的值,而且,无论列表中的项是否被排序,您都需要正确地获得这个值。如果应用程序要支持多种语言,这就更重要了,因为排序可能是不同的。 为了帮助实现这一点,列表中的每一项都可以有一个与之关联的DWORD,并且无论排序如何,这个DWORD都被附加到字符串中。 使用SetItemData(idx, dwData)和GetItemData(idx)。在设置数据时,使用AddString()或InsertString()函数返回的索引来确保正确设置。 隐藏,复制Code

int idx = m_DropDown.AddString( str.Left(pos));
m_DropDown.SetItemData( idx, dw );

要检索数据,获取项索引并调用GetItemData(idx)。 隐藏,复制Code

.
		int idx = m_DropDown.GetCurSel();
.
.
		DWORD dw = m_DropDown.GetItemData( idx );
.

处理CComboBox消息 可用于组合框的通知消息如下: 当组合框不能分配足够的内存时发送CBN_ERRSPACE通知消息。当用户在组合框的列表框中更改当前选择时发送CBN_SELCHANGE通知消息。当用户双击组合框列表框中的字符串时,发送CBN_DBLCLK通知消息。当组合框接收到键盘焦点时发送CBN_SETFOCUS通知消息。当组合框失去键盘焦点时发送CBN_KILLFOCUS通知消息。CBN_EDITCHANGE通知消息是在用户采取可能改变组合框编辑控制部分中的文本的操作之后发送的。当组合框的编辑控制部分即将显示修改后的文本时,发送CBN_EDITUPDATE通知消息。当组合框的列表框即将可见时发送CBN_DROPDOWN通知消息。当组合框的列表框被关闭时发送CBN_CLOSEUP通知消息。CBN_SELENDOK通知消息发送时,用户选择一个列表项目,或选择一个项目,然后关闭列表。CBN_SELENDCANCEL通知消息发送时,用户选择一个项目,但随后选择另一个控件或关闭对话框。 演示程序处理CBN_SELCHANGE和CBN_EDITUPDATE消息。如果您想防止键入某些字符,那么CBN_EDITUPDATE非常方便。 下面的代码仅用于演示,这种验证最好由控件本身执行。这将涉及到子类化控件和重写某些函数。这个更复杂的主题在本站点的其他地方讨论。 隐藏,复制Code

void CComboBoxTutorialDlg::OnSimpleEditupdate()
{
    UpdateData();
    if(!m_strSimple.GetLength()) return;
    DWORD dwSel =  m_Simple.GetEditSel();
    // Only do this if no characters are selected
    if( LOWORD( dwSel ) != LOWORD( dwSel ) ) return;

    if( ispunct( m_strSimple[LOWORD( dwSel )-1] ))
    {
        MessageBeep(0);
        m_strSimple = m_strSimple.Left(LOWORD( dwSel )-1) + m_strSimple.Mid(LOWORD( dwSel ));
        UpdateData(FALSE);
        // put caret back where it was
        m_Simple.SetEditSel( LOWORD( dwSel ), LOWORD( dwSel ) );
//      AfxMessageBox( "Punctuation Characters are not permitted." );
    }
}

一两句警告的话。验证也可以在CBN_KILLFOCUS处理程序中完成。如果这样做,请注意将不正确的数据更改回原为弹出的消息框,这些消息框也会分散控件的注意力。程序可能会在验证和显示消息框的循环中结束。 增强 您可能喜欢使用的一些代码是改变下拉列表中显示的项的行数。这将防止列表末尾出现空行,并改变在资源编辑器中设置的高度。框架确实已经处理了其中的一些事情,但有时拥有控制权是件好事。 隐藏,复制Code

void CComboBoxTutorialDlg::SetNumberOfLines(int nLines)
{
    // This limits the maximum number of visible entries to 7
    nLines = min( max(nLines, 1), 7 );
    CRect lprect;
    m_DropDown.GetWindowRect( &lprect );
    lprect.bottom = lprect.top + nLines * m_DropDown.GetItemHeight( -1 ) + lprect.Height();
    m_DropDown.SetWindowPos(NULL, 0, 0, lprect.Width(), lprect.Height(), SWP_NOMOVE | SWP_NOZORDER );
}

默认情况下,只有在打开下拉列表时,组合框才会处理ENTER键,在本例中,它与单击鼠标进行选择具有相同的效果。一个如果mple组合框根本不处理ENTER键,而是传递给父对话框。如果您希望以其他方式处理ENTER键,则需要为组合框编写子类和处理程序。你可能会喜欢实现一个自动完成的组合框-由Chris Maunder作为起点,处理程序可以添加。 结论 本教程中的消息处理程序是最常用的,应该表明它们不需要非常复杂。更复杂的问题在本网站的其他地方处理。 编程的快乐! 许可证 本文没有附带明确的许可,但可能包含文章文本或下载文件本身的使用条款。如果有疑问,请通过下面的讨论区联系作者。可以在这里找到作者可能使用的许可证列表。 本文转载于:http://www.diyabc.com/frontweb/news189.html

原文地址:https://www.cnblogs.com/Dincat/p/13431059.html