Megosztás a következőn keresztül:


Tulajdonságok (gyakori elemek)

A Text Services Framework (TSF) olyan tulajdonságokat biztosít, amelyek metaadatokat társítanak egy szövegtartományhoz. Ezek a tulajdonságok többek között olyan attribútumokat tartalmaznak, mint a félkövér szöveg, a szöveg nyelvi azonosítója, valamint a szövegszolgáltatás által biztosított nyers adatok, például a beszédszöveg-szolgáltatás szövegéhez társított hangadatok.

Az alábbi példa bemutatja, hogyan tekinthető meg egy hipotetikus szövegszín tulajdonság, amelynek lehetséges értéke piros (R), zöld (G) vagy kék (B).

COLOR:      RR      GGGGGGGG
TEXT:  this is some colored text

A különböző típusú tulajdonságok átfedésben lehetnek. Vegyük például az előző példát, és adjunk hozzá egy szöveges attribútumot, amely félkövér (B) vagy dőlt (I) lehet.

ATTRIB:BBBBBBB      IIIIIIIIIIII
COLOR:      RR      GGGGGGGG
TEXT:  this is some colored text

Az "ez" szöveg félkövér, az "is" félkövér és piros, a "néhány" normál módon jelenik meg, a "színes" zöld és dőlt, a "szöveg" pedig dőlt.

Az azonos típusú tulajdonságok nem fedhetők át. A következő helyzet például nem engedélyezett, mert az "is" és a "színes" azonos típusú átfedésben van.

COLOR: GGG GGGG RRR BBBBGGG     
COLOR:      RR      GGGGGGGG
TEXT:  this is some colored text

Tulajdonságtípusok

A TSF három különböző tulajdonságtípust határoz meg.

Tulajdonságtípus Leírás
Statikus Egy statikus tulajdonságobjektum szöveggel tárolja a tulajdonságadatokat. Emellett a tulajdonság által érintett tartományok szöveginformációinak tartományát is tárolja. ITfReadOnlyProperty::A GetType a GUID_TFCAT_PROPSTYLE_STATIC kategóriát adja vissza.
Static-Compact A statikus-kompakt tulajdonságobjektumok megegyeznek egy statikus tulajdonságobjektummal, kivéve, ha egy statikus-kompakt tulajdonság nem tárol tartományadatokat. Ha a statikus-kompakt tulajdonság által lefedett tartományt kéri, a rendszer létrehoz egy tartományt a szomszédos tulajdonságok minden csoportjához. A statikus-kompakt tulajdonságok a tulajdonságok karakterenkénti tárolásának leghatékonyabb módja. ITfReadOnlyProperty::A GetType a GUID_TFCAT_PROPSTYLE_STATICCOMPACT kategóriát adja vissza.
Szokás Az egyéni tulajdonságobjektumok az egyes tartományok tartományadatait tárolják, amelyekre a tulajdonság vonatkozik. A tulajdonság tényleges adatait azonban nem tárolja. Ehelyett egy egyéni tulajdonság egy ITfPropertyStore objektumot tárol. A TSF-kezelő ezt az objektumot használja a tulajdonságadatok eléréséhez és karbantartásához. ITfReadOnlyProperty::GetType a GUID_TFCAT_PROPSTYLE_CUSTOM kategóriát adja vissza.

 

Tulajdonságok használata

A tulajdonságértékek és attribútumok az ITfReadOnlyProperty interfész használatával szerezhetők be, és az ITfProperty interfész használatával módosulnak.

Ha egy adott tulajdonságtípusra van szükség, akkor ITfContext::GetProperty lesz használva. ITfContext::GetProperty egy GUID- igényel, amely azonosítja a beolvasandó tulajdonságot. A TSF előre definiált tulajdonságazonosítók készletét határozza meg, vagy egy szövegszolgáltatás definiálhatja saját tulajdonságazonosítóit. Egyéni tulajdonság használata esetén a tulajdonságszolgáltatónak közzé kell tennie a tulajdonságot GUID és a kapott adatok formátumát.

Ha például be szeretné szerezni a CLSID- egy szövegtartomány tulajdonosának, hívja meg ITfContext::GetProperty a tulajdonságobjektum beszerzéséhez, hívja meg ITfProperty::FindRange a teljes tulajdonságot lefedő tartomány lekéréséhez, majd hívja meg ITfReadOnlyProperty::GetValue, hogy lekérjen egy TfGuidAtom, amely a szöveget birtokló szövegszolgáltatás CLSID- jelöli. Az alábbi példa egy olyan függvényt mutat be, amely egy kontextus, tartomány és egy szerkesztési cookie alapján a szöveget birtokló szövegszolgáltatás CLSID- fogja beszerezni.

HRESULT GetTextOwner(   ITfContext *pContext, 
                        ITfRange *pRange, 
                        TfEditCookie ec, 
                        CLSID *pclsidOwner)
{
    HRESULT     hr;
    ITfProperty *pProp;

    *pclsidOwner = GUID_NULL;

    hr = pContext->GetProperty(GUID_PROP_TEXTOWNER, &pProp);
    if(S_OK == hr)
    {
        ITfRange    *pPropRange;

        hr = pProp->FindRange(ec, pRange, &pPropRange, TF_ANCHOR_START);
        if(S_OK == hr)
        {
            VARIANT var;

            VariantInit(&var);
            hr = pProp->GetValue(ec, pPropRange, &var);
            if(S_OK == hr)
            {
                if(VT_I4 == var.vt)
                {
                    /*
                    var.lVal is a TfGuidAtom that represents the CLSID of the 
                    text owner. Use ITfCategoryMgr to obtain the CLSID from 
                    the TfGuidAtom.
                    */
                    ITfCategoryMgr  *pCatMgr;

                    hr = CoCreateInstance(  CLSID_TF_CategoryMgr,
                                            NULL, 
                                            CLSCTX_INPROC_SERVER, 
                                            IID_ITfCategoryMgr, 
                                            (LPVOID*)&pCatMgr);
                    if(SUCCEEDED(hr))
                    {
                        hr = pCatMgr->GetGUID((TfGuidAtom)var.lVal, pclsidOwner);
                        if(SUCCEEDED(hr))
                        {
                            /*
                            *pclsidOwner now contains the CLSID of the text 
                            service that owns the text at the selection.
                            */
                        }

                        pCatMgr->Release();
                    }
                }
                else
                {
                    //Unrecognized VARIANT type 
                    hr = E_FAIL;
                }
                
                VariantClear(&var);
            }
            
            pPropRange->Release();
        }
        
        pProp->Release();
    }

    return hr;
}

A tulajdonságok számba vehetők egy IEnumTfProperties felület ITfContext::EnumProperties.

Tulajdonságok állandó tárolása

A tulajdonságok gyakran transzparensek egy alkalmazás számára, és egy vagy több szöveges szolgáltatás használják. A tulajdonságadatok megőrzése érdekében , például egy fájlba való mentéskor az alkalmazásnak szerializálnia kell a tulajdonságadatokat a tároláskor, és az adatok visszaállításakor meg kell szüntetnie a tulajdonságadatok szerializálását. Ebben az esetben az alkalmazásnak nem kell érdekelnie az egyes tulajdonságokat, hanem számba kell vennie az összes tulajdonságot a környezetben, és tárolnia kell őket.

A tulajdonságadatok tárolásakor az alkalmazásnak végre kell hajtania a következő lépéseket.

  1. Szerezze be a tulajdonság-enumerátort ITfContext::EnumPropertiesmeghívásával.
  2. Az egyes tulajdonságok számbavétele IEnumTfProperties::Nextmeghívásával.
  3. Minden tulajdonsághoz szerezze be a tartomány-enumerátort ITfReadOnlyProperty::EnumRangesmeghívásával.
  4. A tulajdonság minden tartományának számbavétele IEnumTfRanges::Nextmeghívásával.
  5. A tulajdonság minden tartományához hívja meg az ITextStoreACPServices::Szerializálja a a tulajdonsággal, a tartománnyal, a TF_PERSISTENT_PROPERTY_HEADER_ACP struktúrával és az alkalmazás által implementált streamobjektummal.
  6. Írja be a TF_PERSISTENT_PROPERTY_HEADER_ACP szerkezet tartalmát az állandó memóriába.
  7. Írja be a streamobjektum tartalmát az állandó memóriába.
  8. Folytassa az összes tulajdonság összes tartományának előző lépéseit.
  9. Az alkalmazásnak valamilyen terminátort kell írnia a streambe, hogy az adatok visszaállításakor egy leállítási pont azonosítható legyen.
HRESULT SaveProperties( ITfContext *pContext, 
                        ITextStoreACPServices *pServices, 
                        TfEditCookie ec, 
                        IStream *pStream)
{
    HRESULT             hr;
    IEnumTfProperties   *pEnumProps;
    TF_PERSISTENT_PROPERTY_HEADER_ACP PropHeader;
    ULONG uWritten;
    
    //Enumerate the properties in the context. 
    hr = pContext->EnumProperties(&pEnumProps);
    if(SUCCEEDED(hr))
    {
        ITfProperty *pProp;
        ULONG       uFetched;

        while(SUCCEEDED(pEnumProps->Next(1, &pProp, &uFetched)) && uFetched)
        {
            //Enumerate all the ranges that contain the property. 
            IEnumTfRanges   *pEnumRanges;
            hr = pProp->EnumRanges(ec, &pEnumRanges, NULL);
            if(SUCCEEDED(hr))
            {
                IStream *pTempStream;

                //Create a temporary stream to write the property data to. 
                hr = CreateStreamOnHGlobal(NULL, TRUE, &pTempStream);
                if(SUCCEEDED(hr))
                {
                    ITfRange    *pRange;

                    while(SUCCEEDED(pEnumRanges->Next(1, &pRange, &uFetched)) && uFetched)
                    {
                        LARGE_INTEGER li;

                        //Reset the temporary stream pointer. 
                        li.QuadPart = 0;
                        pTempStream->Seek(li, STREAM_SEEK_SET, NULL);
                        
                        //Get the property header and data for the range. 
                        hr = pServices->Serialize(pProp, pRange, &PropHeader, pTempStream);

                        /*
                        Write the property header into the primary stream. 
                        The header also contains the size of the property 
                        data.
                        */
                        hr = pStream->Write(&PropHeader, sizeof(PropHeader), &uWritten);

                        //Reset the temporary stream pointer. 
                        li.QuadPart = 0;
                        pTempStream->Seek(li, STREAM_SEEK_SET, NULL);

                        //Copy the property data from the temporary stream into the primary stream. 
                        ULARGE_INTEGER  uli;
                        uli.QuadPart = PropHeader.cb;

                        hr = pTempStream->CopyTo(pStream, uli, NULL, NULL);

                        pRange->Release();
                    }
                    
                    pTempStream->Release();
                }
                
                pEnumRanges->Release();
            }
            
            pProp->Release();
        }
        
        pEnumProps->Release();
    }

    //Write a property header with zero size and guid into the stream as a terminator 
    ZeroMemory(&PropHeader, sizeof(PropHeader));
    hr = pStream->Write(&PropHeader, sizeof(PropHeader), &uWritten);

    return hr;
}

ITextStoreACPServices::SzerializáljaITfPropertyStore::Szerializálja

A tulajdonságadatok visszaállításakor az alkalmazásnak végre kell hajtania a következő lépéseket.

  1. Állítsa a streammutatót az első TF_PERSISTENT_PROPERTY_HEADER_ACP szerkezet elejére.

  2. Olvassa el a TF_PERSISTENT_PROPERTY_HEADER_ACP struktúrát.

  3. Hívja meg ITfContext::GetProperty a TF_PERSISTENT_PROPERTY_HEADER_ACP struktúra guidType tagjával.

  4. Az alkalmazás ezen a ponton két dolog egyikét teheti meg.

    1. Hozzon létre egy ITfPersistentPropertyLoaderACP-példányt objektumot, amelyet az alkalmazásnak implementálnia kell. Ezután hívja meg ITextStoreACPServices::Unserialize a pStreamNULL és az ITfPersistentPropertyLoaderACP mutatóval.
    2. Adja át a bemeneti adatfolyamot ITextStoreACPServices:: és NULLpLoader.

    Az első módszer előnyben részesített, mivel ez a leghatékonyabb. A második metódus implementálásával az összes tulajdonságadat beolvasható a streamből az ITextStoreACPServices::Unserialize hívás során. Az első módszer hatására a tulajdonságadatok később igény szerint beolvashatók.

  5. Ismételje meg az előző lépéseket, amíg az összes tulajdonságblokk nem lesz rendezve.

HRESULT LoadProperties( ITfContext *pContext, 
                        ITextStoreACPServices *pServices, 
                        IStream *pStream)
{
    HRESULT hr;
    ULONG   uRead;
    TF_PERSISTENT_PROPERTY_HEADER_ACP PropHeader;

    /*
    Read each property header and property data from the stream. The 
    list of properties is terminated by a TF_PERSISTENT_PROPERTY_HEADER_ACP 
    structure with a cb member of zero.
    */
    hr = pStream->Read(&PropHeader, sizeof(PropHeader), &uRead);
    while(  SUCCEEDED(hr) && 
            (sizeof(PropHeader) == uRead) && 
            (0 != PropHeader.cb))
    {
        ITfProperty *pProp;

        hr = pContext->GetProperty(PropHeader.guidType, &pProp);
        if(SUCCEEDED(hr))
        {
            /*
            Have TSF read the property data from the stream. This call 
            requests a read-only lock, so be sure it can be granted 
            or else this method will fail.
            */
            CTSFPersistentPropertyLoader *pLoader = new CTSFPersistentPropertyLoader(&PropHeader, pStream);
            hr = pServices->Unserialize(pProp, &PropHeader, NULL, pLoader);

            pProp->Release();
        }

        //Read the next header. 
        hr = pStream->Read(&PropHeader, sizeof(PropHeader), &uRead);
    }

    return hr;
}