Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание компонента. Сообщения... Работа с сообщениями 
V
    Опции темы
dencraft
Дата 16.5.2011, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Что-то я совсем запутался smile. 
Пишу новый компонент на основе базового. Нужно переопределять стандартные действия над компонентом UpDown. При нажатии на мышу должно отрабатывать мое событие, а событие компонента не должно. Вроде сделал - все работает. Но как только добавил второй экземпляр компонента на форму - начались проблемы. На сообщения стал отвечать именно второй компонент, первый стал работать стандартно. 

Внутри компонента я переопределил методы Application->OnMessage и Form->WindowProc. Ламерский вопрос но все же....В чем различие между этими обработчиками Application->OnMessage и Form->WindowProc. Так есть ли разница где размещать код в этих обработчиках. И как определять в каком я нахожусь объекте. Узнать например какой у меня HWND компонента к которому пришло сообщение

кусок кода:
Код


void __fastcall TUpDownEx::WndProc1(Messages::TMessage &Message)
{
   // перехватываем сообщения
   switch (Message.Msg)
   {
      case WM_SETCURSOR:
      {
         FDataDebug = Message.WParam;

          // Проверяем, мышь внутри ли компонента?
         fInComponent = ((HWND) Message.WParam == this->Handle) ? true : false;
          // ...
      }
   }
OwnerWndProc(Message);
}


и дальше я реализую новые возможности тут

Код

void __fastcall TUpDownEx::AppMessage( tagMSG &Msg, bool &Handled)
{
 switch (Msg.message)
 {
   case WM_LBUTTONDOWN:      // Мышь: Нажатие левой кнопки
   {
    if (fInComponent)
    {...
      Handled=true;
    }
   }
 }
}




PM MAIL   Вверх
dencraft
Дата 16.5.2011, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот еще. Кажется начинаю понимать где собака зарылась....
Код

__fastcall TUpDownEx::TUpDownEx(TComponent* Owner)
   : TUpDown(Owner)
{
   if (!ComponentState.Contains(csDesigning)) // Только в режиме выполнения
   {
      //Получить собственника компонента
     FOwnerForm=(TForm*)Owner;

      // Переопределить функцию окна собственника
     OwnerWndProc=FOwnerForm->WindowProc;
     FOwnerForm->WindowProc=WndProc1;

      // Переопределить событие приложения
     FOldAppMessage = Application->OnMessage;
     Application->OnMessage = AppMessage;

   }
}

//---------------------------------------------------------------------------
__fastcall TUpDownEx::~TUpDownEx(void)
{
   if (!ComponentState.Contains(csDesigning)) // Только в режиме выполнения
   {
      //Востановить функцию окна собственника
     FOwnerForm->WindowProc=OwnerWndProc;
      // Востановить событие приложения
     Application->OnMessage=FOldAppMessage;


   }
}


Получается когда выполняется конструктор, он изменяет указатели на методы обработки сообщений. Но тогда как быть со вторым компонентом и последующими? При выполнении конструктора второго компонента, он затирает FOwnerForm->WindowProc новым своим значением. И сообщения идут уже последнему компоненту обновившему FOwnerForm->WindowProc. Как тут быть?
PM MAIL   Вверх
borisbn
Дата 17.5.2011, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Цитата(dencraft @  16.5.2011,  17:59 Найти цитируемый пост)
Как тут быть?

переопределять WindowProc не Owner'а, а свой
Код

OwnerWndProc=this->WindowProc;
this->WindowProc=WndProc1;

а зачем вообще перехватывать все сообщения приложения (Application->OnMessage) ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
dencraft
Дата 17.5.2011, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



А мне нужно перехватывать сообщение мыши за пределами компонента и даже формы. По сути у меня все работает через SetCapture(Application->Handle); Я в Application->OnMessage перехватываю сообщения WM_SETCURSOR, далее относительно него, я уже определяю какая кнопка была нажата. Дело в том, что мне нужно еще отловить момент отпускания кнопки, который может быть не только над данным компонентом, но и над главной формой или за ее пределами, или другим компонентом. 
Через пары BEGIN_MESSAGE_MAP/END_MESSAGE_MAP не получается перехватить отпускание мыши над другими компонентами. И почему-то не работает SetCapture(Application->Handle).

Это сообщение отредактировал(а) dencraft - 17.5.2011, 11:30
PM MAIL   Вверх
xvr
Дата 17.5.2011, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(dencraft @  16.5.2011,  16:52 Найти цитируемый пост)
Внутри компонента я переопределил методы Application->OnMessage и Form->WindowProc.
Это делать КАТЕГОРИЧЕСКИ нельзя!

Цитата(dencraft @  17.5.2011,  11:21 Найти цитируемый пост)
А мне нужно перехватывать сообщение мыши за пределами компонента и даже формы. По сути у меня все работает через SetCapture(Application->Handle);

Делайте SetCapture(Handle);, т.е. от своего (компонента) Handle'а, а не приложения

PM MAIL   Вверх
borisbn
Дата 17.5.2011, 13:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Цитата(dencraft @  17.5.2011,  11:21 Найти цитируемый пост)
А мне нужно перехватывать сообщение мыши за пределами компонента и даже формы

для этого существует TApplicationEvents. делаешь так
Код

// h-файл
TApplicationEvents *appEvents;
// cpp-файл
// Конструктор
  appEvents = new TApplicationEvents( 0 );
  appEvents->OnMessage = onMessage;
// Деструктор
  delete appEvents;
//
void __fastcall MyClass::onMessage(tagMSG &Msg, bool &Handled)
{
  if ( Msg.hwnd == Handle ) // наше окно
  {
       switch ( Msg.message )
       {
            case WM_KEYDOWN:
                ...
            break;
           ...
        }
   }
   else // другое окно
   {
       ...
   }




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
dencraft
Дата 23.5.2011, 03:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



C TApplicationEvents получилось. Но не до конца.  Это по сути то тот же WinProc в удобной оболочке. Но уже вроде работает раздельно. Но все же одна проблема осталась.
Я пользуюсь SetCapture(...) для перехвата всех сообщений мыши, даже если она вышла за пределы компонента, над которым я нажал кнопку мыши. Но вот за пределами главного окна программы, сообщения уже идут мимо приложения, т.е. мимо WinProc. Вот поэтому я тогда и использовал переопределенный обработчик Application->OnMessage. Только туда направляются все сообщения WM_MOUSEMOVE даже если мышь за пределами главного окна. Это работает только при нажатии кнопки и удержании ее в нажатом положении при перемещении курсора за пределы главного окна приложения. 

Хотелось бы все реализовать независимо от основного приложения. Но похоже тут придется писать какой-нибудь ретранслятор сообщений компонентам. Что-то вроде автоматической рассылки сообщений из сообщений приложения этому компоненту если совпадает его Handle. Не хотелось бы, т.к. это разрушает саму идею компонента - "все в одном". 



Это сообщение отредактировал(а) dencraft - 23.5.2011, 03:27
PM MAIL   Вверх
dencraft
Дата 30.5.2011, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Решил проблему несколько по-другому. Может кому будет интересно. 

Использую TApplicationEvents. При нажатии кнопки мыши запускается таймер и SetCapture(). По этому таймеру я определяю координаты мыши через GetCursorPos(). SetCapture нужен для того чтобы отлавливались сообщения об отпускании мыши за пределом текущего компонента. 
Вот собственно и все. И без переопределения WinProc и Application->OnMessage. Все замечательно работает в любом количестве этих компонентов на форме.

Также, кому интересно, что это было и для чего. Это Spinner, созданный на основе TUpDown, значение Position которого можно менять не только нажатием на стрелки Up и Down, но и перетаскиванием мыши вверх и вниз. Если курсор выходит за край экрана, то он перебрасывается на противоположную сторону, тем самым обеспечивается бесконечное прокручивание. Весьма удобно для интерактивного изменения параметров и отображения результата в окне. 

Далее буду прикручивать к нему уже TEdit, работу с Float, округлением и может еще чего.


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

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

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

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

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


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

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


 




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


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

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