Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ScrollBox - видимая область


BMouradov ©   (2006-04-14 20:23:00) 

Как узнать координаты прямоугольника, отображаемого в данный момент в ScrollBox-е? Что-нибудь вроде sb.Canvas.ClipRect есть?


Barloggg   (2006-05-22 10:41:00) [1]

проект? не вопрос.
но словами короче:
берем ScrollBox.
ложим в него чего-нибудь. например панель.

в сторонке ложим две кнопки.
по клику первой увеличиваем панель в несколько раз.
по клику второй - уменьшаем.

Как работает.
кликаем первую кнопку. потом сдвигаем ползунки на scrollbox.
кликаем вторую кнопку. и потом пытаемся вернуть все на место...

О! а вот и проект подоспел. Высылаю.

Кстати обнаружил один неприятный эффект. Панель - то лежит произвольно в центре ScrollBox. А как только начинается движение ползунка - панель прыгает к левой стенке Scrollbox.


ECM   (2006-05-18 17:31:00) [2]

Я тут еще посмотрел на код - возможно его можно будет поправить
(в последней версии KOL в этом месте мои исправления). Если не сложно
сделайте простенький проект где этот эффект проявляется (я бы и сам, но у меня со временем пока неочень) - и мне в мыло (анкета)


Barloggg   (2006-05-18 16:28:00) [3]

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

> "более гибкое"

скорее уж более кодоэкономичное...чем гибкое.
надеюсь Владимир упомянет об этом в книжке-справочнике по KOL.


ECM   (2006-05-18 15:24:00) [4]


> надо их возвращать ручками

...

> После этого уменьшаю PaintBox до первоначального размера

Это же вы тоже делаете "ручками" ? Вот и одновременно возвращайте куда Вам нравится - можно в ноль а можно и пересчитать через разницу масштабов... ИМХО такое поведение ScrollBox - "более гибкое" чем автоматическая перестройка. Да и код надо экономить - KOL всё-таки :)


Barloggg   (2006-05-18 14:25:00) [5]

О!!! я понял. оказывается все детки сдвигаются в глубоко отрицательную сторону и надо их возвращать ручками.... надо же... в VCL кажись детки сами возвращались на первоначальное место...


Barloggg   (2006-05-18 14:17:00) [6]

Еще вопрос.
Есть ScrollBox на нем лежит PaintBox.

PaintBox маленький - полос прокрутки нету.
Увеличиваю PaintBox - полосы прокрутки появляются.
Двигаю ползунки чтобы рассмотреть нижнюю часть PaintBox.
После этого уменьшаю PaintBox до первоначального размера - полосы прокрутки исчезают на PaintBox так и остается за краями кадра. И как его возвращать обратно???


BMouradov   (2006-04-19 14:31:00) [7]

Всем спасибо! Буду пробовать.


ECM   (2006-04-18 18:57:00) [8]


> 40000х40000 пикселов? Огогошеньки. Никаких гигагерцев не
> хватит. Частями надо перерисовывать, все-таки. Хотя бы по
> квадратам, которые в область попали или пересеклись.

Это, да... :)

> Иначе (|).

Я бы даже сказал  (__|__)  !

В свое время /* ух ты а ведь это было уже 10 лет назад :(  */ - чтобы отображать такую массу пикселов я разбивал предварительно изображение по квадратам 400x600 в отдельные пронумерованные bmp-шки. И делал их динамичекую подкачку в память - так чтобы в памяти сидели только реально отображаемые куски.


Vladimir Kladov   (2006-04-18 18:00:00) [9]

Пардон, не тоак прочитал. Решил, что вообще все перерисовывается, а не видимая часть. :)


Vladimir Kladov   (2006-04-18 17:51:00) [10]

40000х40000 пикселов? Огогошеньки. Никаких гигагерцев не хватит. Частями надо перерисовывать, все-таки. Хотя бы по квадратам, которые в область попали или пересеклись. Иначе (|).


ECM   (2006-04-18 17:06:00) [11]

Накладно буферировать видимую часть?!!!
Это у Вас за конфигурация системы такая слабая?
Я при отображении карты (города, области и т.д - неважно) так и делаю - и не считаю это накладным (Windows все равно создает буфер в памяти для окна - ну и пускай их будет два!).
....
Попробуйте повозится с GetClipBox в OnPaint(или там где у Вас идет отрисовка)


BMouradov   (2006-04-18 16:46:00) [12]

Пример - карта города. Держать весь рисунок (или даже только видимую его часть) в памяти, чтобы быстро отрисовывать - накладно по памяти, полностью каждый раз рисовать - тормозит :(


BMouradov   (2006-04-18 16:20:00) [13]

ECM и Кладову: спасибо, R2 - это именно то, что нужно.

Однако второй вопрос остался - не всегда нужно перерисовывать всю область компонента, "видимую" через Scrollbox. Например, если чужое окно лишь частично перекрывало Ваше, либо при скроллировании, либо сам ScrollBox не полностью виден на экране. Нет ли стандартных способов узнать ту область, которую надо именно сейчас перерисовать, или лучше всегда полностью отрисовывать?


ECM   (2006-04-17 16:07:00) [14]


> Иногда проще дать практический совет, чем разводить теорию

Иногда знание теории дает лучший результат :))

 R  := ScrollBox1.ClientRect;
 R1 := PaintBox1.BoundsRect;
 R2.Left := -R1.Left;
 R2.Top := -R1.Top;
 R2.Right := R2.Left+(R.Right-R.Left);
 R2.Bottom := R2.Top+(R.Bottom-R.Top);

Всё в R2: TRect то же самое что и в R из [4] но с меньшими затратами кода, (почти вдвое)   и немного лучше в быстродействии.
:)


Vladimir Kladov   (2006-04-17 15:34:00) [15]

Иногда проще дать практический совет, чем разводить теорию.

R := ScrollBox1.ClientRect;
R.TopLeft := ScrollBox1.Client2Screen( R.TopLeft );
R.BottomRight := ScrollBox1.Client2Screen( R.BottomRight );
R.TopLeft := PaintBox1.Screen2Client( R.TopLeft );
R.BottomRight := PaintBox1.Screen2Client( R.BottomRight );

Все, в R: TRect - видимая часть PaintBox1, который дочерен к ScrollBox1.


ECM   (2006-04-17 13:35:00) [16]

Думаю здесь надо кое-что уточнить :))
GetClipRect - это общая (применимая к любым окнам, т.е. не только к ScrollBox) фунуция позволяющая узнать какая часть окна действительно видна (не заслонена другими, не выходит за пределы экрана и т.п) и должна быть перерисована.
Здесь как мне кажется вопрос был немного о другом. Какая часть элемента помещенного в ScrollBox будет видна в нем в данный момент и должна быть отрисована при необходимости...?
Тут все просто - ScrollBox всегда отрисовывает свой ClientRect (т.е. это видимая часть его "внутреннего содержания" ). Все "дети" помещенные в него имеют свой BoundsRect (Left,Top,Width,Height). Изменение которого заставляет ScrollBox пересчитывать параметры своих ScrollBar-ов и наооборот изменение позиции ScrollBar-а воздействует на позицию потомков внутри ScrollBox (меняются Top и Left). Поэтому ответ  - достаточно найти пересечение ScrollBox.ClientRect и BoundsRect потомка.


MTsv DN   (2006-04-15 09:06:00) [17]

Привет...

Что-то вроде этого...
function TfrmMain.ScrollBox1Message(var Msg: tagMSG;
 var Rslt: Integer): Boolean;
var
R : TRect;  
begin
Result := false;
if (Msg.message = WM_VSCROLL) or
   (Msg.message = WM_HSCROLL) then
 begin
  ZeroMemory(@R, SizeOf(R));
  Windows.GetClipBox(Memo.Canvas.Handle, R);
  MsgOK(
        'Left: ' + int2str(R.Left) + #13#10 +
        'Right: ' + int2str(R.Right) + #13#10 +
        'Top: ' + int2str(R.Top) + #13#10 +
        'Bottom: ' + int2str(R.Bottom)
       );
 end;
end;


С Уважением MTsv DN


BMouradov   (2006-04-15 00:21:00) [18]

Ещё один вопрос на ту же тему - как получить облать ScrollBox-а, которую надо перерисовать? Мне кажется, что отслеживать OnScroll - это не совсем красивый метод, может, есть что-нибудь красивее?


Наверх

Титульная страница Поиск, карта сайта Написать письмо