The next thing that I'd like to talk about are properties. While the TSF manager implements basic property handling (via ITfProperty), a text service has the ability to customize the way TSF handles properties.
If your text service wishes to attach private information to the inserted text, it can do so by calling ITfProperty::SetValue. If you need to control the lifetime of that information (for example, when the property is removed during edits, or how the property will be serialized, or if your data doesn't easily fit in a VARIANT), then your property object needs to implement ITfPropertyStore, and your text service needs to call ITfProperty::SetValueStore instead of ITfProperty::SetValue.
If your text service has a property that implements ITfPropertyStore, and the properties are being serialized, then your text service also must implement ITfCreatePropertyStore (so that your properties can be deserialized), and it's a good idea to implement ITfFnPropertyUIStatus, as well. (I'll talk more about ITfFnPropertyUIStatus later.)
Passed to ITfProperty::SetValueStore
Obtained by QI from ITfTextInputProcessor
Properties can be of 3 styles - static, static-compact, and custom.
Static properties store simple variants. TSF always discards static properties when the range is modified, and serializes static properties that are not of type VT_UNKNOWN.
Static-compact properties are similar to static properties, except that the range data for the properties are not stored; therefore, if two adjacent text ranges have the identical static-compact property applied to them, the ranges will be collapsed. This can make a difference if you're enumerating the ranges of text covered by a particular property.
If your text service defines one or more properties (i.e., not one of the predefined properties), your text service must also register each property via the category manager at install time. You must register the property style so that TSF knows what to do when the text changes. The property style is registered like this:
ITfCategoryMgr::RegisterCategory(<clsid of text service>, GUID_TFCAT_PROPSTYLE_XXX, <guid of property>);
If your text service stores ink or audio data in a property, your text service must also register the property in a property category, like this:
ITfCategoryMgr::RegisterCategory(<clsid of text service>, GUID_TFCAT_PROP_XXX, <guid of property>);