Vba excel перехват нажатия клавиш

Метод Application.OnKey используется в VBA Excel для назначения клавиши или сочетания клавиш, при нажатии которых запускается указанная процедура.

Application.OnKey — это метод VBA Excel, который назначает горячие клавиши или сочетания клавиш процедурам (макросам), которые начинают выполняются при нажатии этих клавиш.

Синтаксис

Синтаксис метода Application.OnKey:

Application.OnKey (Key, Procedure)

Параметры

Параметры метода Application.OnKey:

Параметр Описание
Key Строка, указывающая клавишу или сочетание клавиш. Обязательный параметр.
Procedure Строка, указывающая имя выполняемой процедуры. Необязательный параметр.

Параметры метода Application.OnKey указываются в коде VBA Excel без круглых скобок.

Параметр Key

Параметр Key может состоять из клавиш, представляющих буквы, которые записываются в фигурных скобках, например {a} или {b}. Функциональные клавиши, не представляющие буквы, используются в виде следующих кодов:

Клавиша Код
Backspace {BACKSPACE} или {BS}
Break {BREAK}
Caps Lock {CAPSLOCK}
Clear {CLEAR}
Delete или Del {DELETE} или {DEL}
Стрелка вниз {DOWN}
End {END}
Enter на цифровой клавиатуре {ENTER}
Enter ~ (тильда)
Esc {ESCAPE} или {ESC}
Help {HELP}
Home {HOME}
Insert {INSERT}
Стрелка влево {LEFT}
Num Lock {NUMLOCK}
Page Down {PGDN}
Page Up {PGUP}
Return {RETURN}
Стрелка вправо {RIGHT}
Scroll Lock {SCROLLLOCK}
Tab {TAB}
Стрелка вверх {UP}
F1–F15 {F1}–{F15}

Для создания сочетаний клавиш используются коды клавиш Shift, Ctrl и Alt, которые указываются перед функциональными и буквенными клавишами без фигурных скобок:

Клавиша Код
Shift + (плюс)
Ctrl ^ (крышка)
Alt (левая) % (процент)

Примеры:

  1. Код "^{w}" соответствует сочетанию клавиш Ctrl+w.
  2. Код "^+{t}" соответствует сочетанию клавиш Ctrl+Shift+t.
  3. Код "%{UP}" соответствует сочетанию клавиш Alt+↑.

Параметр Procedure

Имя процедуры записывается также, как отображается в окне «Макрос», которое открывается нажатием кнопки «Макросы» на вкладке «Разработчик»:

Если имя процедуры (макроса) уникальное, тогда имя модуля можно не указывать.


Пример назначения сочетания клавиш Ctrl+w процедуре Module10.Primer1:

Sub Primer()

Application.OnKey «^{w}», «Module10.Primer1»

End Sub

После выполнения процедуры Primer, процедура Module10.Primer1 начнет вызываться нажатием сочетания клавиш Ctrl+w.


Если вместо имени процедуры указать пустую строку, метод Application.OnKey отменит любые действия, ранее назначенные указанному сочетанию клавиш:

Application.OnKey «^{w}», «»

Если у заданного сочетания клавиш было действие по умолчанию, оно также выполняться не будет.


После запуска процедуры с методом Application.OnKey без указания параметра Procedure, отменяются все предыдущие действия метода Application.OnKey:

Если у заданного сочетания клавиш было действие по умолчанию, оно снова начнет выполняться.


Как добавить сочетания клавиш для быстрого доступа к элементам управления пользовательской формы смотрите в статье VBA Excel. Сочетания клавиш для кнопок.


 

ttt480

Пользователь

Сообщений: 395
Регистрация: 17.12.2015

#1

11.03.2017 09:53:23

Доброе утро, форумчане.
Помогите разобраться.

У меня есть макрос — клавиатурный хук. Выполняет он следующую функцию: перехватывает нажатия клавиш на клавиатуре — и запускает более мелкие макросы в соответствии с той клавишей — которая нажата (стрелки влево-вправо-вверх-вниз).
Но в нем есть одно ограничение — он перехватывает клавиатурные нажатия — только в том случае, если экселевская книга с его расположением является активной.

Как заставить макрос — перехватывать нажатия клавиш в любом случае, когда нажата одна из этих клавиш ?
(То есть даже когда, например в ТоталКоммандере на клавиатуре нажимается — клавиша «стрелка вверх» — макрос на экселевском листе — выводил бы сообщение «Up».)

Код
 Option Explicit
  Public Declare Function CallNextHookEx Lib "user32" _
     (ByVal hHook As Long, _
     ByVal nCode As Long, _
     ByVal wParam As Long, _
     ByVal lParam As Long) As Long
 Public Declare Function UnhookWindowsHookEx Lib "user32" _
    (ByVal hHook As Long) As Long
 Public Declare Function SetWindowsHookEx Lib "user32" _
    Alias "SetWindowsHookExA" _
    (ByVal idHook As Long, _
    ByVal lpfn As Long, _
    ByVal hmod As Long, _
    ByVal dwThreadId As Long) As Long
 Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
 Public Const WH_KEYBOARD = 2
 Public hHook As Long
 Public Hooked As Boolean
 Public Key As String
 Public Function KeyboardProc(ByVal nCode As Long, _
                              ByVal wParam As Long, _
                              ByVal lParam As Long) As Long
 'Debug.Print wParam      раскомментировать чтобы посмотреть что будет при нажатии других клавиш
         If wParam = 37 Or wParam = 39 Or wParam = 38 Or wParam = 40 Or wParam = 32 Then
             Hooked = True
             If wParam = 37 Then Key = "Left"
             If wParam = 39 Then Key = "Right"
             If wParam = 38 Then Key = "Up"
             If wParam = 40 Then Key = "Down"
             If wParam = 32 Then Key = "Space"
         End If
    KeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam)
 End Function

 Sub Start()
  Dim i As Long

  'Типа
  Do

  Hooked = False
    hHook = SetWindowsHookEx(WH_KEYBOARD, _
                             AddressOf KeyboardProc, _
                             0&, _
                             GetCurrentThreadId)

     'Пока не хукнули (Hooked=true в KeyboardProc)
   While (Not Hooked)
   i = i + 1
   Cells(1, 1) = i
 'Без этого зависает
   DoEvents
   Wend

    Call UnhookWindowsHookEx(hHook)
    MsgBox Key

 'И типа
  Loop
 End Sub

Прикрепленные файлы

  • 45645.xls (41.5 КБ)

Изменено: ttt48014.03.2017 02:27:06

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#2

11.03.2017 10:03:55

GetCurrentThreadId — насколько помню, получает ID текущего процесса(из которого вызвана), т.е. Excel. И хук будет работать только в том процессе, для которого создан, т.е. в Excel. Делайте выводы. По логике, если в этой строке:

Код
hHook = SetWindowsHookEx(WH_KEYBOARD, _
                             AddressOf KeyboardProc, _
                             0&, _
                             GetCurrentThreadId)

вместо GetCurrentThreadId поставить 0, хук должен работать глобально, на все приложения. Правда, могут возникнуть свои нюансы. А вообще все эти хуки ни разу не для Excel работа, глюков потом не оберетесь.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ttt480

Пользователь

Сообщений: 395
Регистрация: 17.12.2015

#3

11.03.2017 10:11:54

Цитата
The_Prist написал:
вместо GetCurrentThreadId поставить 0, хук должен работать глобально, на все приложения.

Вместо GetCurrentThreadId поставил 0, как вы сказали  — и сообщения перестали запускаться.
То есть — вообще нет реакции на нажатие клавиш — ни в самом экселе, ни в других приложениях.

Изменено: ttt48011.03.2017 10:16:13

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Откройте поисковик, забейте название своей функций и добавьте «глобальный хук». Забыл я, что третий аргумент не должен равняться нулю, если четвертый 0. Там должна идти ссылка на библиотеку, осуществляющую хук. В этом есть проблема использования в VBA. Есть, конечно, обходные пути, но как писал выше — глюков не оберетесь.
В VBA скорее проще будет использовать RegisterHotKey для отлова исключительно нужных сочетаний, чем глобальный хук пробовать внедрить.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ttt480

Пользователь

Сообщений: 395
Регистрация: 17.12.2015

#5

11.03.2017 10:47:49

Цитата
The_Prist написал:
В VBA скорее проще будет использовать RegisterHotKey для отлова исключительно нужных сочетаний

А RegisterHotKey  — он глобально умеет работать?
Просто смотрю в интернете — везде пишут, что только SetWindowsHookEx для этой цели можно использовать.

Изменено: ttt48011.03.2017 11:58:46

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

Вот решение, комбо, наиболее шустро отрабатывает. (из пяти просмотренных вариантов) С библиотеками от самой винды.
Я привязывал реализацию процедуры в класс модуле, поэтому добавил модификатор доступа при подключении к библиотеки.
При использовании в обычном модуле модификатор можно убрать.

Visual Basic
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
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long)
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 
 
.......
Private Sub fpsTracker() 'перехват нажатия клавиш
Do Until GetAsyncKeyState(VK_NUMPAD0)
    DoEvents
    If GetAsyncKeyState(VK_LEFT) Then
    Sleep 16
    'вызов моей процедуры1
    End If
    If GetAsyncKeyState(VK_RIGHT) Then
    Sleep 16
       'вызов моей процедуры2
    End If
    If GetAsyncKeyState(VK_UP) Then
    Sleep 16
       'вызов моей процедуры3
    End If
    If GetAsyncKeyState(VK_DOWN) Then
    Sleep 16
        'вызов моей процедуры4
    End If
Loop
End Sub
........

Очень мягко отрабатывает , по сравнению с остальными вариантами. Экран практически не скачет, и не надо чтобы ячейка или форма,или элемент формы в фокусе был.

Sleep 16 это имитация FPS на экране, примерно 60 кадров в секунду. В данном случае прерываний процедуры. Картинка для игры успевает прорисовываться и на работу не влияют случайные нажатия в ячейки, ввод каких то значений, итд, итп.

Перехват сочетаний клавиш в Форме.

Cere6ellum

Дата: Четверг, 02.03.2017, 15:01 |
Сообщение № 1

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Добрый день.
Несколько дней пытаюсь реализовать перехват сочетания Ctrl+C.
Форма содержит TextBox и несколько кнопок.
У одной из кнопок свойство Default установлено в True. Enter уже не прокатит.

Клик мышью по «проблемной» кнопке копирует всё из TextBox.

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

Копать нужно сюда, наверно:
[vba]

Код

Private Sub WorkBook_Open()
    Application.OnKey «^c», «MyMacro»
End Sub

Private Sub MyMacro()
    MsgBox «AAAAAAAAA»
End Sub

[/vba]

Но концепцию продумать не получается.
Как привязать вызов макроса к кнопке формы?

 

Ответить

K-SerJC

Дата: Пятница, 03.03.2017, 07:31 |
Сообщение № 2

Группа: Проверенные

Ранг: Обитатель

Сообщений: 487


Репутация:

86

±

Замечаний:
0% ±


Excel 2013

Как привязать вызов макроса к кнопке формы?

так?
[vba]

Код

Private Sub WorkBook_Open()
    Application.OnKey «^c», «MyMacro»
End Sub

Private Sub MyMacro()
      Commandbutton1_click()
      MsgBox «AAAAAAAAA»
End Sub

[/vba]
в вашем коде который определяет на запуск по горячей клавише, назначаете запуск процедуры по клику на кнопке

или на всех элементах формы, которые могут быть в фокусе использовать событие KeyPress
[vba]

Код

Private Sub TextBox3_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Debug.Print KeyCode
Debug.Print Shift
End Sub

[/vba]


Благими намерениями выстелена дорога в АД.

Сообщение отредактировал K-SerJCПятница, 03.03.2017, 07:42

 

Ответить

Cere6ellum

Дата: Пятница, 03.03.2017, 10:08 |
Сообщение № 3

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Не особо понял.

Сначала определяю перехват:
[vba]

Код

Private Sub WorkBook_Open()
    Application.OnKey «^c», «MyMacro»
End Sub

[/vba]

После, описываю метод при нажатиии клавиш Ctrl+C в модуле формы:
[vba]

Код

Private Sub MyMacro()
    Commandbutton1_click()
    MsgBox «AAAAAAAAA»
End Sub

[/vba]

После, прописываю метод для TextBox, из которого нужно скопировать данные при нажатии Ctrl+C.:
[vba]

Код

Private Sub TextBox3_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Debug.Print KeyCode
Debug.Print Shift
End Sub

[/vba]
Причём, копирование должно происходить как и митация нажития кнопки в форме.

Всё правильно описал?
Не работает такой подход.
Чувствую, чего-то не понимаю…

 

Ответить

K-SerJC

Дата: Пятница, 03.03.2017, 11:31 |
Сообщение № 4

Группа: Проверенные

Ранг: Обитатель

Сообщений: 487


Репутация:

86

±

Замечаний:
0% ±


Excel 2013

определяете перехват, на ваш макрос
определяете что делать при клике на кнопку
при этом клик на кнопке у вас описан в процедуре событие
типа такого, от названия кнопки зависит:
[vba]

Код

Private Sub Commandbutton1_click()

[/vba]
в вашем макросе указываете эту процедуру должно работать…

[vba]

Код

Private Sub TextBox3_KeyDown

[/vba]
срабатывает когда у вас запущена форма и нажаты любые клавиши, когда фокус на TextBox3
тут надо прописать определение какие клавишы были нажаты и если нужные, то запустить вашу процедуру

свой пример можете приложить?


Благими намерениями выстелена дорога в АД.

Сообщение отредактировал K-SerJCПятница, 03.03.2017, 11:45

 

Ответить

Cere6ellum

Дата: Пятница, 03.03.2017, 12:43 |
Сообщение № 5

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Во вложении.

К сообщению приложен файл:

Example.xlsm
(29.8 Kb)

 

Ответить

Cere6ellum

Дата: Суббота, 04.03.2017, 12:09 |
Сообщение № 6

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Не было возможности глянуть мой файл?

 

Ответить

K-SerJC

Дата: Понедельник, 06.03.2017, 07:26 |
Сообщение № 7

Группа: Проверенные

Ранг: Обитатель

Сообщений: 487


Репутация:

86

±

Замечаний:
0% ±


Excel 2013

Не было возможности глянуть мой файл?

да.

вот так вроде работает:
[vba]

Код

Private Sub msgTextBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 67 And Shift = 2 Then CopyButton_Click Else Exit Sub
End Sub

[/vba]


Благими намерениями выстелена дорога в АД.

 

Ответить

Cere6ellum

Дата: Понедельник, 06.03.2017, 09:17 |
Сообщение № 8

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Почему-то не работает.
Жму Ctrl+c. Ноль эмоций.

Как отловить ошибку?

 

Ответить

Cere6ellum

Дата: Понедельник, 06.03.2017, 11:02 |
Сообщение № 9

Группа: Пользователи

Ранг: Новичок

Сообщений: 25


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Вообщем повесил на действие для первой кнопки переключение фокуса на вторую.
Просто 2 раза Enter нужно нажимать теперь.
Спасибо, в любом случае.

 

Ответить

K-SerJC

Дата: Вторник, 07.03.2017, 07:33 |
Сообщение № 10

Группа: Проверенные

Ранг: Обитатель

Сообщений: 487


Репутация:

86

±

Замечаний:
0% ±


Excel 2013

Вообщем повесил на действие для первой кнопки переключение фокуса на вторую.
Просто 2 раза Enter нужно нажимать теперь.
Спасибо, в любом случае.

попробуйте во всех элементах формы на KeyUP прописать:

[vba]

Код

If KeyCode = 67 And Shift = 2 Then CopyButton_Click Else Exit Sub

[/vba]

а не только для msgTextBox


Благими намерениями выстелена дорога в АД.

Сообщение отредактировал K-SerJCВторник, 07.03.2017, 07:37

 

Ответить

title keywords f1_keywords ms.prod api_name ms.assetid ms.date ms.localizationpriority

Application.OnKey method (Excel)

vbaxl10.chm133180

vbaxl10.chm133180

excel

Excel.Application.OnKey

43662d8b-19e2-2b4a-4c3a-c64be4007643

04/30/2019

medium

Application.OnKey method (Excel)

Runs a specified procedure when a particular key or key combination is pressed.

Syntax

expression.OnKey (Key, Procedure)

expression A variable that represents an Application object.

Parameters

Name Required/Optional Data type Description
Key Required String A string indicating the key to be pressed.
Procedure Optional Variant A string indicating the name of the procedure to be run. If Procedure is «» (empty text), nothing happens when Key is pressed. This form of OnKey changes the normal result of keystrokes in Microsoft Excel.

If Procedure is omitted, Key reverts to its normal result in Microsoft Excel, and any special key assignments made with previous OnKey methods are cleared.

Remarks

The Key argument can specify any single key combined with Alt, Ctrl, or Shift, or any combination of these keys. Each key is represented by one or more characters, such as a for the character a, or {ENTER} for the Enter key.

To specify characters that aren’t displayed when you press the corresponding key (for example: Enter or Tab), use the codes listed in the following table. Each code in the table represents one key on the keyboard.

Key Code
BACKSPACE {BACKSPACE} or {BS}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
CLEAR {CLEAR}
DELETE or DEL {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER (numeric keypad) {ENTER}
ENTER ~ (tilde)
ESC { ESCAPE} or {ESC}
HELP {HELP}
HOME {HOME}
INS {INSERT}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
RETURN {RETURN}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1 through F15 {F1} through {F15}

You can also specify keys combined with Shift and/or Ctrl and/or Alt and/or Command. To specify a key combined with another key or keys, use the following table.

To combine keys with Precede the key code by
Shift + (plus sign)
Ctrl ^ (caret)
Alt % (percent sign)
Command * (asterisk) Only applies to Mac; may only work on Excel 2011 for Mac and not later versions.

To assign a procedure to one of the special characters (+, ^, %, and so on), enclose the character in braces. For details, see the example.

[!NOTE]
There is no way to currently detect the Command key in recent versions of Office VBA. Microsoft is aware of this and is looking into it.

Example

This example assigns InsertProc to the key sequence Ctrl+Plus Sign, and assigns SpecialPrintProc to the key sequence Shift+Ctrl+Right Arrow.

Application.OnKey "^{+}", "InsertProc" 
Application.OnKey "+^{RIGHT}", "SpecialPrintProc"

This example returns Shift+Ctrl+Right Arrow to its normal meaning.

Application.OnKey "+^{RIGHT}"

This example disables the Shift+Ctrl+Right Arrow key sequence.

Application.OnKey "+^{RIGHT}", ""

[!includeSupport and feedback]

Понравилась статья? Поделить с друзьями:
  • Vba excel пересчет ячейки
  • Vba excel пересчет книги
  • Vba excel перенос ячейки в другую ячейку
  • Vba excel перенос ячеек
  • Vba excel перенос на новую строку