Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Custom ScrollBar своими руками, Полоса прокрутки с доп. возможностями 
:(
    Опции темы
Psychosis
Дата 12.8.2005, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 12.8.2005

Репутация: нет
Всего: нет



Уже 6 дней мучаюсь, никак не могу написать...

Этот scrollbar должен быть расширяемым. Имеется ввиду, что верний предел (Max), на самом деле не является пределом. Просто, при перемещении ползунка до этого Max, и далее, это значении Max будет увеличиваться пропорционально тому, насколько мы этот ползунок удвинули дальше. При последующем обратном движении, Max будет уменьшаться, но не опустится менее первоначального Max. Т.е. здесь есть как бы два предела первоначальный (OriginalMax) и текущий (CurrentMax).

Смысл этого. Представте, что у вас прокручиваемой областью является какая-либо диаграмма, на которой находяться разные прямоугольнички.
Множество этих прямоугольничков можно "вписать" в большой ограничивающий прямоугольник (BoundsRect). Высота и ширина этого прямоугольника и будет задавать пределы изменения двух scrollbar'ов.
Только вое если, пользователю захочется прокрутить на чистое место, что бы положить туда новый прямоугольничек, он с обычным scrollbar'ом этого не сделает.

Ответ желательно в форме обработчиков для трех событий:
- MouseDown
- MouseMove
- MouseUp

=================================================

Я пишу свой собственный ScrollBar, но не от TComponent, у меня есть свой собственный класс TArea (от TObject), от него порожден TCustomRectArea, затем TRectArea.

У TArea основные функциональные методы:


Код

    procedure MouseDown(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint); virtual;
    procedure MouseMove(AShiftState: TShiftState; APosition: TPoint); virtual;
    procedure MouseUp(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint); virtual;
    procedure PaintTo(ACanvas: TCanvas); virtual;




Отрисовка производиться на канву формы через буфферный битмап, события от мыши, так же, поступают от формы и передаются самой парентной TArea. У TArea есть список дочерних TArea.... and so on

Так вот я хочу написать нормальный TScrollBar (TScrollBarArea), а не такой глючный как стандартный виндовский и с доп. возможностями.
У стандартного есть например такой глюк, когда тянуть ползунок далеко вправо, за пределы ScrollBar'а, то ползунок перескакивает на позицию 0. Или если предварительно поместить ползунок на середину, а затем аналогично далеко потянуть его влево, то он перескочит на середину...

Так вот, TScrollBar у меня называется TScrollBarAreaNew, но он нам не интересен, т.к. реализует только расположение кнопок для прокрутки и "TSliderBarArea", кот. нас и интересует.

Код

  TScrollBarAreaNew = class(TRectArea)
  private
    FDecreaseButtonArea: TCustomTimerButtonArea;
    FIncreaseButtonArea: TCustomTimerButtonArea;
    FSliderBarArea: TSliderBarArea;
    FListLayout: TListLayout;

    function GetOrientation: TOrientation;
    procedure SetOrientation(AValue: TOrientation);

    function GetMin: Real;
    procedure SetMin(AValue: Real);
    function GetMax: Real;
    procedure SetMax(AValue: Real);
  protected
    procedure DecreaseButtonAreaPaintHandler(ACanvas: TCanvas);
    procedure IncreaseButtonAreaPaintHandler(ACanvas: TCanvas);
    procedure DecreaseButtonAreaTimerHandler(ASender: TObject);
    procedure IncreaseButtonAreaTimerHandler(ASender: TObject);
  public
    constructor Create; override;
    destructor Destroy; override;

    property Orientation: TOrientation read GetOrientation write SetOrientation;

    property Min: Real read GetMin write SetMin;
    property Max: Real read GetMax write SetMax;

    procedure Resize; override;
  end;


TSliderBarArea - по сути, просто контейнер, кот. определяет в каких пределах может ездить "TSliderArea".


Код

  TSliderBarArea = class(TRectArea)
  private
    FSliderArea: TSliderArea;
  public
    constructor Create; override;
    destructor Destroy; override;

    procedure Resize; override;

    procedure PaintTo(ACanvas: TCanvas); override;
  end;


Вот с "TSliderArea" и есть основная "Ж"

Код

  TSliderArea = class({TRectArea}TCustomRectArea)
  private
    FCaught: Boolean;
    FCatchPoint: TPoint;
    FOriginalPoint: TPoint;

    FPosition: Real;
    FSize: Real;
    FMin: Real;
    FMax: Real;
    FRealMin: Real;
    FRealMax: Real;
  protected
    function GetLeft: Integer; override;
    procedure SetLeft(AValue: Integer); override;
    function GetTop: Integer; override;
    procedure SetTop(AValue: Integer); override;
    function GetWidth: Integer; override;
    procedure SetWidth(AValue: Integer); override;
    function GetHeight: Integer; override;
    procedure SetHeight(AValue: Integer); override;
  public
    procedure MouseDown(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint); override;
    procedure MouseMove(AShiftState: TShiftState; APosition: TPoint); override;
    procedure MouseUp(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint); override;

    procedure PaintTo(ACanvas: TCanvas); override;
  end;


================================================

Чего хочу (объясняю на примерах):
1) Тащу ползунок вправо. Он уперся в край (в смысле дошел до максимума). А я все равно тащу, и хочу, что бы он продалжал скролить.
И хочу, что бы он делал это посредством увеличения верхнего предела (максимума). Т.е. дошел ползунок до максимума, видит, что я дальше двигаю, увеличивает свой максимум.
ПРОБЛЕМА: при реализации вышеизложенного напрямую, после достижения максимума (и начала его увеличения), скролить начинает не _линейно_, а _нелинейно_.

2) Тащу обратно, максимум начинаяет уменьшаться, и так до первоначального значения максимума.

Код

{ TSliderArea }

function TSliderArea.GetLeft: Integer;
begin
  Result := Round((FPosition - FRealMin)/(FRealMax - FRealMin)*TRectArea(FParentLink).Width);

  if Result < 0 then
    Result := 0;

  if Result > TRectArea(FParentLink).Width - GetWidth then
    Result := TRectArea(FParentLink).Width - GetWidth;
end;

procedure TSliderArea.SetLeft(AValue: Integer);
begin
end;

function TSliderArea.GetTop: Integer;
begin
  Result := 0;
end;

procedure TSliderArea.SetTop(AValue: Integer);
begin
end;

function TSliderArea.GetWidth: Integer;
begin
  Result := Round((FSize)/(FRealMax - FRealMin)*TRectArea(FParentLink).Width);

  if Result < 3 then
    Result := 3;
end;

procedure TSliderArea.SetWidth(AValue: Integer);
begin
end;

function TSliderArea.GetHeight: Integer;
begin
  Result := 16;
end;

procedure TSliderArea.SetHeight(AValue: Integer);
begin
end;

procedure TSliderArea.MouseDown(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint);
begin
  TArea.CaptureArea(Self);
  FCaught := True;
  FCatchPoint := ChildToParent(APosition);
  FOriginalPoint := Point(GetLeft, GetTop);

  inherited;
end;

procedure TSliderArea.MouseMove(AShiftState: TShiftState; APosition: TPoint);
var
  ParentSize: Integer;
  P: TPoint;
begin
  if FCaught then
  begin
    ParentSize := TRectArea(FParentLink).Width;
    P := ChildToParent(APosition);

    FPosition := FRealMin + (FOriginalPoint.x + (P.x - FCatchPoint.x))/ParentSize*(FRealMax - FRealMin);

    if FPosition > FRealMin then
      if FPosition < FMin then
        FRealMin := FPosition
      else
        FRealMin := FMin;

    if FPosition + FSize < FRealMax then
      if FPosition + FSize > FMax then
        FRealMax := FPosition + FSize
      else
        FRealMax := FMax;
  end;

  inherited;
end;

procedure TSliderArea.MouseUp(AButton: TMouseButton; AShiftState: TShiftState; APosition: TPoint);
begin
  if FCaught then
  begin
    if FPosition < FMin then
      FRealMin := FPosition
    else
      FRealMin := FMin;

    if FPosition + FSize > FMax then
      FRealMax := FPosition + FSize
    else
      FRealMax := FMax;

    FCaught := False;
    TArea.ReleaseArea;
  end;  

  inherited;
end;

procedure TSliderArea.PaintTo(ACanvas: TCanvas);
begin
  ACanvas.Pen.Color := clBlack; 
  ACanvas.Brush.Color := clWhite;
  ACanvas.Rectangle(0, 0, GetWidth, GetHeight);
  //ACanvas.TextOut(0, 0, FloatToStr(FPosition));

  Application.Title := FloatToStr(FPosition);

  inherited;  
end;

================================================

Если есть у кого !!!сорцы!!! классных ScrollBar'ов с разными фишками (как в AudioMulch [если кто знаком с такой прогой] )(например: изменение размеров ползунка мышкой - для масштабирования отображаемой области) кинте на мэйл плиз, или дайте ссылки... Плиз...

А то повешусь... Уже сигарета за сигаретой...

Это сообщение отредактировал(а) Girder - 12.8.2005, 14:42
PM MAIL   Вверх
Y-Vladimir
Дата 12.8.2005, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 16.7.2004
Где: Казань

Репутация: нет
Всего: 6



А почему в раздел Алгоритмы?

Сразу несколько вопросов:
Цитата(Psychosis @ 12.8.2005, 07:42)
ПРОБЛЕМА: при реализации вышеизложенного напрямую, после достижения максимума (и начала его увеличения), скролить начинает не _линейно_, а _нелинейно_.

А что мешает сделать линейно?

Цитата(Psychosis @ 12.8.2005, 07:42)
Тащу обратно, максимум начинаяет уменьшаться, и так до первоначального значения максимума.

Подробнее обьясни, как при этом должен вести себя ползунок, т.е. либо ползунок не смещается, до тех пор, пока не достигнем первоначального максимума, либо еще как.




--------------------
PM MAIL WWW   Вверх
podval
Дата 12.8.2005, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Где я? Кто я?
****


Профиль
Группа: Экс. модератор
Сообщений: 3094
Регистрация: 25.3.2002
Где: СПб

Репутация: нет
Всего: 62



Модератор: тема перенесена из раздела "Алгоритмы"
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0871 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.