![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
UI: Выделение с прокруткой.
guav © (2006-10-15 17:51:00)В программе реализовано выделение прямоугольной области мышью при зажатии левой или правой кнопки (как в пеинте или в ListView). Рисуется оно на TPaintBox лежащем на TScrollBox. Есть требование сделать так чтобы при выводе мыши из области пеинтбокса скроллбокс прокручивался, чтобы можно было выделять большие области.
Как реализовать такую прокрутку ?
guav (2006-10-16 14:03:00) [1]> Какой
интервал таймера ?
guav (2006-10-16 14:01:00) [2]Меня настроаживает это:
> SetTimer(Handle, 1, 60, nil);- есть подозрение, что такие малые задержки не выполняются точно, при этом, для попиксельной прокрутки и этой задержки было бы мало.
> [7] AlexeyT © (16.10.06 01:21)
Что за контрол ? Грид, эдит, или графическое поле ввода ? Какой
Eraser (2006-10-16 01:22:00) [3]> [6] guav © (16.10.06 00:30)
> Мжет правда мне не подойти, т.к. у меня не ячейки а пиксели,
> они значительно меньше.
ну можно скролировать не по 1 пикселю.
> Ещё пример похожего скролинга - в редакторе или в IE при
> выделении текста, если завести курсор мыши выше или ниже
> окна с текстом
угу, можно даже сделать, чтобы скорость скроллинга зависела от удаления мыши от границ контрола.
AlexeyT (2006-10-16 01:21:00) [4]Правильно делать как раз с таймером, IMHO. Когда мышь вне твоего поля, таймер прокручивает контрол, когда мышь вернулась, таймер выключаешь. Я у себя так сделал.
guav (2006-10-16 00:30:00) [5]Таки не понравился такой подход мне самому.
Будем делать как в ListView.
Нашел, что похожий скроллинг у грида.
В TCustomGrid.MouseDown :SetTimer(Handle, 1, 60, nil);- т.е. никакая специальная API функция для таких дел не используется, просто прокручивание по одной ячейке по таймеру. Мжет правда мне не подойти, т.к. у меня не ячейки а пиксели, они значительно меньше.
Ещё пример похожего скролинга - в редакторе или в IE при выделении текста, если завести курсор мыши выше или ниже окна с текстом.
guav (2006-10-15 18:46:00) [6]> [4] Eraser © (15.10.06 18:30)
Уговорил, сделаю так, не понравится пользователям - переделаю.
Eraser (2006-10-15 18:30:00) [7]все таки для граф. редактора удобнее когда процесс полностью контролируешь, а автопрокрутка в ListView уж очень слабоуправляема.
Eraser (2006-10-15 18:21:00) [8]> [2] guav © (15.10.06 18:18)
думаю примерно так же, только убрать SetCursorPos.
> вообще не стоит злоупотреблять функциями вроде SetCursorPos
> или ClipCursor.
согласен, черевато багами. но в моем случае сделал, чтобы выглядело как у конкурентов :)
guav (2006-10-15 18:18:00) [9]> [1] Eraser © (15.10.06 18:08)
Спасибо.
Идея понятна. Никаких таймеров с автопрокруткой, вместо этого при попытке выйти из области прокрутка и SetCursorPos обратно в область. Реализация, конечно, проще в этом случае, но, думаю, пользователю будет удобнее "как в Listview"; вообще не стоит злоупотреблять функциями вроде SetCursorPos или ClipCursor.
Всё же хотелось бы узнать как сделать "как в Listview".
Eraser (2006-10-15 18:08:00) [10]> [0] guav © (15.10.06 17:51)
код из совершенно другой программы, но со сходной функциональностью.
if FConnection.AdvMouseScroll and (FConnection.RenderMode = 1) then
begin
if HorzScrollBar.IsScrollBarVisible then
begin
// Вычисляем 20% от ширины окна.
a1 := ClientWidth div 5;
// Проверяем правую границу окна.
if (x > ClientWidth - a1) and (FLastX > ClientWidth - a1) then
begin
FLastX := ClientWidth - a1;
nX := X - FLastX;
//Caption := 'Pos = ' + IntToStr(HorzScrollBar.Position) +
// ' Range = ' + IntToStr(HorzScrollBar.Range) +
// ' ClientWidth = ' + IntToStr(ClientWidth) +
// ' nX = ' + IntToStr(nX);
//Caption := 'X = ' + IntToStr(x) +
// 'LastX = ' + IntToStr(FLastX) +
// ' nX = ' + IntToStr(nX);
if (nX > 0) and
(HorzScrollBar.Position + 1 < HorzScrollBar.Range - ClientWidth) then
begin
HorzScrollBar.Position := HorzScrollBar.Position + nX;
ptCursor := ClientToScreen(Point(FLastX, FLastY));
SetCursorPos(ptCursor.X, ptCursor.Y);
end;
end;
// Проверяем левую границу окна.
if (x < a1) and (FLastX < a1) then
begin
FLastX := a1;
nX := FLastX - X;
if (nX > 0) and
(HorzScrollBar.Position > 0) then
begin
HorzScrollBar.Position := HorzScrollBar.Position - nX;
ptCursor := ClientToScreen(Point(FLastX, FLastY));
SetCursorPos(ptCursor.X, ptCursor.Y);
end;
end;
end;
FLastX := x;
if VertScrollBar.IsScrollBarVisible then
begin
// Вычисляем 20% от высоты окна.
a1 := ClientHeight div 5;
// Проверяем нижнюю окна.
if (y > ClientHeight - a1) and (FLastY > ClientHeight - a1) then
begin
nY := Y - FLastY;
if (nY > 0) and
(VertScrollBar.Position < VertScrollBar.Range - ClientHeight) then
begin
//Caption := IntToStr(VertScrollBar.Position) + ' X ' +
// IntToStr(VertScrollBar.Range - ClientHeight);
VertScrollBar.Position := VertScrollBar.Position + nY;
ptCursor := ClientToScreen(Point(FLastX, FLastY));
SetCursorPos(ptCursor.X, ptCursor.Y);
end;
end;
// Проверяем верхнюю границу окна.
if (y < a1) and (FLastY < a1) then
begin
nY := FLastY - Y;
if (nY > 0) and
(VertScrollBar.Position > 0) then
begin
VertScrollBar.Position := VertScrollBar.Position - nY;
ptCursor := ClientToScreen(Point(FLastX, FLastY));
SetCursorPos(ptCursor.X, ptCursor.Y);
end;
end;
end;
FLastY := y;
end;