Hello everyone,
I am trying to spell check a String on Windows 10/11 using declares in Xojo. Windows 10/11 now comes with a built-in spell checker. Unfortunately my approach fails when initializing the COM object and I don’t see where the error could be. Any thoughts on this?
Sample call
CheckSpelling("Hallo Weld, wie gehd es Dir heude? Alles gute zun geburtsdag. Mir geht es gud.")
CheckSpelling
Public Sub CheckSpelling(txt As String)
#If TargetWindows Then
Soft Declare Function CoCreateInstance Lib "ole32.dll" ( _
ByRef rclsid As CString, _
ByVal pUnkOuter As Ptr, _
ByVal dwClsContext As UInt32, _
ByRef riid As CString, _
ByRef ppv As Ptr _
) As Int32
Soft Declare Function CoInitializeEx Lib "ole32.dll" ( _
ByVal pvReserved As Ptr, _
ByVal dwCoInit As UInt32 _
) As Int32
Soft Declare Function CoUninitialize Lib "ole32.dll" () As Int32
Const CLSCTX_INPROC_SERVER As UInt32 = &h1
Const COINIT_APARTMENTTHREADED As UInt32 = &h2
// GUIDs for the ISpellCheckerFactory and ISpellChecker interfaces as strings
Var CLSID_SpellCheckerFactory As CString = "{7AB36653-1796-484B-BDFA-E74F1DB7C1DC}"
Var IID_ISpellCheckerFactory As CString = "{8E018A9D-2415-4677-BF08-794EA61F94BB}"
Var IID_ISpellChecker As CString = "{B6FD0B71-98C5-403A-BF8B-80EE0C7DFCAA}"
Var IID_IEnumSpellingError As CString = "{803E3BD4-2828-4410-8290-418D1D73C762}"
// Initialize COM
Var hr As Int32 = CoInitializeEx(Nil, COINIT_APARTMENTTHREADED)
If hr <> 0 Then
MessageBox("Error during COM initialization: " + hr.ToString)
Return
End If
// Create ISpellCheckerFactory
Var pSpellCheckerFactory As Ptr
hr = CoCreateInstance(CLSID_SpellCheckerFactory, Nil, CLSCTX_INPROC_SERVER, IID_ISpellCheckerFactory, pSpellCheckerFactory)
If hr <> 0 Then
MessageBox("Error when creating the ISpellCheckerFactory: " + hr.ToString)
Call CoUninitialize
Return
End If
// Declares for the methods of ISpellCheckerFactory and ISpellChecker
Soft Declare Function GetSpellChecker Lib "spellcheck.dll" ( _
ByVal pFactory As Ptr, _
ByVal lang As WString, _
ByRef ppChecker As Ptr _
) As Int32
Soft Declare Function Check Lib "spellcheck.dll" ( _
ByVal pChecker As Ptr, _
ByVal text As WString, _
ByRef ppErrors As Ptr _
) As Int32
Soft Declare Function NextError Lib "spellcheck.dll" ( _
ByVal pEnum As Ptr, _
ByRef pError As Ptr _
) As Int32
// Retrieve ISpellChecker for the language
Var pSpellChecker As Ptr
hr = GetSpellChecker(pSpellCheckerFactory, "de-DE", pSpellChecker)
If hr <> 0 Then
MessageBox("Error when retrieving the ISpellChecker: " + hr.ToString)
pSpellCheckerFactory = Nil
Call CoUninitialize
Return
End If
// Check text for spelling mistakes
Var pErrors As Ptr
hr = Check(pSpellChecker, txt, pErrors)
If hr <> 0 Then
MessageBox("Spell check error: " + hr.ToString)
pSpellChecker = Nil
pSpellCheckerFactory = Nil
Call CoUninitialize
Return
End If
// Process errors
If pErrors <> Nil Then
' errorList is a DesktopListbox on our window
errorList.HasHeader = True
errorList.HeaderAt(0) = "Incorrect words"
Var pError As Ptr
While NextError(pErrors, pError) = 0 And pError <> Nil
// Declares for ISpellingError
Soft Declare Function GetStart Lib "spellcheck.dll" (ByVal pError As Ptr) As UInt32
Soft Declare Function GetLength Lib "spellcheck.dll" (ByVal pError As Ptr) As UInt32
Soft Declare Function GetCorrectiveAction Lib "spellcheck.dll" (ByVal pError As Ptr) As UInt32
Soft Declare Function GetReplacement Lib "spellcheck.dll" (ByVal pError As Ptr, ByRef pReplacement As WString) As Int32
Var start As UInt32 = GetStart(pError)
Var length As UInt32 = GetLength(pError)
Var correctiveAction As UInt32 = GetCorrectiveAction(pError)
Var incorrectWord As String = txt.Middle(start, length)
Var replacement As WString
Call GetReplacement(pError, replacement)
Var correctiveActionStr As String
Select Case correctiveAction
Case 0
correctiveActionStr = "No action"
Case 1
correctiveActionStr = "Suggestion"
Case 2
correctiveActionStr = "Replace"
Case 3
correctiveActionStr = "Ignore"
Else
correctiveActionStr = "Unknown"
End Select
errorList.AddRow(incorrectWord + " (Index: " + start.ToString + ", Length: " + length.ToString + ", Action: " + correctiveActionStr + ", Suggestion: " + replacement + ")")
Wend
If errorList.RowCount > 0 Then
MessageBox("Spelling mistake found!")
Else
MessageBox("No spelling mistakes found.")
End If
Else
MessageBox("No spelling mistakes found.")
End If
// Release COM
pSpellChecker = Nil
pSpellCheckerFactory = Nil
Call CoUninitialize
#Else
#Pragma Unused txt
#EndIf
End Sub