AutoCompleteML - 多行编辑框自动完成






3.80/5 (6投票s)
2004年10月15日
4分钟阅读

51569

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_EnableUserAutoAdd
和ACML_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
,该类设计为在源代码级别上是可移植的,并且可以独立于组件使用。