Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

TAction и горячие клавиши

3.2K
12 августа 2007 года
nikipelovav
152 / / 12.04.2006
Для объекта TAction назначаю код горячей клавиши,
например

 
Код:
actRecordImageShow->ShortCut = 122; // клавиша F11


и если удерживать нажатой клавишу F11 (в данном примере)
то обработчик события будет запускаться N-ное количество раз.

Понять могу, код нажатой клавиши из очереди буфера клавиатуры активирует действие и т.д. Но, ведь такое поведение не всегда необходимо и допустимо (с точки зрения программы)!

Контролировать запуск какого-либо метада по событию
OnKeyDown не всегда удобно.

Есть ли красивое решение задачи:

По нажатии и удержании клавиши TAction->Execute() выполняется
один раз.
8.8K
12 августа 2007 года
Se AD WMD
165 / / 10.01.2007
Почемуб не ввести булевскую переменную например таким макаром:
На нажатие:
if(!bool)
{
actRecordImageShow->ShortCut = 122;
bool=true;
}
На отпускание
bool=false;
3.2K
13 августа 2007 года
nikipelovav
152 / / 12.04.2006
Ты внимательно читал моё сообщение?

Цитата:

Контролировать запуск какого-либо метада по событию
OnKeyDown не всегда удобно.



Объекты TAction должны "жить" сами по себе. У меня впроекте
некоторые объекты окна связаны с индивидуальными обработчиками
OnKeyDown и OnKeyUp. Помнить о том, чтобы в них ( а также создавать
для других объектов ) описывать для всех TAction такую конструкцию, это не очень хорошая идея. ;)

Я пробовал вариант такой:

В обработчике TAction использовать отсечку лишних запусков

Код:
{
  if ( ImageShowRun ) return;

  ImageShowRun = true;
  try
  {
    ... что-то делаем ...
  }
  catch(...){}
  ImageShowRun = false;
}


Но, к сожалению, это не помогает!

У меня задача - по нажатию клавиши F11 отобразить окно с изображением (берётся из ftBlob поля записи). Повторное нажатие
этой же клавиши (что, Я думаю, удобно) должно закрыть окно просмотра.

Ниже приведенный пример не помогает.
После того как "отсечка" по истинному значению ImageShowRun помогла
исключить повторные запуски, выполнение обработчика TAction
завершилось, ImageShowRun принял значение ЛОЖЬ и следующий
запуск TAction (по причине удержания клавиши F11) запустил заново
обработчик TAction, который, по совему принципу работы, закрыл окно
просмотра! Вот и получается, что Я вижу "мелькающее окно".
10
13 августа 2007 года
Freeman
3.2K / / 06.03.2004
Цитата: nikipelovav
Вот и получается, что Я вижу "мелькающее окно".


А что должно быть? По-моему, утопление F11 к этому и должно привести. Упал-отжался - открыл-закрыл.

2.0K
13 августа 2007 года
WidowMaker
212 / / 05.04.2005
Я давно не пользовался билдером, но почему бы не нагрузить этой проблемой твое окно просмотра:
Пусть Action вызывает только Show и Hide, а окно просмотра в обработчике OnShow реализует остальную логику.
3.2K
13 августа 2007 года
nikipelovav
152 / / 12.04.2006
Как жаль, что мои сообщения читают те,
кто "давно не пользовался билдером" ;(

Уважаемые участники форума, пожалуйста,
давайте дельные советы, а не высказывайте мнения,
типа "спасение утопающих, дело рук самих утопающих".

Наводящий вопрос на тему:
возможно поможет в конце обработчика события TAction
очищать буфер клавиатуры. Как это сделать?
92
13 августа 2007 года
Тень Пса
2.2K / / 19.10.2006
не, здесь однозначно только KeyUp/KeyDown.

на KeyDown показал, на KeyUp скрыл, окно на OnShow показало картинку.... чего сложного... даже не понимаю.

имхо, оптимально. без всяких очисток буфера клавиатуры...

[quote="nikipelovav"]
Объекты TAction должны "жить" сами по себе. У меня впроекте
некоторые объекты окна связаны с индивидуальными обработчиками
OnKeyDown и OnKeyUp. Помнить о том, чтобы в них ( а также создавать
для других объектов ) описывать для всех TAction такую конструкцию, это не очень хорошая идея.
[/quote]
ничего они никому не должны, а написать несколько лишних (которые и не будут лишними) строчек кода... если это проблема, то извините :)

PS: и как раз "тот кто давно не пользовался билдером" тоже говорит правильно.
3.2K
13 августа 2007 года
nikipelovav
152 / / 12.04.2006
Вот, что говорил "тот кто давно не пользовался билдером":

"Пусть Action вызывает только Show и Hide, а окно просмотра в обработчике OnShow реализует остальную логику."

И что же здесь правильного, если переполненый кодом нажатой клавиши
буфер клавиатуры будет вызывать и вызывать обработчик TAction.

И на основании чего "Пусть Action вызывает только Show и Hide".
Если на основании свойства Окно->Visible, то это тоже, что и
"... реализует остальную логику".

Я понимаю, что описать OnKeyDown и OnKeyUp даст желаемый результат.
Я это ранее уже делал с другим окном.

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

Я воспользовался поиском на форуме, оказалось такой вопрос уже задавали. Предложенным решением было использование таймера.

Логическую переменную, которая разрешала выполнение тела обработчика TAction контролировал Таймер. Как Я понимаю, он ждал
0,3 - 1,0 секунды после завершения работы обработчика TAction
и лишь тогда изменял значение логической переменной. При этом
предполагается , что за время 0,3 - 1,0 сек. опусташится буфер клавиатуры.

Но неужели это единственный способ. А если в программе 50 TAction,
что, делать 50 таймеров?
10
14 августа 2007 года
Freeman
3.2K / / 06.03.2004
Цитата: nikipelovav
Но неужели это единственный способ.


Можно ещё VCL переписать, чтобы TAction по-человечески был, а не сбоку припёка.

Цитата: nikipelovav
А если в программе 50 TAction,
что, делать 50 таймеров?


Можно шарить единственный.

3.2K
14 августа 2007 года
nikipelovav
152 / / 12.04.2006
Спаибо Всем за обсуждение. Я нашел решение.

Во первых, надо признаться, Я сам себя немного запутал!
Но мне никто не заметил, что что-то не так!

Вот что Я писал:
Цитата:

У меня задача - по нажатию клавиши F11 отобразить окно с изображением (берётся из ftBlob поля записи). Повторное нажатие
этой же клавиши (что, Я думаю, удобно) должно закрыть окно просмотра.
... Вот и получается, что Я вижу "мелькающее окно".



TAction на главной форме получает информацию о нажатой клавише и генерирует OnExecute. Но как только обработчик OnExecute отображает другое окно, сообщения о нажатой клавише поступают в это окно, а TAction умолкает!!!

Почемуже при удержаной горячей клавише у меня окно закрывалось?
Ответ прост. Вы мне советовали использовать обработчики OnKeyDown и OnKeyUp. А Я Вам писал, что уже использовал их в подобных целях!
Просто забыл!!!! ;))) В обработчике OnKeyDown Я закрывал форму.
Вот и получалось "что Я вижу 'мелькающее окно'".

Вернёмся теперь к повторному запуске OnExecute.
Действительно помогает отсечка повторных запусков логической переменной. Но, чтобы не погрязнуть в огромном количестве однотипных структур обработчиков OnExecute:

Код:
if ( IsRun ) return; // выход, если сейчас выполняется
 
  IsRun = true;
 
  try
  {
     // делаем что-либо
  }
  catch(...){}
 
  IsRun = false;


Я для себя решил. Создам класс, порождённый от TAction и буду
все обработчики событий присваивать собственному указателю,
который будет вызываться в выше описанной структуре кода
из стандартного обработчика OnExecute.

Вот пример кода:
Код:
class BAction : public TAction
{
  public:
        __fastcall BAction(Classes::TComponent* Owner);

        // пользовательский обработчик OnExecute
        TNotifyEvent OnExecuteB;

  protected:

        // собственный обработчик OnExecute
        void __fastcall BActionExecute ( TObject *Sender );

        // признак выполнения метода
        bool   OnExecuteRun;
};

__fastcall BAction::BAction(Classes::TComponent* Owner): TAction(Owner)
{
  OnExecute    = BActionExecute;
  OnExecuteRun = false;
}

void __fastcall BAction::BActionExecute ( TObject *Sender )
{
  if ( OnExecuteRun )  return; // выход, если сейчас выполняется
 
  OnExecuteRun = true;
 
  try { OnExecuteB( Sender ); } catch(...){} // пользовательский метод
 
  OnExecuteRun = false;
}
92
14 августа 2007 года
Тень Пса
2.2K / / 19.10.2006
никто и не мог заметить что "что-то не так", потому как куска кода не было :) ну а телепатов здесь вроде нет ) это не тв-шоу "битва экстрасенсов" :D

Поздравляю с решением проблемы :) Удачи!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог