Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Сокровищница
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  09:41[Войти] | [Зарегистрироваться]

Обработка сообщений от мыши потомками собственного компонента

Peter Taran
дата публикации 13-11-2000 00:00

Обработка сообщений от мыши потомками собственного компонента

Проблема: имеем свой собственный компонент, который может содержать несколько объектов с собственным внешним видом, каждый из которых должен реагировать на перемещение мыши.
Например -- подсвечиваться.
Для гуру: ничего интересного вы здесь не найдёте, примерчик это не более, чем пропаганда использования стандартного оконного механизма в противовес различным самоизобретённым велосипедам.
Классы: класс TMyControl -- основной компонент; TMySubControl -- класс того объекта, который будет лежать на TMyControl и подсвечиваться.

Наследование от TGraphicControl необязательно. Фактически, можно выбирать из четырёх вариантов:
TControl
базовый класс всех элементов управления, не имеет виндовского Handle(дескриптора) окна, т.е. данный элемент Windows не считает окном; вся реализация сообщений, отрисовки и пр. выполняется в VCL; (+) -- меньше кушает ресурсов, (-) -- см. TWinControl
TGraphicControl
то же, что и TControl, но имеет свойство Canvas, при помощи которого удобно рисовать и метод Paint, в котором надо рисовать
TWinControl
это полноценное Windows-окно со всеми преимуществами перед TControl: (а) может получать фокус ввода, (б) может содержать "детей" -- другие окна на своей поверхности, (в) -- имеет дескриптор, св-во Handle
TCustomControl
наследник TWinControl, отличия между ними те же, что и между TControl и TGraphicControl
Выбран TGraphicControl по причине отсутствия "детей" и наличия Canvas.

Данные, составляющие компонент: FItem: TCollectionItem входит в какую-либо коллекцию и, собственно, содержат смысловое наполнение элемента. Я встречал вариант, когда у TMyControl не определялись "дети", а в качестве реакции на WM_PAINT перебирались элементы некоторой коллекции, которые кроме смысловых данных хранили свой контур, координаты и пр. и ручками всё это рисовалось... Жуть! Собственно, мой пример -- антиреклама описанного подхода

Скачать файл MessMouse.zip (3K)

Peter Taran

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  StdCtrls, Buttons, ComCtrls;

type
 
  TMySubControl = class(TGraphicControl)
  private
    FSelected: Boolean; //флаг, отмечающий подсвеченность
    FItem: TCollectionItem;    

    procedure SetMouseOver(Val: Boolean);
    procedure MsMove(var M: TWMMouseMove); message WM_MOUSEMOVE;
      { Реакция на перемещение мыши }
  protected
    procedure Paint(); override; //по этому сообщению надо перерисовывать
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy(); override;
    property IsSelected: Boolean read FSelected write SetMouseOver;
      { Свойство, отмечащее факт "подсвеченности" }
  end;

  { "Главный" элемент управления. Собственную процедуру отрисовки я
    не определял, а "дети" есть. Поэтому -- TWinControl }
  TMyControl = class(TWinControl)
  private
    procedure MsMove(var M: TWMMouseMove); message WM_MOUSEMOVE;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  { Класс основной формы. Ничего интересного }
  TMain = class(TForm)
    CloseButt: TBitBtn;
    Label1: TLabel;
    Label2: TLabel;
    procedure CloseWndExecute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
  public
  end;

var
  Main: TMain;

implementation

{$R *.DFM}

{ По кнопочке "Закрыть" }
procedure TMain.CloseWndExecute(Sender: TObject);
begin
  Close();
end;

{ Создание элементов вручную. Главное: вызвать конструктор,
  задать размеры и положение, назначить "родителя". Поскольку
  пакеты не используются, то на автомате создать их не выйдет. }
procedure TMain.FormCreate(Sender: TObject);
var
  c: TMyControl;
begin
  c := TMyControl.Create(Self);
  with c do begin
    SetBounds(8, 8, 240, 180);
    Color := clTeal;
    Parent := Self; //"родитель" -- формочка
  end;

  with TMySubControl.Create(Self) do begin
    SetBounds(3, 7, 49, 11);
    Parent := c; //у всех TMySubControl родитель -- TMyControl
  end;
  with TMySubControl.Create(Self) do begin
    SetBounds(140, 53, 94, 25);
    Parent := c;
  end;
  with TMySubControl.Create(Self) do begin
    SetBounds(38, 100, 88, 70);
    Parent := c;
  end;
end;

{ Мониторинг перемещений мыши по основному control-у.
  Отметьте, что когда курсор над "детьми", control не получает
  данное сообщение. }
procedure TMyControl.MsMove(var M: TWMMouseMove);
begin
  inherited;
  Main.Label1.Caption :=
    Format('%d:%d', [M.XPos, M.YPos]);
end;

{ Добавляем стиль 3D-рамки. Её отрисовка производится стандартными
  средствами винды. }
constructor TMyControl.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csFramed];
end;

{ Перерисовка. Простой прямоугольник. Цвет -- стандартный или
  подсвеченный, в зависимости от IsSelected }
procedure TMySubControl.Paint();
const
  a: array[Boolean] of TColor = (clWindow, clHighlight);
begin
  inherited;
  Canvas.Brush.Color := a[IsSelected];
  Canvas.FillRect(Canvas.ClipRect);
  with Canvas.ClipRect do
    //показываем -- какая именно часть перерисовывается
    Main.Label2.Caption := Format('(%d:%d) - (%d:%d)',
       [Left, Top, Right, Bottom]);
end;

{ Смена значения свойства. Только один из TMySubControl может быть
  подсвеченным }
procedure TMySubControl.SetMouseOver(Val: Boolean);
var
  i: Integer;
begin
  if Val <> FSelected then begin
    Invalidate(); //если изменилась подсветка, то надо перерисоваться
    if Val then //нас подсветили (Val = TRUE)
      for i := Parent.ControlCount - 1 downto 0 do
        //среди "братьев" ищем другие TMySubControl и снимаем им подсветку
        if (Parent.Controls[i] <> Self) and (Parent.Controls[i] is TMySubControl)
        then
          TMySubControl(Parent.Controls[i]).IsSelected := FALSE;
    FSelected := Val;
  end;
end;

procedure TMySubControl.MsMove(var M: TWMMouseMove);
begin
  IsSelected := TRUE; //над нами переместили мышку -- значит подсветили
end;

constructor TMySubControl.Create(AOwner: TComponent);
begin
  inherited;
  FItem := TCollectionItem.Create(nil {тут произвольный объект-коллекция,
     например его можно указать в параметрах конструктора});
end;

destructor TMySubControl.Destroy();
begin
  FItem.Free();
  inherited;
end;

end.

Peter Taran




Смотрите также материалы по темам:
[TControl] [TWinControl] [TCustomControl] [TCollection] [TCollectionItem] [TForm] [TGraphicControl] [Создание компонентов в run-time] [Создание собственных компонент] [Реакция на клавиатуру, мышь]

 Обсуждение материала [ 23-02-2024 10:33 ] 7 сообщений
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования