StringGrid постраничное перелистывание за скроллер

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

StringGrid постраничное перелистывание за скроллер

Сообщение vitaly_l » 21.12.2016 21:18:32

Всем хорошего настроения!

Код: Выделить всё

procedure TForm1.StringGrid1MouseWheelDown(Sender: TObject;
  Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
StringGrid1.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);
Handled := True;
end;

procedure TForm1.StringGrid1MouseWheelUp(Sender: TObject;
  Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
StringGrid1.Perform(WM_VSCROLL, SB_PAGEUP, 0);
Handled := True;
end;




Вышеприведённый код, постранично скролит StringGrid1.
Если скролить колёсиком мышки := всё чудесно работает.

:arrow: ПРОБЛЕМА:
:!: если потянуть за скролеер (а не крутить колёсиком мышки), то постраничное перелистывание сбивается.
:| Может сбиться на строчку, а может на пол строчки. :oops: :( :cry:
:?: Как постранично скролить, перемещая grid за скроллер?


Добавлено спустя 88 минут 88 секунд:
Код: Выделить всё
TScrollCode = (
    // !!! Beware. The position of these enums must correspond to the SB_xxx
    // values in LCLType  (Delphi compatibility, not our decision)
    // MWE: Don't know it this still is a requirement
    //      afaik have I remeved all casts from the LCL
    scLineUp,   // = SB_LINEUP
    scLineDown, // = SB_LINEDOWN
    scPageUp,   // = SB_PAGEUP
    scPageDown, // = SB_PAGEDOWN
    scPosition, // = SB_THUMBPOSITION
    scTrack,    // = SB_THUMBTRACK
    scTop,      // = SB_TOP
    scBottom,   // = SB_BOTTOM
    scEndScroll // = SB_ENDSCROLL
    );   


Выше код из исходников лазаруса ( StdCtrls ). Возможность постраничного перелистывания туда заложена.
Но не могу понять: :?: где мне задать ему TScrollCode := scPageUp and scPageDown, для пролистывания за скроллер ?



Заранее всем спасибо!
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: StringGrid постраничное перелистывание за скроллер

Сообщение olegy123 » 22.12.2016 02:21:20

TScrollCode часть оконных сообщений WM_VSCROLL и WM_HSCROLL

var Mes: TWMScroll;
mes.Msg := WM_VSCROLL;
mes.ScrollCode := SB_Right;
mes.Pos := 0;
StringGrid1.Dispatch(mes);

ну и функции
GetScrollRange(StringGrid1.Handle,SB_VERT,vMin,vMax); возращает vMin,vMax значение;
vPos := GetScrollPos(StringGrid1.Handle,SB_VERT); - возращает vPos
SetScrollPos(StringGrid1.Handle,WM_VSCROLL, vPos, True); перейти на vPos

я точно не понял в чем проблема, но для гибкости проще преопределить сообщения:
procedure WMHScroll(var message : TLMHScroll); message LM_HSCROLL;
procedure WMVScroll(var message : TLMVScroll); message LM_VSCROLL;
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: StringGrid постраничное перелистывание за скроллер

Сообщение vitaly_l » 22.12.2016 08:40:16

olegy123 писал(а):я точно не понял в чем проблема,

:arrow: Если установить:
StringGrid1.Perform(WM_VSCROLL, SB_PAGEUP, 0);
StringGrid1.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);

то при прокрутке КОЛЁСИКОМ, программа прокручивает грид ПОСТРАНИЧНО.

:cry: Однако, при скроллинге за скроллер, ПОСТРАНИЧНОЕ перемещение ломается и получается некрасиво
( обрезается пол строки, а страницы начинают "скакать" даже при скроллинге за колёсико, т.к. сбилось ПОСТРАНИЧНОЕ перемещение
из-за отсутствия в моём коде, команды, ПОСТРАНИЧНОГО перемещения за скроллер. При этом при перемещении КОЛЁСИКОМ - всё работает. ).

:?: Как ПОСТРАНИЧНО скролить, перемещая grid за СКРОЛЛЕР? :|
PS: Точнее я уже написал костыль, который после перемещения ставит скроллер в нужное положение на onMouseEnter и всё работает. <== Но это костыль, а есть СИСТЕМНАЯ функция. :?: Как активировать системную функцию ПОСТРАНИЧНОГО перелистывания StringGrid за скроллер ?

Добавлено спустя 88 минут 88 секунд:
По сути нужно установить, у StringGrid: ШАГ ПЕРЕМЕЩЕНИЯ СКРОЛЛЕРА - равный одной странице.
Как это делается? ( Должна быть: какая-то системная команда, т.к. для колёсика она уже существует. )

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: StringGrid постраничное перелистывание за скроллер

Сообщение olegy123 » 23.12.2016 22:17:34

Я не большой специалист по скролбарам, но примерах в системных окнах (TWinControl) скролбар не имеет шага. его поведения нужно предопределять
посмотрите на код в grids.pas где в классе TCustomGrid (TStringGrid -> TCustomStringGrid -> TCustomDrawGrid -> TCustomGrid) описана процедура обработки сигналов со скроллбаров
procedure WMVScroll(var message : TLMVScroll); message LM_VSCROLL;

там кстати есть обработка этих сообщений:
StringGrid1.Perform(WM_VSCROLL, SB_PAGEUP, 0);
StringGrid1.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);

если не хотите создовать свой класс от TStringGrid с предопределенным ..message LM_VSCROLL;
можно решить задачу через TScrollBar, он имеет шаг ползунка (LargeChange/SmallChange).
Им можно сэмулировать системный ScrollBar -> StringGrid.. справа ScrollBar, а родной прячем ScrollBars:=ssNone,
в событиях OnScroll у ScrollBar можно уже давать
либо позиционировать StringGrid на заданную строку (наверное TopRow?)
или использовать те же:
StringGrid.Perform(WM_VSCROLL, SB_PAGEUP, 0);
StringGrid1.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: StringGrid постраничное перелистывание за скроллер

Сообщение vitaly_l » 23.12.2016 22:33:30

olegy123 писал(а):там кстати есть обработка этих сообщений:
StringGrid1.Perform(WM_VSCROLL, SB_PAGEUP, 0);
StringGrid1.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);

Вот именно что там есть!!! Да, верно оно там заложено. Но как его активировать?

Вы сами привели пример: GetScrollRange(StringGrid1.Handle,SB_VERT,vMin,vMax);
Из этого примера следует, что существует СИСТЕМНАЯ функция, которую нужно вызвать и заложить туда SB_PAGEUP и SB_PAGEDOWN.

Возможно кто-то уже сталкивался и\или знает ответ, вот я и спросил. Как перелистывать постранично за скроллер?

olegy123 писал(а):можно решить задачу через TScrollBar, он имеет шаг ползунка (LargeChange/SmallChange).
Им можно сэмулировать системный ScrollBar -> StringGrid.. справа ScrollBar, а родной прячем ScrollBars:=ssNone,

Это, реальное решение, я над ним давно задумался, но всё ещё тешу себя надеждой, что есть готовая системная функция,
потому что, для колёсика, она есть. Значит и для скроллера должна быть.

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: StringGrid постраничное перелистывание за скроллер

Сообщение olegy123 » 23.12.2016 22:53:05

vitaly_l писал(а):Вот именно что там есть!!! Да, верно оно там заложено. Но как его активировать?

созданием своего компонента:

TMyStringGrid = class (TStringGrid)
protected
procedure WMVScroll(var message : TLMVScroll); message LM_VSCROLL;
end;

procedure TMyStringGrid.WMVScroll(var message: TLMVScroll);
...
end;

- уже этого достаточно чтобы он умел правильно скролить.
можно разместить на панели контроллов и использовать везде где надо.
но надо зарегистрировать его.

Добавлено спустя 5 минут 4 секунды:
vitaly_l писал(а):Это, реальное решение, я над ним давно задумался, но всё ещё тешу себя надеждой, что есть готовая системная функция,
потому что, для колёсика, она есть. Значит и для скроллера должна быть.

для новичков так проще.
но точно также делают сложные компоненты - составные из нескольких элементов : как пример TDBNavigator
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: StringGrid постраничное перелистывание за скроллер

Сообщение Лекс Айрин » 24.12.2016 10:43:36

vitaly_l писал(а):Как перелистывать постранично за скроллер?


А чем не устраивает щелчок не на модификаторе(кнопке), а на самом ползунке? Лично я так делаю даже чаще чем колесиком. Причем, это системное поведение.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12

Рейтинг@Mail.ru