C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

стр.: (2) < [1] 2 >
узнать имя компонента для которого, вызвано всплывающее меню
kea
Отправлено: 29.12.2005, 11:21


Станционный диспетчер

Группа: Участник
Сообщений: 80



Здравствуйте!
Вызываю PopupMenu либо с компонента TChart либо с компонента TMemo. Как узнать с какого компонета вызван всплывающее меню в обработчике события OnClick для пункта меню?
gvg
Отправлено: 29.12.2005, 12:24


Машинист паровоза

Группа: Участник
Сообщений: 222



А Sender в OnContextPopup не пойдет?
kea
Отправлено: 29.12.2005, 22:28


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (gvg @ 29/12/2005, 12:24)
А Sender в OnContextPopup не пойдет?

Спасибо.
Подскажите, пожалуйста, как мне узнать имя конкретного объекта (например, MyChart) в обработчике OnContextPopup.
AVC
Отправлено: 30.12.2005, 09:13


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

А Sender в OnContextPopup не пойдет?

Не пойдет. Sender = этому popup.

Можно попробовать OnMouseDown (попробовал — плохо)
Нужно искать объект под курсором в момент PopUp

Отредактировано AVC — 30/12/2005, 08:40
gvg
Отправлено: 30.12.2005, 09:34


Машинист паровоза

Группа: Участник
Сообщений: 222



Это я немного поторопился. Sender не нужен. OnContextPopup — у компонентов, на которых вызывается меню, т.е. компонент известен. Остается воспользоваться этим.
AVC
Отправлено: 30.12.2005, 09:41


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (gvg @ 30/12/2005, 08:34)
Это я немного поторопился. Sender не нужен. OnContextPopup — у компонентов, на которых вызывается меню, т.е. компонент известен. Остается воспользоваться этим.

Как? Он protected.
gvg
Отправлено: 30.12.2005, 10:30


Машинист паровоза

Группа: Участник
Сообщений: 222



QUOTE (AVC @ 30/12/2005, 09:41)
QUOTE (gvg @ 30/12/2005, 08:34)
Это я немного поторопился. Sender не нужен. OnContextPopup — у компонентов, на которых вызывается меню, т.е. компонент известен. Остается воспользоваться этим.

Как? Он protected.

Ну, например, в OnContextPopup присвоить какое либо значение Tag у PopupMenu. Потом, при обработке выбора меню, прочитать это значение... Вариантов — куча.
avc*
Отправлено: 30.12.2005, 11:07


Не зарегистрирован







Вы не поняли. У стандартного компонента к этому свойству нет доступа — нельзя простым способом подставить свой обработчик.
gvg
Отправлено: 30.12.2005, 11:44


Машинист паровоза

Группа: Участник
Сообщений: 222



По всей видимости не поняли Вы. Я говорю про событие (event) OnContextPopup, которое наследуется от TControl и доступно. Я же не понимаю другое — про какое свойство Вы говорите?
Admin
Отправлено: 30.12.2005, 11:47


Владимир

Группа: Администратор
Сообщений: 1190



CODE

void __fastcall TForm1::PopupMenu1Popup(TObject *Sender)
{
     if(PopupMenu1->Tag == 0) ShowMessage("Memo1ContextPopup");
     else if(PopupMenu1->Tag == 1) ShowMessage("Panel1ContextPopup");
     else ShowMessage("unknown");

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Memo1ContextPopup(TObject *Sender,
     TPoint &MousePos, bool &Handled)
{
    PopupMenu1->Tag = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1ContextPopup(TObject *Sender,
     TPoint &MousePos, bool &Handled)
{
    PopupMenu1->Tag = 1;
}
//---------------------------------------------------------------------------
Admin
Отправлено: 30.12.2005, 11:52


Владимир

Группа: Администратор
Сообщений: 1190



Или искать объект под курсором в момент PopUp .

CODE

void __fastcall TForm1::PopupMenu1Popup(TObject *Sender)
{
     TPoint pt = PopupMenu1->PopupPoint;
     ....
}
gvg
Отправлено: 30.12.2005, 11:59


Машинист паровоза

Группа: Участник
Сообщений: 222



2Admin — ну да, именно так. Можно и по-другому
CODE

void __fastcall TForm1::Panel1ContextPopup(TObject *Sender,
     TPoint &MousePos, bool &Handled)
{
 PopupMenu1->Tag = int( Panel1 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1ContextPopup(TObject *Sender,
     TPoint &MousePos, bool &Handled)
{
 PopupMenu1->Tag = int( Memo1 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PopupMenu1Popup(TObject *Sender)
{
 ShowMessage( ((TControl*)PopupMenu1->Tag)->Name );
}
avc*
Отправлено: 30.12.2005, 12:19


Не зарегистрирован







QUOTE (gvg @ 30/12/2005, 11:44)
По всей видимости не поняли Вы. Я говорю про событие (event) OnContextPopup, которое наследуется от TControl и доступно. Я же не понимаю другое — про какое свойство Вы говорите?

И я про это же. Извиняюсь.
Как назло форма, котрая была под рукой, была забита DBGrid'ами — чуть ли не единственный компонент у которого это событие не "расшарено". А ставить на форму Memo и Chart — поленился.
Виноват.
А ведь еще и не пил. biggrin.gif
kea
Отправлено: 30.12.2005, 15:34


Станционный диспетчер

Группа: Участник
Сообщений: 80



Здравствуйте! Спасибо за ответы. Мне тоже первым длом пришла мысль про тэги.
Поздравляю всех с наступающим Новым годом!
kea
Отправлено: 01.01.2006, 20:44


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (gvg @ 30/12/2005, 11:59)
2Admin — ну да, именно так. Можно и по-другому
CODE

void __fastcall TForm1::Panel1ContextPopup(TObject *Sender,
TPoint &MousePos, bool &Handled)
{
PopupMenu1->Tag = int( Panel1 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1ContextPopup(TObject *Sender,
TPoint &MousePos, bool &Handled)
{
PopupMenu1->Tag = int( Memo1 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PopupMenu1Popup(TObject *Sender)
{
ShowMessage( ((TControl*)PopupMenu1->Tag)->Name );
}

Здравствуйте! Поясните, пожалуйста, как работает следующий код:
PopupMenu1->Tag = int( Panel1 );

int( Panel1 ) даст уникальное значение в пределах одной программы?

(просто еще не встречалось приведение имени своено компонента к типу int)
kea
Отправлено: 04.01.2006, 12:34


Станционный диспетчер

Группа: Участник
Сообщений: 80



Здравствуйте! Ответьте, пожалуйста на мой последний вопрос, а то тема скоро скроется из виду.
Guest
Отправлено: 04.01.2006, 13:22


Не зарегистрирован







Panel — указатель на экземпляр класса TPannel. Принято считать (в С это задекларировано) что указатель и переменная типа int имеют одинаковый размер в памяти и вообще чуть ли не синонимы.
Будет ли этот указатель иметь ункальное значение в рамках приложения — да если форма на которой расположен TPanel создается один раз. Гарантировано он будет иметь уникальное значение в рамках одной формы пока для неё не вызван деструктор.
kea
Отправлено: 04.01.2006, 14:19


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (Guest @ 04/01/2006, 13:22)
Panel — указатель на экземпляр класса TPannel. Принято считать (в С это задекларировано) что указатель и переменная типа int имеют одинаковый размер в памяти и вообще чуть ли не синонимы.
Будет ли этот указатель иметь ункальное значение в рамках приложения — да если форма на которой расположен TPanel создается один раз. Гарантировано он будет иметь уникальное значение в рамках одной формы пока для неё не вызван деструктор.

Здравствуйте! Спасибо за ответ. Мне вообщето уникалность нужна в пределах одной формы., которую создаю и делаю модальной по мере необходимости. Это будет обеспечиваться? Числа использовать тоже интереса нет.
Guest
Отправлено: 04.01.2006, 14:45


Не зарегистрирован







QUOTE

пределах одной формы ...это будет обеспечиваться?

Да.
Это же результат работы распределителя памяти, а он пытается гарантировать что распределенная памать до её освобождения использоваться не будет.
kea
Отправлено: 04.01.2006, 14:47


Станционный диспетчер

Группа: Участник
Сообщений: 80



Здравствуйте! извините за детский вопрос. А как все же правильно будет записываться преобразование типов:
int(Panel)
или
(int)Panel1
kea
Отправлено: 04.01.2006, 14:51


Станционный диспетчер

Группа: Участник
Сообщений: 80



Как применять в операторе switch

switch ( PopupMenu1->Tag )
{

case (что здесь писать): Func(); break;

default: break;
}
Guest
Отправлено: 04.01.2006, 15:19


Не зарегистрирован







QUOTE

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


Преобразование типов — (int)Panel, а конструктор класса int — int(Panel). В контексте вашей проблемы это безразлично.

QUOTE

case (что здесь писать): Func(); break;

Все что угодно, приводимое целому.
kea
Отправлено: 04.01.2006, 17:04


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (Guest @ 04/01/2006, 15:19)
QUOTE

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


Преобразование типов — (int)Panel, а конструктор класса int — int(Panel). В контексте вашей проблемы это безразлично.

QUOTE

case (что здесь писать): Func(); break;

Все что угодно, приводимое целому.

Здравствуйте! Меня интересовало как в операторе case прописать тот компонент для которого нужно выполнить конкретное действие.

Конструкция:
switch( PopupMenu1->Tag )
{
case (int)Panel1 : Func(); break;
default: break;
}

не компилируется. Что-то недопонимаю. Подскажите, пожалуйстаю
Guest
Отправлено: 04.01.2006, 18:17


Не зарегистрирован







QUOTE

case (что здесь писать): Func(); break;

что здесь писать — константное выражение.

Вы можете написать так
if (...->Tag == int(Panel)) func1...
else if (...->Tag == int(Memo)) func2...
kea
Отправлено: 04.01.2006, 18:39


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (Guest @ 04/01/2006, 18:17)
что здесь писать — константное выражение.

Спасибо за ответы!

1.то есть switch в данном случае не годится?

2. выражение int( Panel ) эффективнее по количесвту операций и скорости выполнения, чем (int)Panel. Поскольку в втором случае преобразуется указатель на TPanel к типу int и затем создается число типа int, а во первом случае сразу создается число типа int с помощью копирующего конструктора. Как вы думаете?

AVC
Отправлено: 05.01.2006, 09:01


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

выражение int( Panel ) эффективнее по количесвту операций и скорости выполнения, чем (int)Panel. Поскольку в втором случае преобразуется указатель на TPanel к типу int и затем создается число типа int, а во первом случае сразу создается число типа int с помощью копирующего конструктора. Как вы думаете?

Вы пишете драйвер? Сколько тысяч раз в секунду вам нужно делать такое преобразование? Если это критично то лучше создать пару переменных нужного типа и сделать преобразования заранее и один раз. smile.gif

PS. Простой эксперимент показывает, что умный компилятор (что логично) для обоих способов записи порождает одинаковый код (помните — указатель и int это почти синонимы).
CODE

void somefun(int);

void __fastcall TForm1::Button2Click(TObject *Sender)
{
somefun(int(Memo1));
somefun((int)Memo1);
asm {qwerty}
}
// asm
mov       eax,dword ptr [ebx+748]
push      eax
call      @@somefun$qi

mov       edx,dword ptr [ebx+748]
push      edx
call      @@somefun$qi
kea
Отправлено: 05.01.2006, 12:17


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (AVC @ 05/01/2006, 09:01)
[QUOTE]
Вы пишете драйвер? Сколько тысяч раз в секунду вам [CODE]

Здравствуйте! Спасибо за ответ. Драйверов пока не пишу. Надо повышать свой уровень в написании обычных программ. Вопросы эффективности кода всегда интересовали. У Михаила Фленова в книге "Что умеюют хакеры" про это интересно написано (для Delphi, но все равно интересно).
gvg
Отправлено: 06.01.2006, 12:30


Машинист паровоза

Группа: Участник
Сообщений: 222



QUOTE (kea @ 04/01/2006, 18:39)
1.то есть switch в данном случае не годится?

1. годится, если использовать также как и присваивание тэга
CODE

case int(Panel1):

По использованию тэга для хранения ссылки описано в его хэлпе (к вопросу о размерности int и указателя)
QUOTE

...It can be used for storing an additional integer value or it can be typecast to any 32-bit value such as a component reference or a pointer.


Отредактировано gvg — 06/01/2006, 12:31
kea
Отправлено: 07.01.2006, 15:19


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (gvg @ 06/01/2006, 12:30)
QUOTE (kea @ 04/01/2006, 18:39)
1.то есть switch в данном случае не годится?

1. годится, если использовать также как и присваивание тэга
CODE

case int(Panel1):


Здравствуйте!
Использую приведенную конструкцию case int(Panel1): в операторе switch:
Сразу компилятор выдает ошибку:
E2313: Constant expression required.

Наверное, недопонял. Подскажите.
kea
Отправлено: 07.01.2006, 15:26


Станционный диспетчер

Группа: Участник
Сообщений: 80



Здравствуйте!

Верочтно, луше определить на глобальном уровне ( в классе формы )
int Panel1Ptr;

В обработчике FormCreate присвоить ему значение
Panel1Ptr = int( Panel1 ).

И уж затем использовать в операторе switch:
case Panel1Ptr: MyFunc(); break;
стр.: (2) < [1] 2 >
Вернуться в Вопросы программирования в C++Builder