Search code examples
delphispell-checking

Spellcheck components for Delphi


One of the requirements for the twitter client we are developing for the community is a spellcheck component. What are some of the spellcheck components/systems you have used in applications and what was your experience using it?


Solution

  • Windows comes with a spell checker API (Windows 8).

    TWindow8SpellChecker = class(TCustomSpellChecker)
    private
        FSpellChecker: ISpellChecker;
    public
        constructor Create(LanguageTag: UnicodeString='en-US');
    
        procedure Check(const text: UnicodeString; const Errors: TList); override; //gives a list of TSpellingError objects
        function Suggest(const word: UnicodeString; const Suggestions: TStrings): Boolean; override;
    end;
    

    With implementation:

    constructor TWindow8SpellChecker.Create(LanguageTag: UnicodeString='en-US');
    var
        factory: ISpellCheckerFactory;
    begin
        inherited Create;
    
        factory := CoSpellCheckerFactory.Create;
        OleCheck(factory.CreateSpellChecker(LanguageTag, {out}FSpellChecker));
    end;
    
    procedure TWindow8SpellChecker.Check(const text: UnicodeString; const Errors: TList);
    var
        enumErrors: IEnumSpellingError;
        error: ISpellingError;
        spellingError: TSpellingError;
    begin
        if text = '' then
            Exit;
    
        OleCheck(FSpellChecker.Check(text, {out}enumErrors));
    
        while (enumErrors.Next({out}error) = S_OK) do
        begin
            spellingError := TSpellingError.Create(
                    error.StartIndex,
                    error.Length,
                    error.CorrectiveAction,
                    error.Replacement);
            Errors.Add(spellingError);
        end;
    end;
    
    function TWindow8SpellChecker.Suggest(const word: UnicodeString; const Suggestions: TStrings): Boolean;
    var
        hr: HRESULT;
        enumSuggestions: IEnumString;
        ws: PWideChar;
        fetched: LongInt;
    begin
        if (word = '') then
        begin
            Result := False;
            Exit;
        end;
    
        hr := FSpellChecker.Suggest(word, {out}enumSuggestions);
        OleCheck(hr);
    
        Result := (hr = S_OK); //returns S_FALSE if the word is spelled correctly
    
        ws := '';
        while enumSuggestions.Next(1, {out}ws, {out}@fetched) = S_OK do
        begin
            if fetched < 1 then
                Continue;
    
            Suggestions.Add(ws);
    
            CoTaskMemFree(ws);
        end;
    end;
    

    The TSpellingError object is a trivial wrapper around four values:

    TSpellingError = class(TObject)
    protected
        FStartIndex: ULONG;
        FLength: ULONG;
        FCorrectiveAction: CORRECTIVE_ACTION;
        FReplacement: UnicodeString;
    public
        constructor Create(StartIndex, Length: ULONG; CorrectiveAction: CORRECTIVE_ACTION; Replacement: UnicodeString);
        property StartIndex: ULONG read FStartIndex;
        property Length: ULONG read FLength;
        property CorrectiveAction: CORRECTIVE_ACTION read FCorrectiveAction;
        property Replacement: UnicodeString read FReplacement;
    end;