Most Popular Delphi Content
A common feature of Microsoft Windows is auto completion. Auto completion functions to expand text as you type, making suggestions to reduce repetitive tasks. With auto completion, partial words can be expanded into more complete phrases that match a stored list of choices. The end result is less typing and more accurate text entry.| CoClasses |
CLSID_AutoComplete |
CLSID_ACLHistory |
CLSID_ACListISF |
CLSID_ACLMRU |
CLSID_ACLMulti |
| Interfaces |
IAutoComplete |
IAutoComplete2 |
IACList |
IACList2 |
ICurrentWorkingDirectory |
IObjMgr |
type
IAutoComplete = interface(IUnknown)
[SID_IAutoComplete]
function Init(hwndEdit: HWND; punkACL: IUnknown; pwszRegKeyPath: PWideChar;
pwszQuickComplete: PWideChar): HResult; stdcall;
function Enable(fEnable: Boolean): HResult; stdcall;
end;
As you can see, IAutoComplete is a simple interface with has two methods: Init and Enable.
The Enable method simply activates or deactivates auto completion based on the value of the fEnable flag. Auto completion is enabled by default.type
IAutoComplete2 = interface(IAutoComplete)
[SID_IAutoComplete]
function SetOptions(dwFlag: DWORD): HResult; stdcall;
function GetOptions(out dwFlag: DWORD): HResult; stdcall;
end;
IAutoComplete2 introduces two new methods. Both methods use the same parameter types, which is a single unsigned integer consisting of a set of logically combined flags. Here is a table of the auto completion options flags and their meanings.| Flag | Description |
ACO_NONE
|
Don't use auto completion. |
ACO_AUTOSUGGEST
|
Use a drop down list. |
ACO_SEARCH
|
Add the text "Search for" to the end of the drop down list. |
ACO_FILTERPREFIXES
|
Prevents auto completion from matching common prefixes such as"www.", "http://". |
ACO_USETAB
|
The TAB key is used to select an item from the drop down list. |
ACF_UPDOWNKEYDROPSLIST
|
The UP ARROW and DOWN ARROW keys to cause the drop down list to appear. |
ACO_RTLREADING
|
Used for right to left reading. |
Notice that the TAB key option must be specifically enabled. This is because the TAB key is normally used to navigate between controls, not within a control. Setting ACO_USETAB as a flag allows the user to navigate to the drop down list by pressing TAB. When the drop down list is closed, the TAB key allows the user to navigate from normally between controls. When the list is dropped down, pressing the ESCAPE key closes the list. CoInitialize(nil);
OleCheck(CoCreateInstance(CLSID_AutoComplete, nil, CLSCTX_INPROC_SERVER,
IID_IAutoComplete2, FAutoComplete));
Thankfully Delphi's run time library makes working with COM easy. The ComObj unit takes care initializing and uninitializing the COM libraries for you, so you never have to call CoInitialize. It defines a function named CreateComObject which creates a single unknown interface of the class associated with it class id parameter. Internally CreateComObject calls CoCreateInstance, requesting and unknown interface from the CoClass.FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;To convert an unknown interface returned from CreateComObject into something useful, use interface querying with the "as" operator. Interface querying with the "as" operator performs safe checked calls, so if the interface being queried for is not supported, an exception will be raised.
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ShlIntf, ActiveX, ComObj, StdCtrls, StrTools;
type
TAutoCompleteForm = class(TForm)
CompletionEdit: TEdit;
CompletionLabel: TLabel;
SourceGroupBox: TGroupBox;
SourceMemo: TMemo;
procedure FormCreate(Sender: TObject);
private
FAutoComplete: IAutoComplete2;
FStrings: IUnknown;
end;
var
AutoCompleteForm: TAutoCompleteForm;
implementation
{$R *.DFM}
{ TAutoCompleteForm }
procedure TAutoCompleteForm.FormCreate(Sender: TObject);
begin
FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;
FStrings := TEnumString.Create(SourceMemo.Lines) as IUnknown;
OleCheck(FAutoComplete.SetOptions(ACO_AUTOSUGGEST or ACO_UPDOWNKEYDROPSLIST));
OleCheck(FAutoComplete.Init(CompletionEdit.Handle, FStrings, nil, nil));
end;
end.
The first line of the event handler above creates an instance of the auto complete CoClass. It queries the unknown result form CreateComObject for an IAutoComplete2 interface. If your system does not support IAutoComplete2, this line will cause an EInvalidCastError exception to be raised. The next line creates an instance of the TEnumString class and queries it for IUnknown. This interface is used later as the punkACL parameter in the Init method of FAutoComplete. The TEnumString class is derived from TInterfacedObject and defined in the StrTools unit. It basic purpose is to make a TStrings object IEnumString compatible. Next we set the options of FAutoComplete to include the drop down list and auto suggest. Finally we initialize the FAutoComplete, associating it with the edit window, and providing an auto completion list from which it can enumerate candidate strings.| CoClass | Description |
CLSID_History
|
The history class provides access to the items in your history folder. |
CLSID_ACListISF
|
The shell folder class lets you work with to the contents of the shell's namespace. |
CLSID_MRU
|
The most recently used class contains a list of strings of recently run programs. |
var
WorkingDirectory: ICurrentWorkingDirectory;
begin
FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;
FStrings := CreateComObject(CLSID_ACListISF);
WorkingDirectory := FStrings as ICurrentWorkingDirectory;
OleCheck(WorkingDirectory.SetDirectory('C:\'));
OleCheck(FAutoComplete.SetOptions(ACO_AUTOSUGGEST or ACO_UPDOWNKEYDROPSLIST));
OleCheck(FAutoComplete.Init(CompletionEdit.Handle, FStrings, nil, nil));
end;
Improving auto completion
Although we have seen that auto completion is relatively easy to work with, there are a few changes that can be made to make it fit better into Delphi's object framework. The most obvious improvement to the auto completion interfaces would be to create a friendly component wrapper around them, encapsulating their various aspects into a single class. Another improvement would be to allow auto completion to work with controls that contain an embedded edit window. In figure four below, a TAutoComplete component is linked to a TTreeView control.
Download Auto Completion Example
Posted on 05/12/2006
Debug Output:
Invalid Address specified to RtlFreeHeap( 00140000, 0015EA04)

