- The Word.Application object can call the engine for a single word or string. The return value is a Boolean indicating True (no errors) or False (errors). Further work must be done to provide spelling suggestions / correction.
- The Document object contained by the Word.Application object exposes all the functionality of MS Word, in particular, the MS Word dialog boxes for spelling and grammar checking can be used.
RTF text can be checked easily by using the CheckClipBoardSpell / Grammar functions.
Custom Dictionaries: Using custom dictionaries is a powerful feature of Word's spelling checker but there appears to be an error in the documentation (at least I can't get it to work as written in Delphi or VBA within Word itself!). Custom dictionaries are text files (usually with a '.dic' extension) with a sorted list of words - one word on each line. Included the ability to "install" a custom dictionary(s) which will be used in all spell checks. The down side is that the dictionary will now be seen by Word all the time, so it's probably a good idea to remove any such dictionary before exiting your program.
Checking if the user wants to cancel spell/grammar checking: In your own program you could check for the press of a "cancel" button or key. This isn't available when using Word's built in dialogs, so I tend to use the SpellingChecked and GrammarChecked properties to check if there are still errors in the text after a spell check has been completed. If the user has decided to quit, these properties should be False. I have mapped them into the UserCancel property for ease of programming.
Installation is very simple, just copy the code and save it as uSpellCheck.pas and include any of your existing/new dpk file.
How to use:
i) Drop the TActionList component onto a form.
ii) Select StandardAction from TActionList
iii)You will see new TSpellCheck action item under Edit category. select it ;-)
By default this action item is associated with F7 shortcut.
iv) Drop few Editable controls like TEdit, TMemo, TRichEdit etc and run the application and press F7 to trigger Spell Check.
That's it really!
{ Unit Name : uSpellCheck.pas Description : TSpellCheck is derived from TEditAction, which is available on TActionList. This newly created action acts as a standard EditAction for example: It gets enabled when the control is in Editable mode. Enhancements: Couldn't think of any more as of now... Create Date : 1st December 2010 Author : Kiran Kumar Kurapaty Code enhanced from original author: Andrew Baylis (ajbaylis@melbpc.org.au), Thanks Andrew. } unit uSpellCheck; interface uses Windows, SysUtils, Classes, ActnList, Forms, StdCtrls, Dialogs, StdActns, ActnRes, Messages, ComObj, ActiveX, Variants; type TWordTimer = class(TThread) private FCaption: string; FDelay: Integer; FDialogWndClass: string; FPopUpExists: Boolean; procedure SetDelay(Value: Integer); protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); procedure Resume; property Caption: string read FCaption write FCaption; property Delay: Integer read FDelay write SetDelay; property DialogWndClass: string read FDialogWndClass write FDialogWndClass; end; TSpellLanguage = Integer; TSpellCheck = class(TEditAction) private FCancel: Boolean; FChangedText: string; FConnected: Boolean; FHandle: HWND; FNumChanges: Integer; FOleOn: Boolean; FSpellCaption: string; FTimer: TWordTimer; FUseSpellCaption: Boolean; FWordApp, FRange, FWordDoc, FCustDics: OLEVariant; FWordDialogClass: string; FWordVersion: string; FLanguage: TSpellLanguage; function GetCheckGWS: Boolean; function GetGrammarErrors: Integer; function GetSpellChecked: Boolean; function GetSpellErrors: Integer; function GetUserCancel: Boolean; function GetVersion: string; function GetWordVersion: string; procedure SetCheckGWS(const Value: Boolean); procedure SetLanguage(Value: TSpellLanguage); protected function Internal_checkGrammar: Boolean; function Internal_checkSpelling: Boolean; procedure StartTimer; procedure StopTimer; public procedure ExecuteTarget(Target: TObject); override; procedure UpdateTarget(Target: TObject); override; function AddCustomDic(const FileName: string): Integer; function CheckClipboardGrammar: Boolean; function CheckClipboardSpell: Boolean; function CheckGrammar(const Text: string): Boolean; function CheckSpelling(const Text: string): Boolean; procedure ClearText; procedure Connect; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Disconnect; procedure RemoveCustomDic(const Name: string); overload; procedure RemoveCustomDic(const Index: Integer); overload; procedure ResetIgnoreAll; procedure SpellingOptions; property ChangedText: string read FChangedText; property CheckGrammarWithSpelling: Boolean read GetCheckGWS write SetCheckGWS; property Connected: Boolean read FConnected; property GrammarErrorCount: Integer read GetGrammarErrors; property NumChanges: Integer read FNumChanges; property SpellChecked: Boolean read GetSpellChecked; property SpellErrorCount: Integer read GetSpellErrors; property UserCancelled: Boolean read GetUserCancel write FCancel; property WordVersion: string read GetWordVersion; published property SpellCaption: string read FSpellCaption write FSpellCaption; property UseSpellCaption: Boolean read FUseSpellCaption write FUseSpellCaption; property Version: string read GetVersion; property Language: TSpellLanguage read FLanguage write SetLanguage; end; LangRecord = record LocalName: string; ID: Integer; end; const // Spelling Language SpellLanguage: array[0..63] of LangRecord = ((LocalName: 'LanguageNone'; ID: $00000000), (LocalName: 'NoProofing '; ID: $00000400), (LocalName: 'Danish '; ID: $00000406), (LocalName: 'German '; ID: $00000407), (LocalName: 'SwissGerman '; ID: $00000807), (LocalName: 'EnglishAUS '; ID: $00000C09), (LocalName: 'EnglishUK '; ID: $00000809), (LocalName: 'EnglishUS '; ID: $00000409), (LocalName: 'EnglishCanadian '; ID: $00001009), (LocalName: 'EnglishNewZealand '; ID: $00001409), (LocalName: 'EnglishSouthAfrica '; ID: $00001C09), (LocalName: 'Spanish '; ID: $0000040A), (LocalName: 'French '; ID: $0000040C), (LocalName: 'FrenchCanadian '; ID: $00000C0C), (LocalName: 'Italian '; ID: $00000410), (LocalName: 'Dutch '; ID: $00000413), (LocalName: 'NorwegianBokmol '; ID: $00000414), (LocalName: 'NorwegianNynorsk '; ID: $00000814), (LocalName: 'BrazilianPortuguese '; ID: $00000416), (LocalName: 'Portuguese '; ID: $00000816), (LocalName: 'Finnish '; ID: $0000040B), (LocalName: 'Swedish '; ID: $0000041D), (LocalName: 'Catalan '; ID: $00000403), (LocalName: 'Greek '; ID: $00000408), (LocalName: 'Turkish '; ID: $0000041F), (LocalName: 'Russian '; ID: $00000419), (LocalName: 'Czech '; ID: $00000405), (LocalName: 'Hungarian '; ID: $0000040E), (LocalName: 'Polish '; ID: $00000415), (LocalName: 'Slovenian '; ID: $00000424), (LocalName: 'Basque '; ID: $0000042D), (LocalName: 'Malaysian '; ID: $0000043E), (LocalName: 'Japanese '; ID: $00000411), (LocalName: 'Korean '; ID: $00000412), (LocalName: 'SimplifiedChinese '; ID: $00000804), (LocalName: 'TraditionalChinese '; ID: $00000404), (LocalName: 'SwissFrench '; ID: $0000100C), (LocalName: 'Sesotho '; ID: $00000430), (LocalName: 'Tsonga '; ID: $00000431), (LocalName: 'Tswana '; ID: $00000432), (LocalName: 'Venda '; ID: $00000433), (LocalName: 'Xhosa '; ID: $00000434), (LocalName: 'Zulu '; ID: $00000435), (LocalName: 'Afrikaans '; ID: $00000436), (LocalName: 'Arabic '; ID: $00000401), (LocalName: 'Hebrew '; ID: $0000040D), (LocalName: 'Slovak '; ID: $0000041B), (LocalName: 'Farsi '; ID: $00000429), (LocalName: 'Romanian '; ID: $00000418), (LocalName: 'Croatian '; ID: $0000041A), (LocalName: 'Ukrainian '; ID: $00000422), (LocalName: 'Byelorussian '; ID: $00000423), (LocalName: 'Estonian '; ID: $00000425), (LocalName: 'Latvian '; ID: $00000426), (LocalName: 'Macedonian '; ID: $0000042F), (LocalName: 'SerbianLatin '; ID: $0000081A), (LocalName: 'SerbianCyrillic '; ID: $00000C1A), (LocalName: 'Icelandic '; ID: $0000040F), (LocalName: 'BelgianFrench '; ID: $0000080C), (LocalName: 'BelgianDutch '; ID: $00000813), (LocalName: 'Bulgarian '; ID: $00000402), (LocalName: 'MexicanSpanish '; ID: $0000080A), (LocalName: 'SpanishModernSort '; ID: $00000C0A), (LocalName: 'SwissItalian '; ID: $00000810)); procedure Register; implementation uses Registry; { TSpellCheck } procedure TSpellCheck.ExecuteTarget(Target: TObject); begin if Assigned(GetControl(Target)) then begin try if CheckSpelling(GetControl(Target).Text) then GetControl(Target).Text := ChangedText; except on E:Exception do MessageDlg(Format('There was an error calling the Spell Checker (%s) - '+ 'you may need to close some Windows Applications and try again', [E.message]), mtError, [mbOk], 0); end; end; end; procedure TSpellCheck.UpdateTarget(Target: TObject); begin inherited; Enabled := Length(GetControl(Target).Text) > 0; end; type TSpellCheckActionClass = class of TSpellCheck; TEditActionClass = class of TEditAction; TEditActionWrapper = class(StdActns.TEditAction); TSpellCheckEditActionInfo = record SpellCheckActionClass: TSpellCheckActionClass; EditActionClass: TEditActionClass; DefaultCaption: string; DefaultHint: string; DefaultImageIndex: Integer; DefaultShortCut: TShortCut; end; TStandardActionsEx = class(TStandardActions) protected procedure CreateByInfo(AEditActionsInfo: TSpellCheckEditActionInfo); function FindEditActionByClassType(AEditActionClass: TEditActionClass): TEditAction; public constructor Create(AOwner: TComponent); override; end; {purpose: Add default properties of future actions here...} const CH4EditActionsCount = 1; CH4EditActionsInfo: array [0..CH4EditActionsCount-1] of TSpellCheckEditActionInfo = ( ( SpellCheckActionClass: TSpellCheck; EditActionClass: TEditAction; DefaultCaption: '&Spell Check'; DefaultHint: 'Spell Check|Check for Spellings and Grammer.'; DefaultImageIndex: -1; DefaultShortCut: VK_F7) ); constructor TStandardActionsEx.Create(AOwner: TComponent); var I: Integer; begin inherited; for I := Low(CH4EditActionsInfo) to High(Ch4EditActionsInfo) do CreateByInfo(CH4EditActionsInfo[I]); end; procedure TStandardActionsEx.CreateByInfo(AEditActionsInfo: TSpellCheckEditActionInfo); var AEditAction: TEditAction; ASpellCheckEditAction: TEditAction; begin AEditAction := FindEditActionByClassType(AEditActionsInfo.EditActionClass); ASpellCheckEditAction := AEditActionsInfo.SpellCheckActionClass.Create(Self); with ASpellCheckEditAction do begin if AEditAction <> nil then begin Caption := TEditActionWrapper(AEditAction).Caption; Hint := TEditActionWrapper(AEditAction).Hint; ImageIndex := TEditActionWrapper(AEditAction).ImageIndex; ShortCut := TEditActionWrapper(AEditAction).ShortCut; end else begin Caption := AEditActionsInfo.DefaultCaption; Hint := AEditActionsInfo.DefaultHint; ImageIndex := AEditActionsInfo.DefaultImageIndex; ShortCut := AEditActionsInfo.DefaultShortCut; end; end; end; function TStandardActionsEx.FindEditActionByClassType(AEditActionClass: TEditActionClass): TEditAction; var I: Integer; begin Result := nil; for I := 0 to ComponentCount - 1 do if (Components[I].ClassType = AEditActionClass) and (Components[I] is TEditAction) then begin Result := Components[I] as TEditAction; Break; end; end; procedure Register; begin RegisterActions('Edit', [TSpellCheck], TStandardActionsEx); end; // these constants used to identify the window class of Word's dialog box const //Constants for MS Word MSDialogWndClass2000 = 'bosa_sdm_Microsoft Word 9.0'; MSDialogWndClass97 = 'bosa_sdm_Microsoft Word 8.0'; MSWordWndClass = 'OpusApp'; CSpellerVersion = '1.0'; function IsWordPresent: Boolean; var Reg: TRegistry; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CLASSES_ROOT; Result := Reg.KeyExists('Word.Application'); finally Reg.Free; end; end; { TSpellCheck } function TSpellCheck.GetCheckGWS: Boolean; begin Result := False; if FConnected then Result := FWordApp.Options.CheckGrammarWithSpelling; end; function TSpellCheck.GetGrammarErrors: Integer; begin if FConnected then Result := FRange.GrammaticalErrors.Count else Result := 0; end; function TSpellCheck.GetSpellChecked: Boolean; // returns false if spelling has yet to be checked begin Result := True; if FConnected then Result := not FRange.SpellingChecked; end; function TSpellCheck.GetSpellErrors: Integer; begin if FConnected then Result := FRange.SpellingErrors.Count else Result := 0; end; function TSpellCheck.GetUserCancel: Boolean; begin Result := FCancel; end; function TSpellCheck.GetVersion: string; begin Result := CSpellerVersion; end; function TSpellCheck.GetWordVersion: string; begin Result := FWordVersion; end; procedure TSpellCheck.SetCheckGWS(const Value: Boolean); begin if FConnected then FWordApp.Options.CheckGrammarWithSpelling := Value; end; function TSpellCheck.Internal_checkGrammar: Boolean; begin SetWindowPos(FHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE + SWP_HIDEWINDOW); // ensures dialogs appear in front FWordDoc.TrackRevisions := True; // note if changes are made FNumChanges := 0; FRange.GrammarChecked := False; if (FLanguage > 0) then // 0 means use the default setting FRange.LanguageID := SpellLanguage[FLanguage].ID; StartTimer; OleCheck(FRange.CheckGrammar); StopTimer; FCancel := not FRange.GrammarChecked; FWordApp.Visible := False; // need to stop ActiveDocument appearing FNumChanges := FRange.Revisions.Count; // seems revisions counts the old word and the new one separately Result := (FRange.Revisions.Count > 0); if Result then FRange.Revisions.AcceptAll; // accept all changes FWordDoc.TrackRevisions := False; // don't track future changes end; function TSpellCheck.Internal_checkSpelling: Boolean; begin SetWindowPos(FHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE + SWP_HIDEWINDOW); // ensures dialogs appear in front FWordDoc.TrackRevisions := True; // note if changes are made FNumChanges := 0; if (FLanguage > 0) then // 0 means use the default setting FRange.LanguageID := SpellLanguage[FLanguage].ID; StartTimer; OleCheck(FWordDoc.CheckSpelling); StopTimer; FCancel := not FWordDoc.SpellingChecked; FWordApp.Visible := False; // need to stop ActiveDocument appearing FNumChanges := FRange.Revisions.Count; // seems revisions counts the old word and the new one separately Result := (FRange.Revisions.Count > 0); if Result then FRange.Revisions.AcceptAll; // accept all changes FWordDoc.TrackRevisions := False; // don't track future changes end; procedure TSpellCheck.StartTimer; begin if FUseSpellCaption then begin FTimer.Caption := FSpellCaption; FTimer.Resume; end; end; procedure TSpellCheck.StopTimer; begin FTimer.Suspend; end; function TSpellCheck.AddCustomDic(const FileName: string): Integer; begin FCustDics.Add(FileName); Result := FCustDics.Count; end; function TSpellCheck.CheckClipboardGrammar: Boolean; // returns true if changes were made. Corrected text is on the clipboard begin Result := False; if not FConnected then Connect; if not FConnected then Exit; // if still not connected then no MS Word! if FConnected then begin FRange.Paste; // replace with new text to check Result := Internal_CheckGrammar; if Result then FRange.Copy; end; end; function TSpellCheck.CheckClipboardSpell: Boolean; // returns true if changes were made. Corrected text is on the clipboard begin Result := False; if not FConnected then Connect; if not FConnected then Exit; // if still not connected then no MS Word! if FConnected then begin FRange.Paste; // replace with new text to check Result := Internal_checkSpelling; if Result then FRange.Copy; // put onto clipboard end; end; function TSpellCheck.CheckGrammar(const Text: string): Boolean; // returns true if changes were made and the corrected text is placed in the Text string begin Result := False; if not FConnected then Connect; if not FConnected then Exit; // if still not connected then no MS Word! if FConnected then begin FChangedText := EmptyStr; FRange.Text := Text; // replace with new text to check Result := Internal_CheckGrammar; if Result then FChangedText := FRange.Text; end; end; function TSpellCheck.CheckSpelling(const Text: string): Boolean; // returns true if changes were made and the corrected text is placed in the Text string begin Result := False; if not FConnected then Connect; if not FConnected then Exit; // if still not connected then no MS Word! if FConnected then begin FChangedText := EmptyStr; FRange.Text := Text; // replace with new text to check Result := Internal_CheckSpelling; if Result then FChangedText := FRange.Text; end else Result := False; end; procedure TSpellCheck.ClearText; begin if FConnected then FRange.Text := EmptyStr; end; procedure TSpellCheck.Connect; var s: string; begin if FConnected then Exit; // don't create two instances try FWordApp := CreateOleObject('Word.Application'); FConnected := True; FWordApp.Visible := False; // hides the application FWordApp.ScreenUpdating := False; // speed up winword's processing FWordApp.WindowState := $00000002; // minimise FWordDoc := FWordApp.Documents.Add(EmptyParam, False); // this will hold the text to be checked FRange := FWordDoc.Range; FRange.WholeStory; // makes FRange point to all text in document FCustDics := FWordApp.CustomDictionaries; FWordVersion := FWordApp.Version; s := FWordDoc.Name + ' - ' + FWordApp.Name; FHandle := FindWindow(MSWordWndClass, PChar(s)); // winword if FWordVersion[1] = '9' then FWordDialogClass := MSDialogWndClass2000 else FWordDialogClass := MSDialogWndClass97; FTimer := TWordTimer.Create(True); FTimer.Delay := 50; // every 0.05 s FTimer.DialogWndClass := FWordDialogClass; FTimer.FreeOnTerminate := True; except FWordApp := Unassigned; FConnected := False; if Assigned(FTimer) then begin FTimer.Terminate; while FTimer.Suspended do FTimer.Resume; end; FTimer := nil; MessageDlg('Unable to initialise MS Word', mtError, [mbYes], 0); end; end; constructor TSpellCheck.Create(AOwner: TComponent); var init: Integer; begin inherited; FConnected := False; FCancel := False; FChangedText := EmptyStr; Init := CoInitialize(nil); if (Init = S_OK) or (Init = S_FALSE) then FOleOn := True else raise EOleSysError.CreateFmt('Error initialising COM library', []); FSpellCaption := EmptyStr; FUseSpellCaption := False; FLanguage := 0; end; destructor TSpellCheck.Destroy; begin Disconnect; if FOleOn then CoUninitialize; inherited; end; procedure TSpellCheck.Disconnect; var savechanges: OleVariant; begin if not VarIsEmpty(FWordApp) then begin savechanges := False; FWordApp.Quit(savechanges); // don't save changes FRange := Unassigned; FWordDoc := Unassigned; FWordApp := Unassigned; FCustDics := Unassigned; FConnected := False; if Assigned(FTimer) then begin FTimer.Terminate; while FTimer.Suspended do FTimer.Resume; // need this in case thread was never started end; FTimer := nil; end; end; procedure TSpellCheck.RemoveCustomDic(const Name: string); var dic: OleVariant; begin dic := FCustDics.Item(Name); if not VarIsEmpty(dic) then dic.Delete; dic := Unassigned; end; procedure TSpellCheck.RemoveCustomDic(const Index: Integer); var dic: OleVariant; begin dic := FCustDics.Item(Index); if not VarIsEmpty(dic) then dic.Delete; dic := Unassigned; end; procedure TSpellCheck.ResetIgnoreAll; begin if FConnected then begin FRange.Text := ''; // ResetIgnoreAll performs an automatic spell check FWordApp.ResetIgnoreAll; end; end; procedure TSpellCheck.SpellingOptions; begin BringWindowToTop(FHandle); // ensures that dialog opens on top FWordApp.Dialogs.Item($000000D3).Show; FWordApp.Visible := False; end; procedure TSpellCheck.SetLanguage(Value: TSpellLanguage); begin FLanguage := Value; end; { TWordTimer } procedure TWordTimer.SetDelay(Value: Integer); begin if (Value > 0) then FDelay := Value; end; procedure TWordTimer.Execute; var h: HWND; begin while not Terminated do begin sleep(FDelay); // use this as a rough timer if (FDialogWndClass <> EmptyStr) then begin h := FindWindow(PChar(FDialogWndClass), nil); if (h <> 0) and (not FPopUpExists) then // only change caption if the window has just appeared begin SetWindowText(h, PChar(FCaption)); FPopUpExists := True; end else FPopUpExists := False; end; end; end; constructor TWordTimer.Create(CreateSuspended: Boolean); begin FDelay := 100; // default delay (ms) inherited Create(CreateSuspended); end; procedure TWordTimer.Resume; begin FPopUpExists := False; inherited; end; end.
2 comments:
Spell Checker control
if you find a good news website who provide all type of videos and new then go to this website
Desirulez
And if you find latest and upcoming videos song then visit here Desi videos
Or if you find the latest and trending movie to watch online visit here Desi movies
If you like to learn the latest news visit here Trending Topic
If you want to like to play online games then visit here Desi play online Games
Post a Comment