Sender: немного практики, или создаём свой стиль кнопок.

Создаём свои кнопки, используя TImage и параметр Sender. На delphi
Полтора года назад писал такую статью на одном форуме, на блоге этого нет. В связи с тем, что на этой неделе поднял тему использования Sender: TObject и операторов as и is, распишу всё заново здесь и сейчас :)

Мы используем TImage, столько TImage, сколько нужно кнопок.

Подготовка

У наших кнопок будет три состояния — нажата, не нажата, активна (наведена мышь).
Заранее подготовь три картинки, для трёх этих состояний, и помести в папку программы.
Создадим константы с именами наших картинок:

const
  IM_DOWN: string='down.bmp';
  IM_MAIN:  string='main.bmp';
  IM_HOVER: string='hover.bmp';

Ии, нам надо их менять, подготовимся:

procedure SetState(btn:TImage;vstate:string);
var
  vfile:string;
begin
  vfile:=ExtractFilePath(ParamStr(0))+vstate;
  try
    btn.Picture.LoadFromFile(vfile);
  except
  end;
end;

Здесь мы передаём функции имя файла картинки (из созданных констант) и указание на TImage, с которым нужно такое сотворить.

Так-с, поставим теперь на форму Image1, создадим ему следующие обработчики событий:

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  SetState(Image1,IM_HOVER);
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  SetState(Image1,IM_MAIN);
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  SetState(Image1,IM_DOWN);
end;

Тут всё понятно (надеюсь): при нажатии, отжатии, наведении мышью. А как быть, когда мышь уходит?

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  SetState(Image1,IM_MAIN);
end;

Да, с одним TImage работает на ура. Только вот мерцает при движении мышью, это плохо, так ведь?

Тогда добавим еще четыре константы:

const
  BS_UP=1001;         //последнее событие было mouseup
  BS_DOWN=1002;       //последнее событие было mousedown
  BS_HOVER=1003;      //последнее событие было mousemove
  BS_FORM=1004;  //мышь двигается по форме

Куда мы будем их присваивать? Неверно, к свойству tag у TImage, оно зарезервировано специально для таких пожарных случаев.

Сразу приведу модифицированный код:

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Image1.Tag<>BS_HOVER then
    SetState(Image1,IM_HOVER);
  Image1.Tag:=BS_HOVER;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Image1.Tag<>BS_UP then
    SetState(Image1,IM_MAIN);
  Image1.Tag:=BS_UP;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Image1.Tag<>BS_DOWN then
    SetState(Image1,IM_DOWN);
  Image1.Tag:=BS_DOWN;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Image1.Tag<>BS_FORM then
    SetState(Image1,IM_MAIN);
  Image1.Tag:=BS_FORM;
end;

Обобщение

Вот и настал тот момент… когда нам надо переходить от одного Image1 к любому TImage, на котором произошло событие. Если ты читал мой блог, то уже знаешь, что надо заменить Image1 на (Sender as TImage) во всех обработчиках событий у Image1.

А что делать при движении мышью по форме? Точно, надо перебрать все компоненты TImage на форме, полезный, кстати, навык:

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do begin
    if Components[i] is TImage then begin
      if (Components[i] as TImage).Tag<>BS_FORM then
        SetState((Components[i] as TImage),IM_MAIN);
     (Components[i] as TImage).Tag:=BS_FORM;
    end;
  end;
end;

Вроде всё чисто и ясно, могу про это потом отдельный пост написать.

Ну и назначим события при старте формы:

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do begin
    if Components[i] is TImage then begin
      (Components[i] as TImage).OnMouseDown:=Image1MouseDown;
      (Components[i] as TImage).OnMouseUp:=Image1MouseUp;
      (Components[i] as TImage).OnMouseMove:=Image1MouseMove;
    end;
  end;
end;

Итог

Теперь, сколько бы мы TImage не создали в проекте, столько у нас и будет кнопок :)


Свой стиль кнопок на delphi
А вы знали, что google — хиппи? Особенно рано утром :)

Иногда требуется подключить интернет, но возникают проблемы — много провайдеров, разные тарифы — как выбрать? Если ты в Москве, то воспользуйся ссылкой выше.


(c) crystalbit, http://parsers.info

Ах, вот проектик — скачать
А вот rss лента — подписаться

8 ответов к «Sender: немного практики, или создаём свой стиль кнопок.»

  1. Спасибо за все статьи про Sender. Написано классно! Очень понравилось визуальное оформление кода. Есть ли сервис для хранения кода с таким же дизайном?

    1. Старался :)
      Визуальное оформление это плагин syntax highlighter, в принципе просто хитрый стиль css, http://code.google.com/p/syntaxhighlighter/ — страница автора, по идее для любой страницы подойдёт, я особо не заморачивался и поставил готовый плагин.
      Что имеется в виду под сервисом хранения кода? Если просто подсветка на компьютере, то я использую Notepad++, а если онлайн, типа документов google, то мне и самому интересно :)

  2. Большое спасибо. Ломал голову над битбаттонами и png.. Но получилось только так. Единственное, не понял, как обобщить бдя всех кнопок, чтоб разные png использовались. В итоге повторил большую часть кода для второй кнопки, остальное втиснул в этот, где было возможно.
    Всё работает, и это главное. Еще раз спасибо.

  3. Можно конечно посчитать за спам. В одной из статей за декабрь прошлого года прочитал описываемые Вами причины не комментирование блогов. Пишу здесь специально. Не раз читал, что если на блоге масса комментариев, то поисковики отмечают только часть первых, остальные пропускают. Чушь, я думаю, но многих это отпугивает. И еще, иногда раздражает скорость загрузки блога. Не у всех ведь скоростной интернет.
    Удачи!!!

    1. По поводу скорости — перенесу скоро на другой хостинг.
      Геннадий, так мило, из-за этого ты пишешь в другой пост?)

  4. Как использовать разные картинки для разных кнопок!? Попробовал поэксперементировать с кодом, но так ничего и не понял(

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *