Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

AutoCompleteML - auto completion for multiline edit box

0.00/5 (No votes)
14 Oct 2004 1  
COM object for easy user input in multiline edit boxes

Introduction

It is one more article devoted to autocompletion. I have written the program of the warehouse automation for one organization. The organization is the big warehouse with intensive movement of property that demands filling a plenty of electronic documents. For simplification of users life I used the windows built-in autocompletion, which works only for single-line editboxes (without style ES_MULTILINE). I hoped that to users will be enough of it, but a bit later users have estimated advantages of autocompletion and have wanted it for all textual fields, including multiline editboxes. Attempts to force to work builtin autocompletion in multiline fields did not give of result as well as search of suitable code in the net and I have decided to fill in this blank.

In addition to typical properties of the builtin autocompletion my realization allows transfer a task of management of string storage to the user of the program. User may to add and delete lines from the list, removing thus from the programmer necessity of string storage management.

Description

Autocompletion is realized as COM object (Progid:Acmpl.AutoCompleteML), which connects to editbox. The interface of object (IAutoCompleteML) is defined by analogy to interface IAutoComplete.

 
typedef enum ACMLFlags {
  ACML_AutoSuggest = 1, 
  ACML_AutoAppend = 2, 
  ACML_UpDownKeyDropList = 4,
  //new flags 

  ACML_ToolTip = 8, 
  ACML_EnableUserAutoAdd = 16, 
  ACML_EnableUserDelete = 32
} ACMLFlags;

interface IAutoCompleteML: IDispatch 
{
  [id(1), helpstring("method Init")] HRESULT Init([in] 
    long hwndEdit, [in] IUnknown *punkACL); 
  [propget, id(3), helpstring("property Options")] 
    HRESULT Options([out, retval] ACMLFlags *pVal); 
  [propput, id(3), helpstring("property Options")]
    HRESULT Options([in] ACMLFlags newVal); 
  [propget, id(4), helpstring("property ItemMaxLines")]
    HRESULT ItemMaxLines([out, retval] long *pVal); 
  [propput, id(4), helpstring("property ItemMaxLines")] 
    HRESULT ItemMaxLines([in] long newVal); 
  [propget, id(5), helpstring("property Enabled")] 
    HRESULT Enabled([out, retval] VARIANT_BOOL *pVal); 
  [propput, id(5), helpstring("property Enabled")] 
    HRESULT Enabled([in] VARIANT_BOOL newVal);
};

Properties/methods of autocompletion object (Acmpl.AutoCompleteML) "inherited" from built-in autocompletion:

  • Init() - initialization of autocompletion object, takes handle of editbox, and pointer to autocompletion source object
  • Flag ACML_AutoAppend - autoappend of a text tail
  • Flag ACML_AutoSuggest - dropping out the suggest-list
  • Flag ACML_UpDownKeyDropList - a call of the suggest-list by up/down keys
  • Enable() - autocompletion switching-on/off
New properties (not in the builtin autocompletion):
  • ItemMaxLines - a maximum number of lines in the one item of suggest-list
  • Flag ACML_EnableUserAutoAdd - user can add a line into source of lines by Enter key. If editbox has ES_WANTRETURN style a line can be added by Ctrl+Enter combination
  • Flag ACML_EnableUserDelete - user can remove a line from a source of lines. When this option included elements of the suggest-list are displayed with the remove button
  • Flag ACML_ToolTip - tooltip may be useful to display full text of suggest-list element not limited by ItemMaxLines value

The autocompletion object may use any source of autocompletion wich supports IEnumStrings interface, but thus some new properties of object will be inaccessible. For use of all properties of object it is necessary to use as a source of lines Acmpl.StringStorage object which realizes IStringStorage interface. Also object Acmpl.StringStorage may be used for standard autocompletion object.

 
interface IStringStorage: IDispatch 
{
  [id(1), helpstring("method Add")] HRESULT Add([in] BSTR Item); 
  [id(2), helpstring("method LoadPrivateProfile")] 
    HRESULT LoadPrivateProfile([in] BSTR File, [in] BSTR Section); 
  [id(3), helpstring("method LoadXML")] 
    HRESULT LoadXML([in] VARIANT Source); 
  [id(4), helpstring("method SavePrivateProfile")] 
  HRESULT SavePrivateProfile([in, defaultvalue("")] 
    BSTR File, [in, defaultvalue("")] BSTR Section); 
  [id(5), helpstring("method SaveXML")] 
    HRESULT SaveXML([in] VARIANT Destination); 
  [id(6), helpstring("method Delete")] HRESULT Delete([in] BSTR Item);
};

Methods of object Acmpl.StringStorage:

  • LoadPrivateProfile()/SavePrivateProfile() loads/saves the list of lines in a textual file. Before saving multiline strings will be encoded in single-line. SavePrivateProfile() may be called with empty parameters, in this case lines are saved in the same section of text file whence were loaded
  • LoadXML()/SaveXML() loads/saves the list of lines in xml document, textual parameter are interpreted as name of file, and objective parameter as an xml document element in which will be loaded/saved an child element <strings>
  • Add()/Delete() are automatically called for addition/removal of lines from a source of the data when flags ACML_EnableUserAutoAdd and ACML_EnableUserDelete are set in autocompletion object.

For user interface objects ATL/WTL classes are used. After initialization of autocompletion object subclasses for editbox and his(its) parental window are created. These subclasses process changes of editbox contents and depending of options of autocompletion object the list of suitable lines drops out and/or the suffix to editbox contents is added.

Structure of component project

  • class CACml - COM autocompletion object
  • class CEditML - a subclass of a multiline editbox
  • class CEditMLParent - a subclass of the parent of a multiline editbox
  • class CListBoxML - multiline list control
  • class CListBoxMLParent - the parent for the multiline list control
  • class CStrStg - COM string storage object

Using the code

For use of autocompletion in VC the project it is necessary to import type library from acml.dll

  #import "acmpl.dll"
To create an autocompletion source, to load in it strings
  ACMPLLib::IStringStoragePtr m_spStrings; 
  m_spStrings.CreateInstance(__uuidof(ACMPLLib::StringStorage)); 
  m_spStrings->LoadXML(L"acml.xml");
To create autocompletion object, to connect it with a source of strings and editbox
  ACMPLLib::IAutoCompleteMLPtr m_spac; 
  m_spac.CreateInstance(__uuidof(ACMPLLib::AutoCompleteML)); 
  m_spac->Init((long)GetDlgItem(IDC_EDIT1), m_spStrings);
By default all options of autocompletion are set, for setting a subset of options add the next line.
  m_spac->Options = ACML_AutoSuggest|ACML_ToolTip;

Bonus

For the multiline list in a component WTL-class CListBoxML is used, which is designed portable at a level of source code, and it may be used separately from the component.

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