範囲
アンカー
範囲は、開始アンカーと終了アンカー 2 つのアンカーで区切られます。 アンカーは、2 文字の間の虚数スロットに存在します。 開始アンカーはアンカーの後のテキストに関連し、終了アンカーはアンカーの前にあるテキストに関連します。 開始アンカーと終了アンカーはどちらも同じ場所に存在できます。 この場合、範囲の長さは 0 です。
たとえば、次のテキストから始めます。
This is text.
次に、開始アンカーと終了アンカーの両方を位置 0 に設定して、このテキストに範囲を適用します。 視覚的には次のように表されます。
<anchor></anchor>This is text.
アンカーは、テキスト自体内のスペースを占有しません。 これは長さ 0 の範囲であり、そのテキストは空です。
次に、終了アンカーを +3 位置にシフトします。 視覚的には次のように表されます。
<anchor>Thi</anchor>s is text.
開始アンカーは位置 0 の文字の直前に配置され、終了アンカーは位置 3 の文字の直後に配置されます。これは、終了アンカーが右の 3 桁に移動したためです。 テキストの範囲が "Thi" になりました。
さらに、開始アンカーを終了アンカーの後に置くことができず、開始アンカーの前に終了アンカーを作成することはできません。
アンカー重力
各アンカーには 重力 設定があり、アンカー位置でテキストがテキスト ストリームに挿入されたときにアンカーがどのように応答するかを決定します。 アンカーの位置で挿入を行う場合は、アンカーの位置で調整を行う必要があります。 重力によって、このアンカー位置の調整方法が決まります。
例えば:
It is <anchor></anchor>cold today.
"very" という単語が範囲の位置に挿入されている場合、開始アンカーは挿入された単語の前または後に配置できます。
It is <anchor>very </anchor>cold today.
-又は-
It is very <anchor></anchor>cold today.
アンカーの重力は、カーソルが位置で行われるときにアンカーの位置を変更する方法を指定します。 重力は、後方 することも、前方 することもできます。
アンカーに後方重力がある場合、アンカーは挿入時にカーソルを基準にして後方に移動し、挿入されたテキストがアンカーの後に移動します。
It is <anchor>very </anchor>cold today.
アンカーが前方重力を持つ場合、アンカーは挿入時に (カーソルを基準として) 前方に移動し、挿入されたテキストがアンカーの前に配置されるようにします。
It is very <anchor></anchor>cold today.
複製とバックアップ
範囲オブジェクトの "コピー" を作成するには、2 つの方法があります。 1 つ目は、ITfRange::Cloneを使用して、範囲の 複製 を作成することです。 2 つ目は、ITfContext::CreateRangeBackupを使用して、範囲の バックアップ を作成することです。
複製は、静的データを含まない範囲のコピーです。 範囲のアンカーはコピーされますが、複製はコンテキスト内のテキストの範囲をカバーします。 クローンは、あらゆる点で範囲オブジェクトです。 つまり、複製範囲のテキストとプロパティは動的であり、複製の対象範囲のテキストやプロパティが変更されると変更されます。
バックアップでは、バックアップが静的データとして作成されるときに、範囲のテキストとプロパティが格納されます。 バックアップでは、元の範囲のサイズと位置の変更を追跡できるように、元の範囲も複製されます。 つまり、バックアップ範囲のテキストとプロパティは静的であり、バックアップ対象範囲のテキストやプロパティが変更されても変更されません。
たとえば、コンテキスト内の次の範囲 (pRange) です。
"This is some <pRange>text</pRange>."
次に、この範囲の複製とバックアップを作成します。
ITfRange *pClone;
ITfRangeBackup *pBackup;
pRange->Clone(&pClone);
pContext->CreateRangeBackup(ec, pRange, &pBackup);
これで、オブジェクトには次のものが含まれます。
pRange = "text"
pClone = "text"
pBackup = "text"
次に、pRange のテキストを変更します。
WCHAR wsz[] = L"other words";
pRange->SetText(ec, 0, wsz, lstrlenW(wsz));
これで、オブジェクトには次のものが含まれます。
Context = "This is some other words."
pRange = "other words"
pClone = "other words"
pBackup = "text"
テキストを設定すると、コンテキスト内のテキストが変更されます。 また、pRange と pClone の終了アンカーも変更されます。 範囲内でテキストが変更され、これらの変更はすべての範囲で追跡されるため、pClone に "他の単語" が含まれるようになりました。 pRange と pClone の両方でカバーされるテキストが変更されると、pClone のテキストも変更されました。
バックアップのデータ (テキストとプロパティ) はコンテキストとは無関係であり、個別に格納されるため、pBackup のテキストは元の pRange から変更されていません。 バックアップに含まれる複製は実際には変更されますが、データは静的です。
バックアップを復元する場合、バックアップはバックアップ内の複製に適用することも、別の範囲に完全に適用することもできます。 バックアップ内の複製にバックアップを適用するには、次のコード例に示すように、NULL を ITfRangeBackup::Restore に渡します。
pBackup->Restore(ec, NULL);
これで、オブジェクトには次のものが含まれます。
Context = "This is some text."
pRange = "text"
pClone = "text"
pBackup = "text"
バックアップを別の範囲に復元するには、ITfRangeBackup::Restore 呼び出すときに範囲オブジェクトへのポインターを渡します。 バックアップされたテキストとプロパティが新しい範囲に適用されます。 たとえば、Restore 呼び出しの前に上記の例を使用すると、これを示すために pRange が変更されます。
LONG lShifted;
pRange->ShiftEnd(ec, -2, &lShifted, NULL);
これで、オブジェクトには次のものが含まれます。
Context = "This is some other words."
pRange = "other wor"
pClone = "other words"
pBackup = "text"
pRange の終了アンカーが左の 2 か所にシフトされたとき、pClone の終了アンカーは変更されませんでした。
次のコード例で pRange を使用してバックアップを復元します。
pBackup->Restore(ec, pRange);
これで、オブジェクトには次のものが含まれます。
Context = "This is some textds."
pRange = "text"
pClone = "textds"
pBackup = "text"
pRange の対象となるテキストが "text" に置き換えられ、pClone でカバーされるテキストの一部が変更され、pRange と一致するように pBackup が変更されました。