Sender: немного практики, или создаём свой стиль кнопок.
Полтора года назад писал такую статью на одном форуме, на блоге этого нет. В связи с тем, что на этой неделе поднял тему использования 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 не создали в проекте, столько у нас и будет кнопок :)
А вы знали, что google — хиппи? Особенно рано утром :)
Иногда требуется подключить интернет, но возникают проблемы — много провайдеров, разные тарифы — как выбрать? Если ты в Москве, то воспользуйся ссылкой выше.
(c) crystalbit, http://parsers.info
Ах, вот проектик — скачать
А вот rss лента — подписаться
Спасибо за все статьи про Sender. Написано классно! Очень понравилось визуальное оформление кода. Есть ли сервис для хранения кода с таким же дизайном?
Старался :)
Визуальное оформление это плагин syntax highlighter, в принципе просто хитрый стиль css, http://code.google.com/p/syntaxhighlighter/ — страница автора, по идее для любой страницы подойдёт, я особо не заморачивался и поставил готовый плагин.
Что имеется в виду под сервисом хранения кода? Если просто подсветка на компьютере, то я использую Notepad++, а если онлайн, типа документов google, то мне и самому интересно :)
Большое спасибо. Ломал голову над битбаттонами и png.. Но получилось только так. Единственное, не понял, как обобщить бдя всех кнопок, чтоб разные png использовались. В итоге повторил большую часть кода для второй кнопки, остальное втиснул в этот, где было возможно.
Всё работает, и это главное. Еще раз спасибо.
Можно конечно посчитать за спам. В одной из статей за декабрь прошлого года прочитал описываемые Вами причины не комментирование блогов. Пишу здесь специально. Не раз читал, что если на блоге масса комментариев, то поисковики отмечают только часть первых, остальные пропускают. Чушь, я думаю, но многих это отпугивает. И еще, иногда раздражает скорость загрузки блога. Не у всех ведь скоростной интернет.
Удачи!!!
По поводу скорости — перенесу скоро на другой хостинг.
Геннадий, так мило, из-за этого ты пишешь в другой пост?)
Особо не заморачивался с кнопками — просто обычный гипертекст с цветом и шрифтом красивым. Меньше весить будет!
Как использовать разные картинки для разных кнопок!? Попробовал поэксперементировать с кодом, но так ничего и не понял(