property BookmarkFrom[Handle: FPDF_BOOKMARK]: TBookmark; // read only
BookmarkFrom — мост между низкоуровневым обходом закладок PDFium и высокоуровневой записью TBookmark. Когда дескриптор FPDF_BOOKMARK попадает к вам напрямую из PDFium (например, через FPDFBookmark_GetFirstChild, FPDFBookmark_GetNextSibling или в составе click hit-test во вьювере), прогоните его через этот индексатор и получите разрешённый текст заголовка, целевой PageNumber, вид TPdfAction и ассоциированный URI / путь к файлу
Возвращаемая запись — снимок: словарь закладки читается один раз, а назначение декодируется в номер страницы с единицы. Сам дескриптор тоже сохраняется в записи, так что его можно передать обратно в API PDFium без повторного обхода дерева
Этот индексатор — канонический способ написать собственный обход outline с большим контролем, чем Bookmarks (перечисляет всё в глубину) или BookmarkChildren (возвращает только прямых детей). Смешивайте сырые дескрипторы PDFium с разрешением через BookmarkFrom, чтобы собрать, к примеру, tree view с ленивой загрузкой
| Handle | FPDF_BOOKMARK. Не-nil дескриптор закладки, полученный из C API PDFium или из поля TBookmark.Handle предыдущей записи. При nil возвращается запись, заполненная нулями. Дескриптор остаётся валидным, только пока базовый документ загружен |
TBookmark — не вызывайте на нём функции освобождения PDFium. PDFium сам освобождает дескрипторы outline при закрытии документаAction использует тот же enum TPdfAction, что Bookmark и LinkAnnotation, поэтому один код-диспетчер может маршрутизировать клики и по записям outline, и по link-аннотациямPageNumber выдаётся как 0. Используйте HasBookmarkChildren, чтобы решить, разворачивать узел или переходить
procedure TForm1.DumpOutline(const Bm: TBookmark; Depth: Integer);
var
Child: FPDF_BOOKMARK;
Sub: TBookmark;
begin
Memo1.Lines.Add(StringOfChar(' ', Depth * 2) + Bm.Title +
Format(' -> page %d', [Bm.ActionPageNumber]));
Child := FPDFBookmark_GetFirstChild(Pdf1.Document, Bm.Handle);
while Child <> nil do
begin
Sub := Pdf1.BookmarkFrom[Child];
DumpOutline(Sub, Depth + 1);
Child := FPDFBookmark_GetNextSibling(Pdf1.Document, Child);
end;
end;