Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Горячие клавиши 
:(
    Опции темы
Letchik
Дата 21.6.2010, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Даже не знаю с чего начать...  smile 
Ну для начала всем привет!
Перебрал кучу вариантов, как можно легче реализовать поддержку горячих клавиш. Все методы работают, но у каждого есть один такой минус, который портит ВСЁ! Вот основные:

1) Акселераторы.
Плюс: легко и удобно.
Минус: Откликается во всех окнах приложения. Можно конечно это блокировать, но это будет "через попу".

2)RegisterHoKey()
Плюс: кажется, что леко и удобно.
Минус: Тот же что и у первого метода. В добавок, если работаю в другой программе, (например в скайпе сообщение хочу отправить кнопочкой Enter), кнопочка не работает. 

3)Локальный хук для каждого диалогового окна программы.
Плюс: Почти полный контроль над вводом с клавиатуры.
Минус: Сложно, не удобно, есть мелкие глюки, нейтрализовать которые очень проблематично.

Вопрос: как правильно реализовать поддержку горячих клавиш. Надо учитывать то, то одна и таже клавиша может использоватья и в главном окне, и в дочерном (например Enter или Insert), только выполнять она будет разные операции. 

Помогите кто может! smile 
PM MAIL Skype   Вверх
Dem_max
Дата 21.6.2010, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Даже не знаю с чего начать... 

Нужно сначала определиться для чего тебе горячие клавиши и что они должны делать. 



--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Letchik
Дата 21.6.2010, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Горячие клавиши не мне, а пользователю  smile 

Приведу пример:

Клавиша Insert в главном окне должна открывать диалоговое окно добавления новой записи. В этом диалоговом окне есть два варианта дальнейших действий. Можно нажать ОК (или Enter). Тогда запись добавитья и окно закроется. Можно нажать "Next" (или Insert), тогда запись добавитья, но окно не закроется, а освободится для ввода следующей записи.
PM MAIL Skype   Вверх
GremlinProg
Дата 21.6.2010, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

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



а что мешает перед вызовом диалога освободить хоткей Insert, 
после чего, в самом диалоге повторно его использовать, уже для другого действия,
а по закрытии диалога - снова назначить хоткей insert для работы в главном окне

Это сообщение отредактировал(а) GremlinProg - 21.6.2010, 11:54


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Dem_max
Дата 21.6.2010, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



тогда все проще, отлавливай WM_KEYDOWN и определяй код нажатой клавиши, в зависимости от открытого окна делай различные действия на тот же Insert.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Earnest
Дата 21.6.2010, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Действительно, зачем тебе горячие клавиши. Смысл их как раз в полной прозрачности - где бы ни нажал, выполняется некоторое действие. А локальная обработка - через ловлю WM_KEYDOWN, в каждом окне по своему.


--------------------
...
PM   Вверх
Letchik
Дата 21.6.2010, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Именно это я и хотел сделать изначально.
Однако Enter скорее всего будет нажат тогда, когда курсор будет в каком-то эдитбоксе. А в таком случае WM_KEYDOWN не посылается окну родителю.
PM MAIL Skype   Вверх
Peter
Дата 21.6.2010, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Когда-то такую проблему для себя решал так: в главном цикле сообщений проверял
Код
        if(messages.message == WM_KEYDOWN && messages.wParam == 13)
           if(messages.hwnd == hEdtSrc || messages.hwnd == hEdtDest
              || (bInComboVol && !bOpenComboVol))
              PostMessage(hwnd, WM_COMMAND, ID_DIV, 0);
Здесь hEdtSrc и hEdtDest - два эдит-бокса, а hwnd - главное окно. Еще две переменные показывают, находится ли фокус в комбобоксе и раскрыт ли этот комбобокс (а то если он раскрыт, то на Enter он сам должен отреагировать). Таким образом, программа сделает, что нужно при нажатии Enter, даже если фокус в окошечках редактирования hEdtSrc и hEdtDest.


--------------------
всё, что делаете, делайте от души, как для Господа (Послание апостола Павла колоссянам, 3:23).
PM MAIL WWW   Вверх
TGrey
Дата 21.6.2010, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Именно это я и хотел сделать изначально.
Однако Enter скорее всего будет нажат тогда, когда курсор будет в каком-то эдитбоксе. А в таком случае WM_KEYDOWN не посылается окну родителю.

А если самому послать это сообщение окну родителю?

Это сообщение отредактировал(а) TGrey - 21.6.2010, 15:39
PM MAIL   Вверх
Letchik
Дата 21.6.2010, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

А если самому послать это сообщение окну родителю?


С удовольствием, только когда? 
PM MAIL Skype   Вверх
TGrey
Дата 21.6.2010, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Когда? Когда оно приходит возможно? Возможно заменить оконную процедуру Едита, ну или чего там, в ней проверять, что приходит, заодно выполнять нужные действия и в любом случае вызывать оригинальную процедуру. Только наверно в таком случае чем больше элементов, и то каждый надо обрабатывать, тогда им всем ставить одну процедуру(свою), а потом вызывать ихние.

Или может хук всунуть в приложение, пусть ловит все сообщения, а там уже фильтровать, что куда. 
А прочитал, что хук не устраивает. Просто не вижу в чем его проблема? 1 хук, 1 фильтрующая функция, в которой проверять нужные сообщения, по сути забивать на эту функцию и выполнять нужные себе действия.

Это сообщение отредактировал(а) TGrey - 21.6.2010, 16:55
PM MAIL   Вверх
Letchik
Дата 21.6.2010, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

Возможно заменить оконную процедуру Едита,

Это называется сабклассингом (Subclassing). Это я тоже пробовал. Но никому не советую использовать его в данных целях. Слишком много обработчиков получается. Дело в том, что обработчик Едита не подходит любому другому типу элементу управления (и наоборот). Для каждого типа прийдётся создавать свой обработчик. И это, извините, тоже через попу. 
Я склоняюсь к локальному хуку. Это сложно и кажется что неудобно, но я получаю почти полный контроль над вводом.
GremlinProg посоветовал освобождать хоткей при открытии диалога. Так не пойдёт. Пользователь должен иметь возможность работать в главном окне несмотря на открытое диалоговое окно.

Что касается локального хука. Есть пара идей, которые я реализую в ближайшее время. Как реализую - поделюсь опытом.
По любому, каждое диалоговое окно будет иметь свой хук. Однако хук действует на все открытые окна приложения. Поэтому вначале обработчика мы будем проверять, активно ли нужное нам окно. Если активно - обрабатываем нажатие клавиши, если нет - то это нам не надо.
PM MAIL Skype   Вверх
TGrey
Дата 21.6.2010, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А какая разница в оконных процедурах Едита или чего либо? Структура то одинаковая. Я же не говорю все сообщения отлавливать. К примеру нужны же только клавиши, то есть только 1 сообщение, и в нем же и вообще в любом случае вызывать стандартный. По типу:
Код

...
switch(msg)
{
case WM_CHAR:
      //actions
      return CallWindowProc(....)
}
      return CallWindowProc(....)


То есть выполнятся нужные вам действия, а потом все пойдет дальше, как ни в чем не бывало, конечно если там тоже, что-то будет на эту кнопку обрабатываться, то получится не красиво=)

Ну а тогда если Диалог не модальный, тогда да... Горяие клавиши как-то ни к селу ни к городу=) Тогда точно, что надо проверять на активность окна. Хотя это тоже не ахти=)
PM MAIL   Вверх
Earnest
Дата 22.6.2010, 07:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Вообще-то можно вместо хука вставить в главный цикл сообщений функцию-фильтр, что-то типа TranslateAccelerators, только свою. Можно разработать структуру данных, которая будет связывать хотя бы таблицу акселераторов с окном и использовать TranslateAccelerators. Или просто для каждого окна вызывать свой вариант фильтра. В общем, масса вариантов. А хук - это микроскопом гвозди. Я бы сказала, что в своем процессе хук нужно применять тогда, когда нужно добавить какую-то совершенно не связанную с функциональностью окна обработку. Или когда нужно ловить что-то в других, не подчиненных окнах.
В данном же случае, хук тебе потребуется не один - обработка-то разная. А если сделать просто каркас на основе таблиц соответствий - то функция-фильтр в основном цикле справиться ничуть не хуже.


--------------------
...
PM   Вверх
Letchik
Дата 22.6.2010, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всё-таки я решил попробовать усовершенствовать мой локальный хук. Представьте, получилось. Ниодин метод реализации горячих клавиш не даёт такой гибкости как хук. 
Казалось бы, это сложно, неудобно (только с первого взгляда), но всё совсем наоборот. Надо лишь проверять какое окно активно в данный момент. Если активно, то соответственно ввод произвёден именно в это окно. 
Решилось пару проблем касающихся TАВ"а. Например едит бокс со стилем ES_MULTILINE (что-то в этом роде) не отвечает на нажатие Таба. Поэтому я написал собственную обработку этой клавиши (Shift + TAB, TAB). Работает прекрасно.
В топике была идея использовать сабклассинг. Напоминаю, для данной цели он не подходит. Представьте, в диалоговом окне есть контролы трёх разных типов. Это значит, что для каждого типа контрола нужен свой обработчик. Три (!) обработчика, когда можно обойтись только одним. Сабклассинг полезен тогда, когда этот контрол выполняет что-то конкретное, что-то такое, что другие контролы не должны выполнять. А локальный хук полезен когда все контролы (или их большинство) отвечают одним и тем-же действием на некоторое сообщение. 
Короче. Я выбираю Хук!!!  smile 
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


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

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


 




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


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

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