Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.94/98: Рейтинг темы: голосов - 98, средняя оценка - 4.94
Покинул форум
3189 / 1368 / 109
Регистрация: 29.01.2010
Сообщений: 2,887

Создание событий MouseEnter и MouseLeave для TImage (решено)

11.06.2010, 17:16. Показов 19291. Ответов 31

Студворк — интернет-сервис помощи студентам
Раз на форуме появилось огромное количество желающих, которым нужно событие OnMouseEnter и OnMouseLeave для TImage, то почему бы этого не сделать?!
Сие краткое руководство (да что там руководство, просто пример) поможет вам разобраться в этой проблеме (надеюсь).
За основу был взять
пример из интернета
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class TMyImage:public TImage
{
public:
       //Событие OnMouseEnter
       virtual void __fastcall Process_OnEnter(TMessage &msg){
               Picture = EnterPic;
       }
       //Событие OnMouseLeave
       virtual void __fastcall Process_OnLeave(TMessage &msg){
               Picture = LeavePic;
       }
         //Конструктор, принимающий в качестве аргументов 2 картинки (когда мышка попадает на объект и когда
         //покидает его) и объект TImage, события которого присваиваются потом нашему объекту.          
       _fastcall TMyImage::TMyImage(TPicture* Pic1, TPicture* Pic2, TImage* ParentImage, TComponent*Owner):TImage(Owner){
               Picture = ParentImage->Picture;//Задаём начальную картинку для изображения
               Left = ParentImage->Left;
               Top = ParentImage->Top;
               OnClick = ParentImage->OnClick;
               OnMouseDown = ParentImage->OnMouseDown;
               OnMouseUp = ParentImage->OnMouseUp;
               Visible = true;
               AutoSize = true;
 
               EnterPic=Pic1;
               LeavePic = Pic2;
 
       }
private:
 
       TPicture* EnterPic;
       TPicture* LeavePic;
 #pragma warn -8027
BEGIN_MESSAGE_MAP
       VCL_MESSAGE_HANDLER(CM_MOUSEENTER,TMessage,Process_OnEnter);
       VCL_MESSAGE_HANDLER(CM_MOUSELEAVE,TMessage,Process_OnLeave);
END_MESSAGE_MAP(TImage)
#pragma warn -8027
};
, но слегка модифицирован и упрощен, а также прокомментирован по мере возможности и знаний автора (я скорее практик, чем теоретик, поэтому за скупое описание прошу не судить).

1. Для начала нужно создать нашу кнопку. Оба состояние кнопки будут в одном изображении (левая часть изображения до середины отвечает за исходное состояние, а правая часть после середины за измененное). Размер кнопки может быть любой, но для начала сделайте размер 150*40, а при склеивании должно получится 300*40.

2. Теперь переходим к созданию своего класса! Делать мы его будем на основе TImage, так как это, по моему скромному мнению, самый идеальный вариант. Можно было бы использовать TButton, но он не имеет свойство TCanvas, которое нам необходимо:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class TFunnyButton: public TImage  //Собственно наш класс
     {
     Graphics::TBitmap *Source_Bitmap;  /*Создаем TBitmap, который будет хранить целое изображение кнопки,
         Так как в Picture у нас будет только выводится готовое "обрезанное" изображение*/
        public: 
            //Теперь обьявляем новые функции для нашего класса
        virtual void __fastcall  OnMouseEnter(TMessage &msg)   //Курсор на кнопке
        {
        Canvas->CopyRect(Rect(0,0,Width,Height),Source_Bitmap->Canvas,Rect(Width,0,Width*2,Height));  /*Так как изображение у нас состоит из 2 частей, где первая левая часть - это исходное изображение,
            а правая отрисовывается при попадании курсора на кнопку, то мы копируем соответственно правую часть исходного изображения (от Width до Width*2) */
        }
 
        virtual void __fastcall  OnMouseLeave(TMessage &msg)  //Курсор покидает кнопку
        {
 
        Canvas->CopyRect(Rect(0,0,Width,Height),Source_Bitmap->Canvas,Rect(0,0,Width,Height));
        //Делаем тоже самое что и при попадании крсора на кнопку, только в этот раз копируем левую часть
 
        }
 
        _fastcall TFunnyButton::TFunnyButton(AnsiString BitmapName):TImage(Owner){   //Конструктор обьекта, в качестве аргумента принимается только путь к файлу
 
 
            Width=150;  //Устанавливаем ширину кнопки по умолчанию
            Height=40;  //Устанавливаем высоту кнопки по умолчанию
           Source_Bitmap=new Graphics::TBitmap;
           Source_Bitmap->Width=Width*2;
           Source_Bitmap->Height=Height;
 
           Source_Bitmap->LoadFromFile(BitmapName);  //Загружаем само изображение из файла, указанного в BitmapName
           Canvas->CopyRect(Rect(0,0,Width,Height),Source_Bitmap->Canvas,Rect(0,0,Width,Height));  //Теперь отрисовываем левую часть изображения (исходную)
           Transparent=true;  //Включаем "прозрачность" кнопки, чтобы она приобрела округленный вид
        }
 
        private:
        #pragma warn -8027  //Своего рода игнорирование предупреждения - использовать по желанию
        BEGIN_MESSAGE_MAP  //Это таблица сообщений, она служит для отлавливания сообщений от Windows. Если честно, то мне самому не очень понятно что происходит далее, точнее смысл понятен, а обьяснить не могу...
         VCL_MESSAGE_HANDLER(CM_MOUSEENTER,TMessage,OnMouseEnter);  
         VCL_MESSAGE_HANDLER(CM_MOUSELEAVE,TMessage,OnMouseLeave);
         END_MESSAGE_MAP(TImage)
         #pragma warn -8027 
     };
Теперь пример использования класса:
C++
1
2
     TFunnyButton  *b=new TFunnyButton("F:\\button.bmp"); //Загружаем изображение из F:\button.bmp
       b->Parent=Form1; //Обязательно нужно указать родителя
Вот и все. Теперь ждем пожеланий и улучшений от форумчан!!!
(Изображение кнопки, использованной в примере)
Изображения
 
13
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.06.2010, 17:16
Ответы с готовыми решениями:

SetTimeout для mouseenter/mouseleave
Как правильно повесить setTimeout на события mouseenter/mouseleave? Но с одним нюансом, если предположим, что setTimeout для обоих событий...

Альтернатива mouseenter/mouseleave для touch
Здравствуйте уважаемые форумчане. Посоветуйте как можно сделать функционал для устройств с тач... Смысл такой: Есть список комментариев и...

Поймать MouseEnter, MouseLeave для строчек ListView
пожалуйста, примерчик или ссылку на таковой. пару колонок и пару строчек. и как хэндлеры событий к строчкам присоединить. нахожу...

31
0 / 0 / 0
Регистрация: 11.01.2012
Сообщений: 4
11.01.2012, 14:37
Студворк — интернет-сервис помощи студентам
Спасибо, помогли
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,476
27.01.2012, 10:30
подскажите - обработчики объявленные в вашем классе используют механизм аналогичный обработчикам для TLabel? просто для TLabel есть родные обработчики MouseEnter и MouseLeave, но в одном из проектов я заметил, что при быстром перемещении мыши сообщения могут "пропускаться". то есть, например, сообщение о входе мыши не приходит, а о выходе - успевает. стрессовое тестирование делали?
0
Почемучка)
 Аватар для Ddv122
1244 / 304 / 30
Регистрация: 23.12.2010
Сообщений: 2,001
Записей в блоге: 1
16.03.2012, 01:30
скажите пожалуйста можно ли создать для этого класса на основе TImage, события OnClick и тп. чтобы было как полноценная кнопка ...
0
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
16.03.2012, 01:36
Цитата Сообщение от EdarGp Посмотреть сообщение
скажите пожалуйста можно ли создать для этого класса на основе TImage, события OnClick и тп. чтобы было как полноценная кнопка ..
Да, учитывая, что у TImage и так есть события обрабатывающие нажатия клавиши мыши . Да и очень многие свойство могут быть использованы, просто объявив их:
C++
1
2
// ...
__property TabStop;
А вот графическое отображение нужно реализовывать самостоятельно.
1
Почемучка)
 Аватар для Ddv122
1244 / 304 / 30
Регистрация: 23.12.2010
Сообщений: 2,001
Записей в блоге: 1
16.03.2012, 02:30
как ее писать в программе при использовании .. ?
я вот дописал в классе

C++
1
2
3
4
...
__published:
__property OnClick;
...
и далее в проге

C++
1
2
3
4
void __fastcall TSimpleButton::OnClick(TObject *Sender)
{
Form1->Edit1->Text="1";
}
и выдает такую ​​вот ошибку

[BCC32 Error] Unit1.cpp(43): E2316 '_fastcall TSimpleButton::OnClick(TObject *)' is not a member of 'TSimpleButton'
0
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
16.03.2012, 02:43
А зачем ты его объявляешь? Если родитель TImage, то у него есть свойство OnClick.
0
Почемучка)
 Аватар для Ddv122
1244 / 304 / 30
Регистрация: 23.12.2010
Сообщений: 2,001
Записей в блоге: 1
16.03.2012, 02:45
а. . разобрался.. )))
дописал в классе..
C++
1
DYNAMIC void __fastcall MouseDown(System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, int X, int Y);
и сам обработчик стандартний
C++
1
2
3
4
void __fastcall TSimpleButton::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
Form1->Edit1->Text="1";
}
так работает .. =)

Добавлено через 1 минуту
Цитата Сообщение от DefineTrueFalse Посмотреть сообщение
А зачем ты его объявляешь? Если родитель TImage, то у него есть свойство OnClick.
есть то есть .. но если не объявить то говорит что он не является членом класса...
1
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
16.03.2012, 02:45
Да и прописывается это не вручную, а через дизайнер. А если ты это пытался в файле самого компонента писать, то тогда надо перехватывать события, как это с MouseEnter и MouseLeave.
0
Почемучка)
 Аватар для Ddv122
1244 / 304 / 30
Регистрация: 23.12.2010
Сообщений: 2,001
Записей в блоге: 1
16.03.2012, 02:51
Цитата Сообщение от DefineTrueFalse Посмотреть сообщение
Да и прописывается это не вручную, а через дизайнер. А если ты это пытался в файле самого компонента писать, то тогда надо перехватывать события, как это с MouseEnter и MouseLeave.
через дизайнер не получится .. нашего элемента же на форме нет .. мы же класс создаем .. а как ты переменную класса в дизайнер засунеш?) .. это не готовый компонент ...
писал я это в этом же классе но подобно тому как в файлах компонента прописывают .. собственно в другом компоненте и посмотрел)
0
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
16.03.2012, 02:55
Цитата Сообщение от EdarGp Посмотреть сообщение
через дизайнер не получится .. нашего элемента же на форме нет .. мы же класс создаем .. а как ты переменную класса в дизайнер засунеш?) .. это не готовый компонент ...
писал я это в этом же классе но подобно тому как в файлах компонента прописывают .. собственно в другом компоненте и посмотрел)
Все, понятно, меня немного декларация OnClick'а смутила, которая уже с готовым компонентом используется. В этом плане, конечно в перехват событий смотреть нужно.
0
DG
0 / 0 / 0
Регистрация: 23.11.2014
Сообщений: 3
06.04.2013, 00:00
Вариант создания кнопки из TImage в C++ Builder 6:

Т.к. события MouseEnter и MouseLeave для TImage отсутствуют в C++ Builder 6, можно воспользоваться элементом TLabel (у него такие события есть).
Итак, делаем 3 картинки и загружаем их в три объекта TImage через Properties Picture:
Image1 - картинка кнопки до наведения курсора
Image2 - картинка кнопки после наведения курсора
Image3 - картинка кнопки при нажатии
Делаем у них одинаковые размеры и положение, располагаем одну под другой: сверху Image1, снизу Image3.
Над ними располагаем Label1 с такими же размерами.
Чтобы картинки были видны, делаем в свойствах Label1:
Label1->AutoSize=false
Label1->Caption=ничего
Label1->Transparent=true
Дальше используем события Label1:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void __fastcall TForm1::Label1MouseEnter(TObject *Sender)
{
 Image2->Visible=true;
 Image1->Visible=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label1MouseLeave(TObject *Sender)
{
 Image1->Visible=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
 Image3->Visible=true;
 Image2->Visible=false;
 Image1->Visible=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label1MouseUp(TObject *Sender, TMouseButton Button,  TShiftState Shift, int X, int Y)
{
 Image2->Visible=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label1Click(TObject *Sender)
{
 //ФУНКЦИИ КНОПКИ
}
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
06.04.2013, 00:05
Цитата Сообщение от NiTan Посмотреть сообщение
OnMouseLeave
Я не замарачивался такими проблемами в свое время и обрабатывал вместо него событие MouseMove формы ( или другого Owner-a) и соседних компонентов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.04.2013, 00:05

События MouseEnter и MouseLeave
У меня на форме не большой Splitter, ширика 3-4 пикселя, на его события MouseEnter и MouseLeave повешены обработчики, но если очень быстро...

MouseLeave и MouseEnter(Gradient)
Привет форумчане, пытаюсь изучить wpf и при изучение материала с этими событиями создал себе практическую задачу, на эту тематику и уже...

Обработчики mouseenter() и mouseleave()
Всем здравствуйте! Подскажите как изолировать обработчики друг от друга. В принципе все работает, но если быстро двигать мышью по углу...

Многоразовое событие mouseenter / mouseleave
Проблема в том, что если человек быстро и много раз будет водить курсором по элементу, то после этого, элемент будет и дальше выполнять...

Избавится от артефактов MouseEnter/MouseLeave
Есть такой кусочек кода... var png: TPngImage; .... procedure TForm1.Image4MouseEnter(Sender: TObject); begin Png :=...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru