Перехватить определённую последовательность клавиш

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Перехватить определённую последовательность клавиш

Сообщение Sun07 » 08.05.2006 (Пн) 17:42

Подскажите пожалуйста, как программе перехватить последовательность Ctrl+A+Q (Ctrl зажат, затем нажимается A, отпускается A, затем Q) без хука на клавиатуру при FORM1.Visible = FALSE?

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 08.05.2006 (Пн) 17:57

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

Sun07, почему именно без хука? Это самый правильный способ.

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 08.05.2006 (Пн) 19:03

потому что сложно и фаерволы ругаются. Обзовут шпионом. Проще сделать через GetKeyboardState, сейчас разбираюсь с ней. Хотел использовать GetAsyncKeyState, но не могу составить код для отлова последовательности клавиш. Интересно, что мелкософт пишет, что эта ф-я возвращает 0, если фокус клавиатуры принадлежит другому процессу. А в статьях инета используют её для перехвата вне зависимости от фокуса (для кейлоггеров) - так она и работает!

Adept
Новичок
Новичок
 
Сообщения: 25
Зарегистрирован: 21.02.2005 (Пн) 7:59
Откуда: Питер

Сообщение Adept » 08.05.2006 (Пн) 22:15

я вроде делал так:
Код: Выделить всё

Private Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As Long) As Integer
Dim keystate As Long

Private Sub Timer1_Timer()
keystate = GetKeyState(vbKeyShift)
If (keystate And &H80) = &H80 Then
  keystate = GetKeyState(vbKeyPause)
  If (keystate And &H1) = &H1 Then
     *код тута*   
  End If
End If


ЗЫ
If (keystate And &H80) = &H80 Then - если клавиша ЗАжата
If (keystate And &H1) = &H1 Then - если клавиша НАжата
вроде бы так...

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 08.05.2006 (Пн) 23:14

Sun07, дело в том, что использовать таймер в таких вещах - весьма плохой способ, лучше его избегать.

а) не гарантирует 100% работоспособность
б) загружает процессор

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 09.05.2006 (Вт) 0:30

Amed писал(а):Sun07, дело в том, что использовать таймер в таких вещах - весьма плохой способ, лучше его избегать.

а) не гарантирует 100% работоспособность
б) загружает процессор


по работоспособности не знаю, думаю что проколов не будет. По загрузке процессора в Диспетчере задач показывает 0.

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 09.05.2006 (Вт) 0:41

Отловить нажатие Shift и ещё одной клавиши - не проблема. Shift зажат, его отловить легко. Но если клавиша нажимается и отпускается, тут проблемы при отлове нескольких клавиш. Как в моём вопросе, Ctrl+A я отловлю. Я установлю флаг на нажатие Ctrl+A и буду ждать нажатия Q, но здесь может быть нажата любая клавиша, потом Q. А мне надо A,Q.

Adept
Новичок
Новичок
 
Сообщения: 25
Зарегистрирован: 21.02.2005 (Пн) 7:59
Откуда: Питер

Сообщение Adept » 09.05.2006 (Вт) 9:41

так тебе нужна именно последовательность, а не одновременно зажатые клавиши? тогда я просто вопроса не понял...
Код: Выделить всё

Private Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As Long) As Integer
Dim keystate As Long
Dim word as String
Dim Letter as Long

word="test"   ' слово, последовательность букв которого нужно нажать
Letter=1        ' номер проверяемой буквы

Private Sub Timer1_Timer()
keystate = GetKeyState(chr$(mid$(word,1,Letter)))
If (keystate And &H1) = &H1 Then
    Letter=Letter+1
        If Letter=len(word) then
            *код тута*   
        end if
Else  'если нажали не ту букву
    Letter=1
End If
End Sub


могут быть и ошибки))
на этом компе VB нету...

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 09.05.2006 (Вт) 11:14

Я подобную вешь делал через RegisterHotKey. Что-то типа этого:
Код: Выделить всё
Private Const MOD_ALT = &H1
Private Const MOD_CONTROL = &H2
Private Const MOD_SHIFT = &H4
Private Const PM_REMOVE = &H1
Private Const WM_HOTKEY = &H312
Private Type POINTAPI
    x As Long
    y As Long
End Type
Private Type Msg
    hWnd As Long
    Message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type
Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hWnd As Long, ByVal id As Long) As Long
Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As Msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
Private Declare Function WaitMessage Lib "user32" () As Long
Private bCancel As Boolean
Private Sub ProcessMessages()
    Dim Message As Msg
    'loop until bCancel is set to True
    Do While Not bCancel
        'wait for a message
        WaitMessage
        'check if it's a HOTKEY-message
        If PeekMessage(Message, Me.hWnd, WM_HOTKEY, WM_HOTKEY, PM_REMOVE) Then
            'minimize the form
            WindowState = vbMinimized
        End If
        'let the operating system process other events
        DoEvents
    Loop
End Sub
Private Sub Form_Load()
    'KPD-Team 2000
    'URL: http://www.allapi.net/
    'E-Mail: KPDTeam@Allapi.net
    Dim ret As Long
    bCancel = False
    'register the Ctrl-F hotkey
    ret = RegisterHotKey(Me.hWnd, &HBFFF&, MOD_CONTROL, vbKeyF)
    'show some information
    Me.AutoRedraw = True
    Me.Print "Press CTRL-F to minimize this form"
    'show the form and
    Show
    'process the Hotkey messages
    ProcessMessages
End Sub
Private Sub Form_Unload(Cancel As Integer)
    bCancel = True
    'unregister hotkey
    Call UnregisterHotKey(Me.hWnd, &HBFFF&)
End Sub

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 09.05.2006 (Вт) 12:30

Прочитав описание RegisterHotKey, нетрудно убедиться, что нельзя двум приложениям зарегистрировать одно сочетание. Таким образом, если ctrl+a или ctrl+q уже зарегистрировано, ничего не получится.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Sun07
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 355
Зарегистрирован: 17.02.2006 (Пт) 21:27

Сообщение Sun07 » 12.05.2006 (Пт) 0:22

Для Adept: GetKeyState вернёт ноль, если нажата не нужная нам клавиша? А если фокус ввода не на моём приложении (Form1.Visible=False), что вернёт GetKeyState?


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 141

    TopList  
cron