Scintilla GetLineCount неверно, когда завернутый в слова

Я пытаюсь заменить встроенные полосы прокрутки сцинтиллы на пользовательские. У меня проблемы с настройкой Макса полосы прокрутки. Код Delphi для моей вертикальной полосы прокрутки:

ALScrollBar1.Max := ((Scintilla1.GetLineCount * Scintilla1.TextHeight(0)) -
Scintilla1.ClientHeight + ALScrollBar2.Height); 

Это прекрасно работает, если wordwrap выключен, но если он включен, GetLineCount не учитывает перенос слов. Счетчик строк в каком-то смысле остается тем же, но фактический видимый счетчик строк при переносе слов неверен (что касается информации о прокрутке). Я мог использовать такие вещи, как VisibleLineCount или EditRect или TopOffset в некоторых других элементах управления, чтобы достичь этого, но у сцинтиллы их нет.

Если кто-нибудь сталкивался с этим и нашел ответ, я бы наверняка хотел узнать!

Использование SCILexer.dll 4.1.0.0

Новая информация: (Примечание: моя цель при всем этом состояла в том, чтобы просто заменить стандартные полосы прокрутки ОС на те, которые имеют цвета, чтобы они визуально соответствовали моей форме и другим компонентам. Мне нравятся "темные" темы и ярко-серая (почти белая) ОС Полоса прокрутки выглядит ужасно. Также обратите внимание, что она прекрасно работает со стилями VCL, используя эту строку:

TStyleManager.Engine.RegisterStyleHook(DScintillaSRD.TSRDScintilla, TScrollingStyleHook);

Однако я не хотел использовать стили VCL в своем приложении.)

Я понял это (к моему удовлетворению в любом случае!), Поэтому я хотел добавить то, что нашел.

В основном я придумал 3 подхода к этому. Первым было добавление моей пользовательской полосы прокрутки (которая может иметь установленные цвета) к форме вместе с элементом управления, который я хочу прокрутить, а затем настройка связи между элементом управления и SB. Этот пользовательский компонент SB (компонент ALCINOE) не основан на обычном TScrollBar, поэтому вы не можете просто передать ему scrollinfo (который все равно не будет работать, если вы "отключите" системные полосы прокрутки элемента управления, чтобы "скрыть" их). Я мог делать это много раз, пока у элемента управления есть свойства TopOffset или YOffset и LeftOffset или XOffset (PlusMemo, VirtualStringTree, ScrollBox, ListBox). Проблема, с которой я столкнулся, заключается в том, что в элементе управления Scintilla доступно только смещение X. Я близко подошел к этому методу, но всегда возникает одна вещь - все элементы прокрутки должны быть очень точными (позиции, размер большого пальца и т. Д.). Вы можете сделать это с некоторой "отстойностью" (именно так этот метод работал), но всегда старательно полагаться на него.

Следующим подходом было создание небольшого окна (TWinControl), чтобы "накрыть" системные SB элемента управления, а затем добавить TScrollBar в это окно. Поскольку это TScrollBar, вы можете передавать scrollinfo назад и вперед между SB и элементом управления. С помощью этой настройки вы, наконец, можете использовать сообщение TWMCtlColorScrollbar, чтобы закрасить фон (ТОЛЬКО) TScrollBar (мне никогда не удавалось заставить это сообщение работать напрямую со Scintilla). Это лучше, чем полностью светло-серый SB, но только фон приобретает цвет, а кнопки большого пальца и стрелки остаются серыми, поэтому он не идеален. Это было, однако, очень точно с точки зрения позиций, прокрутки и т. Д.

Последний подход состоял в том, чтобы использовать маленькое окно "обложки", чтобы скрыть панели ОС и добавить пользовательский SB (ALCINOE) в это окно, как я это сделал с TScrollBar. Проблема, с которой я столкнулся (опять же), заключалась в том, что позиции большого и прокручиваемого дисков по-прежнему были "выключены", хотя я мог взять скроллинфо из элемента управления Scintilla (так что я знал, что размер моего большого пальца, номера MAX и POS были мертвыми). Делать это таким образом было очень точно с TScrollBar, поэтому я знал, что чего-то не хватает в моем коде прокрутки. Я наконец понял, что это были данные PAGE, которые мне нужны. Итак, в коде для позиционирования СБ от элемента управления вместо:

ALVScrollBar.Max := SInfo.nMax;

Мне нужно было использовать:

ALVScrollBar.Max := SInfo.nMax - integer(SInfo.nPage);

Чтобы пользовательский SB имел всю информацию, необходимую для точного позиционирования (я также извлекаю номера MIN и POS из scrollinfo). Код прокрутки для пользовательского VERT SB:

sinfo.cbSize := SizeOf(sinfo);
SInfo.fMask := SIF_ALL;
//Control is the Scintilla control:
GetScrollInfo(Control.Handle, SB_VERT, SInfo);

if SInfo.nPos > ScrollPos then
    i := -((SInfo.nPos - ScrollPos))
else
    i := (ScrollPos - SInfo.nPos) ;

SendMessage(Control.Handle, EM_LINESCROLL, 0 , i);

И код для пользовательского HORZ SB просто:

TSRDScintilla(Control).SetXOffset(ScrollPos);

Конечно, вы должны делать различные вещи, такие как обновление управления и SB в нужное время, и другие вспомогательные вещи, но все это работает сейчас и является точным с точки зрения позиционирования и прокрутки, с или без переноса слов, с аннотациями Scintilla или без них, в любой размер шрифта.

Скриншот пользовательских SB

0 ответов

Другие вопросы по тегам