65.9K
CodeProject 正在变化。 阅读更多。
Home

AutoCompleteML - 多行编辑框自动完成

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (6投票s)

2004年10月15日

4分钟阅读

viewsIcon

51569

downloadIcon

1625

COM 对象,用于在多行编辑框中轻松进行用户输入

引言

这是另一篇关于自动完成的文章。我为一家组织编写了一个仓库自动化程序。该组织是一个大型仓库,财产移动频繁,需要填写大量电子文档。为了简化用户的生活,我使用了 Windows 内置的自动完成功能,该功能仅适用于单行编辑框(没有 ES_MULTILINE 样式)。我希望这足以满足用户需求,但稍后用户们评估了自动完成的优势,并希望将其应用于所有文本字段,包括多行编辑框。尝试让内置自动完成在多行字段中工作,以及在网上搜索相关代码都未能成功,所以我决定填补这一空白。

除了内置自动完成的典型属性外,我的实现还允许将字符串存储的管理任务委托给程序用户。用户可以从列表中添加和删除行,从而省去了程序员管理字符串存储的麻烦。

描述

自动完成被实现为一个 COM 对象(Progid:Acmpl.AutoCompleteML),它连接到编辑框。对象 (IAutoCompleteML) 的接口是根据 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);
};

自动完成对象(Acmpl.AutoCompleteML)“继承”自内置自动完成的属性/方法

  • Init() - 初始化自动完成对象,接收编辑框的句柄,以及指向自动完成源对象的指针
  • 标志 ACML_AutoAppend - 自动追加文本尾部
  • 标志 ACML_AutoSuggest - 关闭建议列表
  • 标志 ACML_UpDownKeyDropList - 通过上下键调用建议列表
  • Enable() - 自动完成的开关
新属性(内置自动完成中没有)
  • ItemMaxLines - 建议列表单项的最大行数
  • 标志 ACML_EnableUserAutoAdd - 用户可以通过 Enter 键将一行添加到行源。如果编辑框具有 ES_WANTRETURN 样式,则可以通过 Ctrl+Enter 组合键添加一行
  • 标志 ACML_EnableUserDelete - 用户可以从行源中删除一行。启用此选项后,建议列表的元素将显示删除按钮
  • 标志 ACML_ToolTip - 工具提示可能有助于显示建议列表元素的完整文本,而不受 ItemMaxLines 值的限制

自动完成对象可以使用任何支持 IEnumStrings 接口的自动完成源,但这样一来,对象的一些新属性将不可用。要使用该对象的所有属性,必须使用 Acmpl.StringStorage 对象作为行源,该对象实现了 IStringStorage 接口。此外,Acmpl.StringStorage 对象也可以用于标准的自动完成对象。

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

Acmpl.StringStorage 对象的方法

  • LoadPrivateProfile()/SavePrivateProfile() 将行列表加载/保存到文本文件中。保存前,多行字符串将被编码为单行。SavePrivateProfile() 可以用空参数调用,在这种情况下,行将保存在从文件加载的相同文本文件部分中
  • LoadXML()/SaveXML() 将行列表加载/保存到 XML 文档中,文本参数被解释为文件名,对象参数被解释为将加载/保存子元素 <strings> 的 XML 文档元素
  • 当自动完成对象中的标志 ACML_EnableUserAutoAddACML_EnableUserDelete 被设置时,Add()/Delete() 会自动调用,用于添加/删除数据源中的行。

对于用户界面对象,使用了 ATL/WTL 类。初始化自动完成对象后,会为编辑框及其父窗口创建子类。这些子类处理编辑框内容的更改,并根据自动完成对象的选项,显示合适的行列表和/或向编辑框内容添加后缀。

组件项目结构

  • class CACml - COM 自动完成对象
  • class CEditML - 多行编辑框的子类
  • class CEditMLParent - 多行编辑框父窗口的子类
  • class CListBoxML - 多行列表控件
  • class CListBoxMLParent - 多行列表控件的父控件
  • class CStrStg - COM 字符串存储对象

使用代码

要在 VC 项目中使用自动完成,需要从 acml.dll 导入类型库

  #import "acmpl.dll"
创建自动完成源,并向其中加载字符串
  ACMPLLib::IStringStoragePtr m_spStrings; 
  m_spStrings.CreateInstance(__uuidof(ACMPLLib::StringStorage)); 
  m_spStrings->LoadXML(L"acml.xml");
创建自动完成对象,将其与字符串源和编辑框连接
  ACMPLLib::IAutoCompleteMLPtr m_spac; 
  m_spac.CreateInstance(__uuidof(ACMPLLib::AutoCompleteML)); 
  m_spac->Init((long)GetDlgItem(IDC_EDIT1), m_spStrings);
默认情况下,所有自动完成选项都已设置,要设置选项子集,请添加以下行。
  m_spac->Options = ACML_AutoSuggest|ACML_ToolTip;

奖励

对于组件中的多行列表,使用了 WTL 类 CListBoxML,该类设计为在源代码级别上是可移植的,并且可以独立于组件使用。

© . All rights reserved.