Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Изменяется Num Lock при %{down), При посыле команды Alt+Down меняется индикатор NumLock
 
И все-таки это возможно.

Коротко и с готовым примером (файл прилагается).


Перед
Код
Application.SendKeys "%{DOWN}"
надо выполнить
Код
If Num_Not_Stable() Then Application.SendKeys "{NUMLOCK}"
и NumLock меняться не будет.

В листе:
Код
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim lValidation As Long
    
    If Num_Not_Stable() Then Application.SendKeys "{NUMLOCK}" ' делает NumLock стабильным
    
    On Error Resume Next
      lValidation = ActiveCell.Validation.Type
    On Error GoTo 0
    If lValidation = 3 Then Application.SendKeys "%{DOWN}"
End Sub

В модуле книги:
Код
Declare PtrSafe Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long

' Определяет, изменчивое ли состояние у NumLock или нет
' Возвращает false - стабильный, true - изменчевый
Function Num_Not_Stable() As Boolean

    Dim keystat(0 To 255) As Byte
    Dim state As String
    
    GetKeyboardState keystat(0)
    state = keystat(vbKeyNumlock)
    
    If (state = 0) Then
     Num_Not_Stable = False
    Else
     Num_Not_Stable = True
    End If
End Function 

Теперь рассуждения что, и как работает.

Посмотрев по предложенным ссылкам и многим другим источникам, убедился- все это шляпа. И она не работает.
Я не то что не гуру, использую VBA около месяца. Потому, все что ниже (и выше, не счет "шляпы"  ;)  может не соответствовать истине.
Кроме того, что бы придти к этому способу я сознательно подменил стандартные понятия своими, заведомо не верными, но работающими в данном контексте.

И так.
Первое понятие: команда {NUMLOCK} не посылает сигнал "нажать NumLock", а закрепляет NumLock, если он "изменчивый".

"Изменчивый" - это когда он меняет свое состояние, когда не должен, например при команде %{DOWN} которая по идее должна только сымитировать Alt+Down.

Экспериментальным путем выяснил, что NumLock имеет "стабильное" состояние и "изменчивое". Не путать с "включен" и "выключен", в любом из них он может быть как "изменчивым" так и "стабильным".

Второе понятие: строчки
GetKeyboardState keystat(0)    
state = keystat(vbKeyNumlock)
определяют не текущее состояние NumLock, а его текущую стабильность. Если state = 0, то NumLock стабилен, иначе изменчив.

Теперь все просто.
Если NumLock стабилен, ничего не делаем, просто посылаем команду %{DOWN}.
Если NumLock изменчивый, посылаем команду стабилизации (закрепления) {NUMLOCK}, и после уже спокойно пишем %{DOWN}, зная, что NumLock не изменится.

Конечно понятия "стабильный" и "изменчивый" надуманы но тут они отлично подходят.

Несколько фактов из наблюдений.
В стабильном состоянии следущие команды не меняют NumLock
%{DOWN}
{NUMLOCK} {NUMLOCK} (т.е. два раз подряд послать нажатие NumLock)

В изменчивом состоянии те же команды его меняют регулярно (при каждой команде NumLock 1 раз меняется) оставляя его изменчивым.
При этом команда
{NUMLOCK} (т.е. один раз послать нажатие NumLock)
работает так (допустим сейчас стабильное состояние, и он включен (лампочка горит)):
1. {NUMLOCK} - NumLock изменился (погас), состояние стало изменчивым
2. {NUMLOCK} - NumLock не изменился (не горит),   состояние стало стабильным
3. {NUMLOCK} - NumLock изменился (загорелся), состояние стало изменчивым
4. {NUMLOCK} - NumLock не изменился (горит),  состояние стало стабильным
...... и далее по кругу


Еще немного мелочей.
Во многих гайдах пишут подключить библиотеку для работы GetKeyboardState keystat(0), а именно:
Declare PtrSafe Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
PtrSafe - там отсутствует, что вызывает ошибку, т.к. сейчас почти у всех Windows 64 bit, а не 32. Для совместимости и надо добавить.

Так же в этом объявлении для совместимости с 64-битной версией, рекомендуют использовать тип LongLong вместо Long. Возможно это где-то оправдано. У меня работали оба варианта, но у одного из тех, кому я делал вылезла ошибка, что у него нет такого типа данных (LongLong). По этому пишу просо Long.
Что у меня, что у него Windows 7 64bit, Excel 2010.

P.S. мда, ну и накатал. Что значит заняться не чем было (5 часов разбирался). Ну да может пригодится кому.
Изменяется Num Lock при %{down), При посыле команды Alt+Down меняется индикатор NumLock
 
Ок, попробуем обойти. Где-то месяц назад я писал макрос с использованием этого трюка. На VBA до этого не писал так что уже подзабыл что да как. Смысл в том, что как и рекомендовано в Mictosoft по ссылке выше, я пытался запомнить значение NumLock и после восстановить его. Считывал значение 2-3 разными методами, но возвращалось всегда одно и то же значение. Так и не разобрался тогда. Может кто напишет пару строк работающего кода?

Схема проще некуда:
1. before = Get_NumLock()
2. Application.SendKeys "%{DOWN}"
3. Set_NumLock(before)

Но в 1-й строчке как ни крутил, всегда true возвращалось (или false, не помню уже) .
(на всякий случай: 1 и 3 строчки используют несуществующие методы Get/Set, это только пример как должно работать)

Предложения от Microsoft:
Чтобы обойти эту проблему, выполните одно из следующих:
Определите параметр клавиши NumLock до с помощью SendKeys. Затем, Отключите NumLock перед использованием SendKeys. После использования SendKeys, сброс NumLock его предыдущего значения. Это достигается с помощью GetKeyboardState, keybd_event и SetKeyboardState API функций. См. в разделе ссылки ниже для получения дополнительной информации.
ИЛИ
С помощью функций API вместо SendKeys
Изменено: Dmitri_0154 - 21.10.2014 16:14:36
Изменяется Num Lock при %{down), При посыле команды Alt+Down меняется индикатор NumLock
 
Не указал сразу. Если на клавиатуре выполнить Alt + "стрелка вниз", то что при левом, что при правом Alt, NumLoсk не меняется. В т.ч. если выделена ячейка со списком. Список раскрывается и сворачивается, а NumLock не реагирует. Реагирует только на команду из скрипта.

У меня действительно nVidia, не знаю где там что может быть с хоткеями, но поищу, хоть и сомневаюсь что найду что-то.
И еще, отпишитесь кто-нибудь у кого именно этот макрос нормально выполняется, без смены NumLock (желательно проверить в приложенном файле). А то ощущение, что советуют не проверив. Просто для уверенности, мол "Я, такой-то проверял, у меня все как надо, ищи ошибку у себя". Редко бывает, что на разных машинах один и тот же глюк.
Изменено: Dmitri_0154 - 21.10.2014 14:37:41
Изменяется Num Lock при %{down), При посыле команды Alt+Down меняется индикатор NumLock
 
При посыле команды Alt+Down меняется индикатор NumLock. (решено, пост №9)
По-моему это глюк Excel.

Прикрепил файл, но по сути он чист. Только в "Лист1" добавлен макрос ну и создан список для теста:

Код
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim lValidation As Long
    On Error Resume Next
     lValidation = ActiveCell.Validation.Type
    On Error GoTo 0
    If lValidation = 3 Then Application.SendKeys "%{DOWN}"
End Sub

Подробно.
Если выделить ячейку с проверкой данных, то посылается команда Alt+Down, что бы список сам раскрылся. Для удобства.
Однако вместе с этим, меняется индикатор NumLok, причем, если в какой-то момент нажать NumLock самому (пальцем на клавиатуре), то он как ему и положено изменится и больше меняться от выделения ячейки не будет.
Если нажать еще раз, то снова начнет меняться от выделения ячейки.

На другом форуме уже задавал этот вопрос, сказали смотри машину. Проверял на 4-х разных машинах (на одной 3 недели назад винду переустанавливали, так что чище некуда) с разными клавиатурами. Эффект один.

Как бы это пофиксить?
Изменено: Dmitri_0154 - 22.10.2014 17:41:23
Страницы: 1
Наверх