範囲
アンカー
範囲は、開始アンカーと終了 アンカーの 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 を呼び出すときに範囲オブジェクトへのポインターを渡します。 バックアップされたテキストとプロパティが新しい範囲に適用されます。 たとえば、 復元 呼び出しの前に上記の例を使用すると、これを示すために 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 が変更されました。