Auto-completion ComboBox

Auto-complete combobox Download sample project and source files

I had a need for a combobox that would auto-complete, very much like the URL edit box in the toolbar of Netscape Navigator. It was actually surprisingly simple since the base CComboBox is so rich in functionality.

The basic idea is that every time the text in the edit box changes, check to see if there is any text in the drop down list that is prefixed by this edit box text. Handle the CBN_EDITUPDATE message to get the text change notifications, and use GetWindowText() to get the text. CComboBox::SelectString will look for a string in the list which is prefixed by the given string, and select it into the edit box. I then select the portion of text that was added to the users typed text so that they can continue typing and have the additions ignored if they wish. That takes care of 90% of the work.

The only trick is in handling backspaces and deletes. When a user hits delete, the text is changed, and the auto-completion routine will try to restore that text back again. Just check in PreTranslateMessage for a KEY_DOWN message with a virtual key of VK_DELETE or VK_BACK, and temporarily disable the auto-complete mechanism for those key strokes.

Source code

#if !defined(AFX_COMBOBOXEX_H__115F422E_5CD5_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_COMBOBOXEX_H__115F422E_5CD5_11D1_ABBA_00A0243D1382__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

// ComboBoxEx.h : header file
//
// Copyright (c) Chris Maunder 1997.
// Please feel free to use and distribute.


/////////////////////////////////////////////////////////////////////////////
// CComboBoxEx window

class CComboBoxEx : public CComboBox
{
// Construction
public:
	CComboBoxEx();

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CComboBoxEx)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CComboBoxEx();

	BOOL m_bAutoComplete;

	// Generated message map functions
protected:
	//{{AFX_MSG(CComboBoxEx)
	afx_msg void OnEditUpdate();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_COMBOBOXEX_H__115F422E_5CD5_11D1_ABBA_00A0243D1382__INCLUDED_)




// ComboBoxEx.cpp : implementation file
//
// Copyright (c) Chris Maunder 1997.
// Please feel free to use and distribute.

#include "stdafx.h"
#include "ComboBoxEx.h"

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

/////////////////////////////////////////////////////////////////////////////
// CComboBoxEx

CComboBoxEx::CComboBoxEx()
{
	m_bAutoComplete = TRUE;
}

CComboBoxEx::~CComboBoxEx()
{
}


BEGIN_MESSAGE_MAP(CComboBoxEx, CComboBox)
	//{{AFX_MSG_MAP(CComboBoxEx)
	ON_CONTROL_REFLECT(CBN_EDITUPDATE, OnEditUpdate)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CComboBoxEx message handlers

BOOL CComboBoxEx::PreTranslateMessage(MSG* pMsg)
{
	// Need to check for backspace/delete. These will modify the text in
	// the edit box, causing the auto complete to just add back the text
	// the user has just tried to delete. 

	if (pMsg->message == WM_KEYDOWN)
	{
		m_bAutoComplete = TRUE;

		int nVirtKey = (int) pMsg->wParam;
		if (nVirtKey == VK_DELETE || nVirtKey == VK_BACK)
			m_bAutoComplete = FALSE;
	}

	return CComboBox::PreTranslateMessage(pMsg);
}

  // if we are not to auto update the text, get outta here
  if (!m_bAutoComplete) 
      return;

  // Get the text in the edit box
  CString str;
  GetWindowText(str);
  int nLength = str.GetLength();
  
  // Currently selected range
  DWORD dwCurSel = GetEditSel();
  WORD dStart = LOWORD(dwCurSel);
  WORD dEnd   = HIWORD(dwCurSel);

  // Search for, and select in, and string in the combo box that is prefixed
  // by the text in the edit box
  if (SelectString(-1, str) == CB_ERR)
  {
      SetWindowText(str);		// No text selected, so restore what was there before
      if (dwCurSel != CB_ERR)
        SetEditSel(dStart, dEnd);	//restore cursor postion
  }

  // Set the text selection as the additional text that we have added
  if (dEnd < nLength && dwCurSel != CB_ERR)
      SetEditSel(dStart, dEnd);
  else
      SetEditSel(nLength, -1);
Last updated: 12 Sep 1998


Comments

  • Buen cuidado del cabello con el mejor GHD IV Styler

    Posted by vpwsan366 on 07/17/2013 02:19pm

    plancha de pelo ghd utiliza placas de cerámica para liso, fácil de moldear. Control de la tensión, puede crear el más apropiado entre las placas cerámicas de pelo liso. El producto también tiene el mismo anión, la conservación de hacer que el cabello suave y brillante, para evitar el pánico. Cuerpo con una configuración de calor digitales, pantalla digital hace que sea fácil seleccionar la función deseada o ajustar la forma de la temperatura. Puede ayudar a elegir el pelo bien y la temperatura deseada. Pulse un botón, tendrá un efecto perfecto de inmediato. 1 función de apagado automático hora le permite utilizar más paz de la mente. Planchas ghd como operación segura y simple. Ocupar gran cuota de mercado. Convertido en una moda de comprar. Debido a esto, a menudo parece falsa, por lo que cada vez más personas están comprando auténticos planchas ghd. Nuestra tienda, aunque las ventas de negro pelo ghd. Pero somos productos ghd regulares. No traen todo tipo de daño fuego falso. Nuestro producto de mapa con el mapa físico es exactamente el mismo. Para asegurar que los productos reales y fiables. Y vendemos planchas ghd baratas, 7 * 24 funciones en línea, usted puede comprar en cualquier momento. Siempre y cuando haya seleccionado el tipo deseado, complete la información personal, etc temas relacionados, el producto puede ser enviado directamente a las manos de espera. Por favor, comprar productos ghd sentimientos antes, mira a nuestra política de privacidad, Quiénes somos, transporte, preguntas más frecuentes y las políticas más relevantes, esto le ayudará a comprar nuestros productos. Gracias por tu colaboración. [url=http://compraresghd.webspawner.com/]planchas ghd[/url] EE.UU. Altid tiltrækker Vores opmærksomhed, vi kan lide Smukke ting, ting Mennesker eller. Så enhver kvinde ønsker al eje mera charmerende og Smukke. Dette kræver, por lo vi hele tiden Gore dig forandring. --- Hver dag vi skifter Toj og kan BAERE forskellige Toj. Dette er kun udseendet af ændringen, kan vi OGSA læse flere Boger. Skift indefra dig selv. Det hår. Sådan Gor du hår. Dette er OGSA en masa af skønhed spørgsmål. Før Begge er ændret. Hombres hvordan hombre Gor den første tipo. Vi El Vendedor ghd glattejern, hår er et godt konverteringsværktøj, kan det konstant ændre hår dit, los hombres ved din egen parte, ikke kun para Barber Shop kan repuesto dig tid, gennem konstant forandring kan du findes para ejer mera hår. [url=http://ghd-espa-a.manifo.com/]ghd Planchas España[/url] Web oficial de GHD es un servicio gratuito para comprobar la autenticidad del sitio, y usted tiene la intención de comprar su cuerpo de hierro (que recomiendo), el peso también GHD es mucho más bajo que otro hierro (preferiblemente GHD súper fácil que cualquier otra tabla), incluso junta con cable en forma de L de la auténtica GHD pseudoartrosis diferente L, por no hablar de los accesorios de embalaje tales como bolsos calientes pinzas ghd baratas ... que son fáciles de entender que los accesorios adecuados acompañar a su original de GHD es una copia descarada! Por último, para asegurarse de que su proveedor es oficial.

    Reply
  • Styler GHD IV - Mon outil parfait

    Posted by xccjvj293 on 07/16/2013 02:27pm

    Cadeaux de Noël enveloppés dans du papier coloré de Noël, marqué par des tags de nom et distribué avant Noël. Les colis sont généralement ouvertes à la maison en Scandinavie habituellement pendant une fête de famille le réveillon de Noël au Royaume-Uni et aux États-Unis le jour de Noël. Dans les familles avec de petits enfants norvégiens, bon nombre des cadeaux distribués par un Père Noël habillé venir à eux dans son sac. Sinon, il est fréquent de recueillir des cadeaux de Noël dans une pile sous l'arbre de Noël et les ouvrir lorsque la famille est samlet.Trodde Noël lors de l'envoi GHD? [url=http://bbeatsinorge.cabanova.com/]lisseur ghd[/url] Lisseur GHD est un outil de style professionnel avec revêtement avancé de perles en céramique pour une distribution uniforme de la chaleur et de douceur glissent à revêtement céramique normal. Il ne sera pas coincé dans les cheveux et le rendre brillant et droite à zéro tid.Høytpresterende redresseur avec cordon de revêtement en céramique et chauffage rapide à 10 sekunder.Den fonctionnalités réglage automatique de la tension pour le bon fonctionnement dans le monde, il s'éteint automatiquement après 60 minutes et il a un fil à charnière de 3 mètres. Une pochette de rangement résistant luxueux et chauffage inclus. [url=http://ghdpascherfer.hpage.com/]lisseur ghd[/url] Ces dernières strykejern GHD viennent avec un bonbon de protection suscité que vous pouvez sauter quand vous avez fini un protège votre tige droite. Glam Svart vattert sac de roulis est l'accessoire parfait pour Red Metallic GHD. Et d'un être complètement résistant à innsiden rouleau derrière gir deg aussi un tapis résistant à la chaleur pour y distillat une Trygg lieu de repos pour køllene tout en bruk.Prøver y choisir la beste Flatt fer ou redresseur peuvent être skremmende. Comment vite qui ne sera pas Bryte, n'endommagera pas les cheveux et va peiner le plus rapide? Je l'ai fait pour jobben deg, y enquêter sur la Flatt fer beste et défrisants sur le marché. Vous aurez nageoire coûteux Flatt fer arguments affection et le strykejern de flate plus raisonnable ne sera pas Bryte à deg.

    Reply
  • Hoeveel tijd is er nodig om beats by Dr Dre koptelefoon reizen

    Posted by mrswanzi on 06/06/2013 08:53am

    [url=http://koptelefoon-monsterbeats.blogspot.com/]beats by dre[/url] Terwijl ze konden misschien niet klein, oordopjes hebben meestal matig chauffeurs. beats monster by dre vakantie oordopjes verklaren grote driver exploitanten, en gecentreerd in de buurt van de gunstige koper reactie, lijkt de grote automobilisten dimensie rekeningen voor het gebruik van de matige regelmaat reactie. Zelfs als uw oordopjes zijn geweldig, moet je echt de tevreden is slecht een oordopjes waardeloos zijn. Deze oordopjes komen productie van het gebruik van de vele monster headphones isoleren oordopjes truc maten en soorten om de mogelijkheid om een beroep op iedereen te bezitten. bezit vermeld dat, even bewust waarom deze oordopjes factoren zou kunnen ongeschikt iedereen. [url=http://koptelefoon-monsterbeats.cabanova.com/]beats by dre[/url] Met de Monstercable Beats Dr. Dr¨¦ gaat u op in de muziek terwijl u vergeet dat u een hoofdtelefoon draagt. De oorschelpen zijn groot en comfortabel dankzij soepele kussentjes van zacht en geventileerd materiaal. De Beats hoofdtelefoon heeft bovendien een glanzend design en is krasbestendig. [url=http://beatssolokopen.weebly.com/]beats solo kopen[/url] Beats By Dr. Dre heeft de Beats Wireless aangekondigd, een draadloze koptelefoon met Bluetooth. Deze heeft het design van de populaire Solo HD en kan eenvoudig worden gekoppeld met een smartphone of tablet. Het nieuwe model is ook voorzien van ControlTalk, met een microfoon in de oorschelp en alle benodigde bedieningsknoppen. Beats By Dr. Dre introduceert de Beats Wireless bluetooth hoofdtelefoonBeats By Dr. Dre introduceert de Beats Wireless bluetooth hoofdtelefoon die de luisteraar volledige muzikale vrijheid biedt.

    Reply
  • Fashion Party, billige ghd glattejern giver dig en unik frisure

    Posted by motherdhmm on 05/30/2013 03:20pm

    [url=http://www.buy-beatsdrdre.com/]beats by dre headphones[/url] trækkraft alopeci er til stede, hvis en person bånd eller trækker hendes / hans hår, stramt, der forårsager spændinger på hovedbunden. Dette særlige forhold, der kan være permanent, hvis frisure er slidt i lang tid, længe nok til at skade den pågældende persons hårsækkene. [url=http://www.blog.cheapbeatsbydre.co.nz/]beats by dre nz[/url] En fremragende “øjeblikkelig conditioner” er almindeligvis en bestemt dette specifikke præcise klæder din gode hår dage krøllet hår glatning klubber samt giver disse fysik foruden glimt. Speedy hår hårbalsam minimere den faktiske unikke forbedrede neglebånd, oprette dine distinkte god Ghd Tilbud Tresses gør dig hår jern moderat desuden opnås, med hinanden ved hjælp af assistance sikre den faktiske tydelig indre design i de ekstraordinære vilde hår tidsperioder basis via skade gennem betyder at involvere medvirken såsom en filtrering. Denne form for afhjælpning vilde hår emne vil rutinemæssigt blive gengivet anytime ens personlige Ghd hår styling jern vil blive skyllet ud. [url=http://www.buy-beatsdrdre.com/category/new-beats-dr-dre-headphones]Beats By Dr Dre[/url] At sikre det definitivt kan udvikle sig til vigtige for et parti af os alle at overveje rigtige behandling efter de faktiske ordentlig handlinger at finde stykke for næsten næsten enhver vilde hår.

    Reply
  • How we can add an string to list box item of combobox by code?

    Posted by Legacy on 05/01/2003 12:00am

    Originally posted by: zeinalzadeh

    How we can add an string to list box item of combobox by code.While I exit from program that string value be saved on list box data of combobox?

    Reply
  • How to capture the event from Popup menu from the right click??

    Posted by Legacy on 02/06/2003 12:00am

    Originally posted by: R.Singaravelan

    I need to know how to get the key pressed event from the Popup menu(On right click) of the Combo Box(Dropdown list)

    Reply
  • Fix for ShowDropDown() eating up the first entered character

    Posted by Legacy on 02/27/2002 12:00am

    Originally posted by: Manish Singh

    I have been trying to use the Auto Complete Combo Box
    
    and was stuck at this issue, wherein, the ShowDropDown would eat up the first character which was typed in.

    To overcome this problem, what i did was instead of using SelectString, i used FindString and then manually Set that string into the edit control of the combo box

    Here is the modified OnEditUpdate() function which Chris Maunder had written

    void OnEditUpdate()
    {
    // if m_AutoComplete is false we return from here
    if( !m_bAutoComplete )
    return ;

    // Auto Complete the entries

    CString strEnteredText,
    strSuggestedText;

    // Get the text in the Edit box
    GetWindowText( strEnteredText );

    // Length of the text typed in
    int nTextLength = strEnteredText.GetLength();

    // Currently selected range
    DWORD dwCurSel = GetEditSel();
    WORD wStart = LOWORD( dwCurSel );
    WORD wEnd = HIWORD( dwCurSel );

    // Search for the string with the prefix
    int nIndex = 0;

    if( ( nIndex = FindString( -1, strEnteredText ) ) = CB_ERR ) {
    SetWindowText( strEnteredText );// No text selected, so restore what was there before
    if( dwCurSel != CB_ERR )
    SetEditSel( wStart, wEnd ); //restore cursor postion
    }// end of if clause
    else {
    GetLBText( nIndex, strSuggestedText );
    ShowDropDown();
    ::SetCursor( ::LoadCursor( NULL, MAKEINTRESOURCE( IDC_ARROW ) ) );
    SetWindowText( strSuggestedText );
    SetEditSel( nTextLength, -1 );
    }//end of else clause
    }// end of OnEditUpdate

    Reply
  • Problem on using this code

    Posted by Legacy on 02/26/2002 12:00am

    Originally posted by: Meghana Parwate

    Hello,
    I have a dialog-based application . The dialog has a combo box and two buttons - "OK" and "Cancel".
    I used this code to add the autocompletion feature.
    But now the problem is :
    When I press enter after typing a string or on autocompletion , the event that should be generated when the Ok button is clicked , does not occur. In other words,
    if I press enter , it does not execute the code that is supposed to be executed if the Ok button would have been clicked. Ok button clicked code works properly if the Ok button is pressed explicitly.
    Does anyone know why this happens?
    Meghana

    Reply
  • Extended with prefix matching (like "http://")

    Posted by Legacy on 02/11/2002 12:00am

    Originally posted by: Michael Christensen


    I wanted the auto-completion to work with prefix matching
    similar to what you have in the IE address bar. That is,
    when you start typing "www.codeguru" it also matches on
    "http://www.codeguru.com";). What I did might not be the
    cleverest solution but it seems to work ok:

    First I renamed CComboBoxEx to CAutoComboBox to prevent
    the name clash w. the existing CComboBoxEx. Then I extended
    the CAutoComboBox class w. a list of prefixes to recognize
    and with a public function to add such prefixes:

    class CAutoComboBox : public CComboBox
    {
    ...
    public:
    void AddPrefix(CString prefix);
    ...
    private:
    CList<CString, CString> m_prefixes;
    };

    The implementation of AddPrefix simply is:

    void CAutoComboBox::AddPrefix(CString prefix)
    {
    m_prefixes.AddTail(prefix);
    }

    And finally OnEditUpdate was rewritten to look like this:

    void CAutoComboBox::OnEditUpdate()
    {
    // if we are not to auto update the text, get outta here
    if (!m_bAutoComplete)
    return;

    // Get the text in the edit box
    CString str;
    GetWindowText(str);
    int nLength = str.GetLength();

    // Currently selected range
    DWORD dwCurSel = GetEditSel();
    WORD dStart = LOWORD(dwCurSel);
    WORD dEnd = HIWORD(dwCurSel);

    // Search for, and select in, and string in the combo box that is prefixed
    // by the text in the edit box
    if (SelectString(-1, str) == CB_ERR)
    {
    BOOL prefixMatch = FALSE;
    CString prefix;

    //look for matches w. prefixes prepended
    POSITION pos = m_prefixes.GetHeadPosition();
    for (int i=0;i < m_prefixes.GetCount();i++)
    {
    prefix = m_prefixes.GetNext(pos);

    if (str.Left(8) != prefix)
    {
    CString newstr = prefix + str;
    if (SelectString(-1, newstr) != CB_ERR)
    {
    prefixMatch = TRUE;
    nLength += prefix.GetLength();
    dStart += prefix.GetLength();
    dEnd += prefix.GetLength();
    str = newstr;
    break;
    }
    }
    }

    if (!prefixMatch)
    {
    SetWindowText(str); // No text selected, so restore what was there before
    if (dwCurSel != CB_ERR)
    SetEditSel(dStart, dEnd); //restore cursor postion
    }
    }

    // Set the text selection as the additional text that we have added
    if (dEnd < nLength && dwCurSel != CB_ERR)
    SetEditSel(dStart, dEnd);
    else
    SetEditSel(nLength, -1);
    }

    To use this you can f.ex. add code like below to your
    dialogs OnInitDialog:

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

    m_ComboBox.AddPrefix("http://";);
    m_ComboBox.AddPrefix("ftp://";);

    return TRUE;
    }

    ....And thanks for posting the original code!
    Michael

    Reply
  • Excellent Code! Works like a charm!

    Posted by Legacy on 11/07/2001 12:00am

    Originally posted by: Owen Matthews

    Excellent Code! Works like a charm!

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds