Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Using the CComboBox control

, 23 Mar 2001
An entry level tutorial on using the CComboBox control
combobox_tut_demo.zip
ComboBoxTutorial
ComboBoxTutorial.aps
ComboBoxTutorial.clw
ComboBoxTutorial.dsp
ComboBoxTutorial.dsw
ComboBoxTutorial.ncb
ComboBoxTutorial.opt
ComboBoxTutorial.plg
Debug
ComboBoxTutorial.exe
res
ComboBoxTutorial.ico
// ComboBoxTutorialDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ComboBoxTutorial.h"
#include "ComboBoxTutorialDlg.h"
#include "resource.h"
#include "string.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComboBoxTutorialDlg dialog

CComboBoxTutorialDlg::CComboBoxTutorialDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CComboBoxTutorialDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CComboBoxTutorialDlg)
	m_InsertText = FALSE;
	m_LoadList = FALSE;
	m_AddData = FALSE;
	m_strDropDown = _T("");
	m_strSimple = _T("");
	m_nDropListIndex = -1;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CComboBoxTutorialDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CComboBoxTutorialDlg)
	DDX_Control(pDX, IDC_COMBO3, m_Simple);
	DDX_Control(pDX, IDC_COMBO2, m_DropList);
	DDX_Control(pDX, IDC_COMBO1, m_DropDown);
	DDX_Check(pDX, IDC_CHECK1, m_InsertText);
	DDX_Check(pDX, IDC_CHECK2, m_LoadList);
	DDX_Check(pDX, IDC_CHECK3, m_AddData);
	DDX_CBString(pDX, IDC_COMBO1, m_strDropDown);
	DDX_CBString(pDX, IDC_COMBO3, m_strSimple);
	DDX_CBIndex(pDX, IDC_COMBO2, m_nDropListIndex);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CComboBoxTutorialDlg, CDialog)
	//{{AFX_MSG_MAP(CComboBoxTutorialDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CHECK1, OnInsertText)
	ON_BN_CLICKED(IDC_CHECK2, OnLoadList)
	ON_CBN_SELCHANGE(IDC_COMBO1, OnDropDownSelchange)
	ON_CBN_SELCHANGE(IDC_COMBO2, OnDropListSelchange)
	ON_CBN_EDITUPDATE(IDC_COMBO3, OnSimpleEditupdate)
	ON_CBN_SELCHANGE(IDC_COMBO3, OnSimpleSelchange)
	ON_BN_CLICKED(IDC_CHECK3, OnAddItemData)
	ON_BN_CLICKED(IDC_BUTTON1, OnSelectItem3)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComboBoxTutorialDlg message handlers

BOOL CComboBoxTutorialDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	//*****************************************************************************
	//  Up to here is the Dialog based application inits
	//  
	//  Now we init the combo boxes

	m_Simple.ResetContent();

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

	m_DropDown.SetCurSel( 0 );
	m_DropList.SetCurSel( 1 );

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CComboBoxTutorialDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CComboBoxTutorialDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CComboBoxTutorialDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

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

	if( m_InsertText )
	{
		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);

		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);
	}
	else
	{
		CString str;
		str.LoadString(IDS_STRING108);
		int idx = m_DropList.FindString(0, str);
		// we add one because we want it after 
		if( idx != CB_ERR )
			m_DropList.DeleteString(idx);

		// reset size
		CRect rc;
		m_DropList.GetWindowRect( &rc );
		m_DropList.SetDroppedWidth( rc.Width());
	}	
	m_DropList.SetCurSel( 1 );
}

void CComboBoxTutorialDlg::OnLoadList() 
{
	UpdateData();
	m_Simple.ResetContent();
	if( m_LoadList )
	{
		m_Simple.Dir( DDL_READWRITE,_T("*.*"));
		m_Simple.SetCurSel(m_Simple.GetCount()-2);
	}
}

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

	m_DropDown.GetLBText( idx, str );
	CString Out;
	if( m_AddData )
	{
		DWORD dw = m_DropDown.GetItemData( idx );
		Out.Format( "Drop List Selection => index %d\n%s = 0x%08X", idx, str, dw );
	}
	else
		Out.Format( "Drop List Selection => index %d\n%s", idx, str );

	AfxMessageBox( Out ); 
}

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

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." );
	}
}

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

void CComboBoxTutorialDlg::OnAddItemData() 
{
	UpdateData();
	m_DropDown.ResetContent();
	CString str;
	if( m_AddData )
	{
		for( UINT i=IDS_STRING109; i<=IDS_STRING115; i++ )
		{
			str.LoadString( i );
			int pos = str.Find( '|' );
			char* end;
			DWORD dw = (DWORD)strtoul((LPCSTR)str.Mid(pos+1), &end, 0);
			int idx = m_DropDown.AddString( str.Left(pos));
			m_DropDown.SetItemData( idx, dw );
		}
	}
	else
	{
		for( int i=0; i<6; i++ )
		{
			str.LoadString(IDS_STRING102 + i);
			m_DropDown.AddString(str);
		}
	}
	m_DropDown.SetCurSel( 0 );
}

void CComboBoxTutorialDlg::OnSelectItem3() 
{
	m_nDropListIndex = 2;
	m_AddData = 0;				// used here to ensure the correct list is loaded
	OnAddItemData();			// used here to ensure the correct list is loaded
	UpdateData(FALSE);
	m_Simple.SetCurSel(2);

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

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Wolfram Steinke
Engineer MedTech Global
Australia Australia
Started working with computers when I/O was with punched paper tape, using Algol. Then learned Fortran, Basic, various Assemblers, Forth and Postscript. Built a robot in the early '80s. When I finally got a PC I learned C, C++ and more recently worked on a variety of .NET and PHP projects. Senior Software Engineer at MedTech Global in Melbourne, Australia.

| Advertise | Privacy | Mobile
Web04 | 2.8.140821.2 | Last Updated 24 Mar 2001
Article Copyright 2000 by Wolfram Steinke
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid