Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Компоненты Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.09.2020, 09:23   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию как правильно подобрать размер scrollbar'а?

Здравствуйте.
вот код:
Код:
procedure TForm1.SortElements; //выполняется при ресайзе окна и теребонькании скроллбара
const
  gap = 0;
var
  i,n,xStart,x,y, PerRow, RowsCount : Integer;
begin
  PerRow := Trunc(pnl1.Width / (cubeWidth + gap));
  if PerRow = 0 then
  PerRow := 1;
  if count mod PerRow = 0 then
  RowsCount := trunc(count / PerRow) else
  RowsCount := trunc(count / PerRow) + 1;
  xStart := Round((pnl1.Width div 2) - (((cubeWidth + gap) * PerRow) div 2));
  x := xStart;
  y := -cubeHeight - gap;
  for i := 0 to count - 1 do
  begin
    if i mod PerRow = 0 then
    begin
      inc(y, cubeHeight + gap);
      x := xStart;
    end;
    ar[i].Top := y - sb.Position; //sb - TScrollBar
    ar[i].Left := x;
    inc(x, cubeWidth + gap);
  end;

  i := cubeHeight * RowsCount - pnl1.Height;
  if i > sb.PageSize then
  sb.Max := I else
  sb.Max := sb.PageSize;
end;
вот результат: https://www.youtube.com/watch?v=ZVlnouuTjsY
Не знаю, как словами это описывать. Всё должно быть понятно из видео.
Как это исправить?
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.09.2020, 10:46   #2
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 947
По умолчанию

BLACK_RAIN,

словами так:

знаем размеры фрейма (окошко просмотра)
знаем размеры всего объекта (по нему ползает фрейм)

(описание для одной координаты. По второй - всё так же)
если длина объекта вся влазит во фрейм, полоску скрываем
если не влазит, то: узнаём длину скрытой части - её и будем скроллить (0% - объект с фреймом совмещены координатой 0, а 100% - совмещены максимальной координатой)

минимум и максимум скролбара удобно делать всегда 0 и 100 (эквивалент процентов прокрутки). Разве что разрешение экрана настолько дико большое, что эта дискретность не устраивает, тогда вариант 0...1000 и так далее
Алексей1153 вне форума Ответить с цитированием
Старый 24.09.2020, 10:56   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
если не влазит, то: узнаём длину скрытой части - её и будем скроллить
не понял
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.09.2020, 11:00   #4
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 947
По умолчанию

BLACK_RAIN, нарисуй на бумаге - поймёшь

или даже вырежь из бумаги эти окошки и подвигай друг над другом, если представить мысленно сложно. Скроллится именно скрытая часть объекта. Если скрытой части нет - скроллить ничего не требуется
Алексей1153 вне форума Ответить с цитированием
Старый 24.09.2020, 11:15   #5
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

если какая-то панелька не желает "целиком влезать на форму" я обычно пользую Scrollbox.

ScrollBar заменить TScrollbox (у него уже есть ScrollBar)
рабочую панель поместить на на этот ScrollBox
размеры рабочей панели задать необходимо(не больше) и достаточно(но и не меньше) для отображения всех имеющихся на ДАННЫЙ момент ее компонентов.

1. меняем размеры окна(Resize) --> подстраиваем размеры Scrollbox
2. меняем заполнения рабочей панели -->подстраиваем ее размеры.

а ScrollBox в обоих случаях настраиваем СВОИ scrollbar's как ему нужно.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 24.09.2020, 11:22   #6
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
минимум и максимум скролбара удобно делать всегда 0 и 100 (эквивалент процентов прокрутки).
А если прокручиваемый список слишком большой? Тогда при шаге даже в 1% будет пропущено дофига элементов.

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
нарисуй на бумаге
Несколько лет назад я писал скроллбар на WinAPI и никаких особых проблем не возникло. Всё крутилось и отображалось нормально. Ничего на бумаге не рисовал.
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.09.2020, 11:35   #7
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
ScrollBar заменить TScrollbox
Работает.
Но прокрутка не обновляется, пока не отпустишь скроллбар. Это плохо.

Последний раз редактировалось BLACK_RAIN; 24.09.2020 в 11:48.
BLACK_RAIN вне форума Ответить с цитированием
Старый 24.09.2020, 11:46   #8
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 947
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
А если прокручиваемый список слишком большой
перемещением ползунка в этом случае всё равно не поможешь. Если количество строк не поддерживается скроллбаром, то индекс верхней отображаемой строки нужно будет контролировать "вручную" и синхронизировать с отображением на скроллбаре.

В Qt для этого используется технология модель-представление, можно идею оттуда содрать
Алексей1153 вне форума Ответить с цитированием
Старый 24.09.2020, 11:53   #9
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
перемещением ползунка в этом случае всё равно не поможешь. Если количество строк не поддерживается скроллбаром, то индекс верхней отображаемой строки нужно будет контролировать "вручную" и синхронизировать с отображением на скроллбаре.

В Qt для этого используется технология модель-представление, можно идею оттуда содрать
На WinAPI скроллбар работает как надо. При том, что я даже не особо старался и код там корявый.
И прокручиваемый диапазон там огромный.

Последний раз редактировалось BLACK_RAIN; 24.09.2020 в 11:55.
BLACK_RAIN вне форума Ответить с цитированием
Старый 25.09.2020, 11:44   #10
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Переписал программу на WinAPI
Код:
procedure SortBlocks;
const
  gap = 4;
var
  i,n,xStart,x,y, PerRow, RowsCount,
  BlocksCount, ScrollbarPos : Integer;
  r : TRect;
  si : TScrollInfo;
begin
  if GetClientRect(hPanelRender, r) then
  begin
    BlocksCount := Length(Blocks);
    PerRow := Trunc(r.Width / (BLOCK_SIZE_X + gap));
    if PerRow = 0 then
    PerRow := 1;
    if BlocksCount mod PerRow = 0 then
    RowsCount := trunc(BlocksCount / PerRow) else
    RowsCount := trunc(BlocksCount / PerRow) + 1;
    xStart := Round((r.Width div 2) - (((BLOCK_SIZE_X + gap) * PerRow) div 2));
    x := xStart;
    y := -BLOCK_SIZE_Y - gap;
    for i := 0 to BlocksCount - 1 do
    begin
      if i mod PerRow = 0 then
      begin
        inc(y, BLOCK_SIZE_Y + gap);
        x := xStart;
      end;
      ScrollbarPos := SendMessage(hScrollBar, SBM_GETPOS, 0,0);

      Blocks[i].PositionY := y - ScrollbarPos;
      Blocks[i].PositionX := x;
      inc(x, BLOCK_SIZE_X + gap);
    end;

    ZeroMemory(@si, SizeOf(TScrollInfo));
    si.cbSize := SizeOf(TScrollInfo);
    si.nMax := RowsCount * (BLOCK_SIZE_Y + gap);
    si.nPage := r.Bottom;
    si.fMask := SIF_RANGE or SIF_PAGE;
    SendMessage(hScrollBar, SBM_SETSCROLLINFO, 0, lparam(@si));
  end;
end;

    WM_SIZE:
    begin
      w := loword(Lpar);
      h := HiWord(Lpar);
      SetWindowPos(hPanelRender, 0, 0,0, w - 20, h, SWP_NOZORDER or SWP_NOMOVE);
      SetWindowPos(hScrollBar, 0, w - 20, 0, 20, h, SWP_NOZORDER);
      SortBlocks;
    end;

    WM_VSCROLL:
    if Lpar = hScrollbar then
    begin
      case loword(Wpar) of

        SB_LINEDOWN:
        begin
          si.cbSize := SizeOf(TScrollInfo);
          si.fMask := SIF_POS or SIF_RANGE;
          SendMessage(hScrollBar, SBM_GETSCROLLINFO,0, lparam(@si));
          si.nPos := si.nPos + 10;
          si.fMask := SIF_POS;

          SendMessage(hScrollBar, SBM_SETSCROLLINFO, 0, lparam(@si));

          SortBlocks;
          InvalidateRect(wnd, nil, False);
        end;

        SB_LINEUP:
        begin
          si.cbSize := SizeOf(TScrollInfo);
          si.fMask := SIF_POS;
          SendMessage(hScrollBar, SBM_GETSCROLLINFO, 0, lparam(@si));
          si.nPos := si.nPos - 10;
          if si.nPos < 0 then
          si.nPos := 0;
          SendMessage(hScrollBar, SBM_SETSCROLLINFO, 0, lparam(@si));

          SortBlocks;
          InvalidateRect(wnd, nil, False);
        end;

        SB_PAGEDOWN:
        begin
          if GetClientRect(hPanelRender, r) then
          begin
            si.cbSize := SizeOf(TScrollInfo);
            si.fMask := SIF_POS;
            SendMessage(hScrollBar, SBM_GETSCROLLINFO, 0, lparam(@si));
            si.nPos := si.nPos + r.Bottom;
            SendMessage(hScrollBar, SBM_SETSCROLLINFO, 0, lparam(@si));

            SortBlocks;
            InvalidateRect(wnd, nil, False);
          end;
        end;

        SB_PAGEUP:
        begin
          if GetClientRect(hPanelRender, r) then
          begin
            si.cbSize := SizeOf(TScrollInfo);
            si.fMask := SIF_POS;
            SendMessage(hScrollBar, SBM_GETSCROLLINFO, 0, lparam(@si));
            si.nPos := si.nPos - r.Bottom;
            if si.nPos < 0 then
            si.nPos := 0;
            SendMessage(hScrollBar, SBM_SETSCROLLINFO, 0, lparam(@si));

            SortBlocks;
            InvalidateRect(wnd, nil, False);
          end;
        end;

        SB_THUMBTRACK:
        begin
          si.cbSize := SizeOf(TScrollInfo);
          si.fMask := SIF_TRACKPOS;
          SendMessage(hScrollBar, SBM_GETSCROLLINFO, 0, lparam(@si));
          SendMessage(hScrollBar, SBM_SETPOS, si.nTrackPos, 0);
          SortBlocks;
          InvalidateRect(wnd, nil, False);
        end;
      end;
    end;

    WM_CREATE:
    begin
      hPanelRender := CreateWindow('Static', nil, WS_CHILD or WS_VISIBLE or SS_BITMAP,
                              0,0,0,0, wnd, 0, HInstance, nil);
      hScrollBar := CreateWindow('Scrollbar', nil, WS_CHILD or WS_VISIBLE or SBS_VERT,
                              0,0,0,0, wnd, 0, HInstance, nil);
      Randomize;
      SetLength(Blocks, 21);
      for I := 0 to 20 do
      begin
        Blocks[i].PositionX := 0;
        Blocks[i].PositionY := i * BLOCK_SIZE_Y;
        Blocks[i].Color := RGB(Random(255), Random(255), Random(255));
      end;
    end;
В поле nPage просто передаем размер видимой области и всё работает.
А в TScrollBar что надо сделать, чтобы заработало?
BLACK_RAIN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не знаю как правильно сделать задания. Питон Kirkkki Помощь студентам 1 17.09.2020 01:13
Как это делать? АндрейН C# (си шарп) 1 14.09.2020 18:36
Как правильно подобрать жесткий диск? Shved77 Компьютерное железо 23 24.02.2010 14:33
Как изменить размер выделеного текста в twebbrowser правильно pervii Мультимедиа в Delphi 0 08.02.2010 09:09
Как правильно задать размер TextBox-a? Diego__ Microsoft Office Word 3 02.09.2009 11:27