Hook (global) sur le clavier - empêcher le traitement ultérieur (local) de la to

Nicolas_75 Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 12 juillet 2013 - 20 févr. 2010 à 17:47
Nicolas_75 Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 12 juillet 2013 - 22 févr. 2010 à 09:20
Bonjour,

J'apprécierais de l'aide sur le problème suivant.

Mon but final est que l'appui sur la touche F12 entraîne l'impression de la date (par SendKeys) dans l'application qui a le focus (que ce soit Outlook, Word, Excel, etc...). J'ai donc mis en place un "global keyboard hook" à l'échelle du système, qui fonctionne bien (code ci-dessous).

Mon seul souci est que je souhaiterais neutraliser toute interception ultérieure par le système du même F12. Par exemple, l'appui sur F12 sous Word imprime bien la date, mais lance en même temps la boîte de dialogue ("Enregistrer sous..."), car F12 est la raccourci clavier naturel pour cette boîte de dialogue sous Word (hook local). La date s'imprime en fait au sein d'un champ de cette boîte de dialogue.

En d'autres termes, je souhaiterais améliorer le hook pour que l'appui sur F12 fasse ce que je souhaite (c'est déjà le cas), mais rien d'autre. C'est-à-dire faire en sorte que, hormis mon traitement, le système "oublie" que F12 a été pressé.

Je débute en VB.net : je compte sur votre indulgence.

Merci d'avance pour votre aide,
Cordialement,

Nicolas

' Option Strict On
Option Explicit On
 
' inspired by:
' http://jo0ls-dotnet-stuff.blogspot.com/2008/12/vbnet-global-keyboard-hook-to-detect.html
 
Imports System.Runtime.InteropServices
 
Public Class Form1
 
    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_SYSKEYUP As Integer = &H105
    Private proc As LowLevelKeyboardProcDelegate = AddressOf HookCallback
    Private hookID As IntPtr
 
    Private Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As Integer, ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As IntPtr
 
    <DllImport("user32")> _
    Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProcDelegate, _
        ByVal hMod As IntPtr, ByVal dwThreadId As UInteger) As IntPtr
    End Function
 
    <DllImport("user32.dll")> _
    Private Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
 
    <DllImport("user32.dll")> _
    Private Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As IntPtr
    End Function
 
    <DllImport("kernel32.dll", CharSet:=CharSet.Unicode)> _
    Private Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
    End Function
 
    Sub New()
        InitializeComponent()
        Text = "KeyboardPlus 1.01"
        hookID = SetHook(proc)
    End Sub
 
    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing
        UnhookWindowsHookEx(hookID)
    End Sub
 
    Private Function SetHook(ByVal proc As LowLevelKeyboardProcDelegate) As IntPtr
        Using curProcess As Process = Process.GetCurrentProcess()
            Using curModule As ProcessModule = curProcess.MainModule
                Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0)
            End Using
        End Using
    End Function
 
    Private Function HookCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        ' "The WM_KEYUP message is posted to the window with the keyboard focus
        ' when a nonsystem key is released. A nonsystem key is a key that is pressed when the ALT key is not pressed,
        ' or a keyboard key that is pressed when a window has the keyboard focus." 
        If nCode >0 AndAlso (wParam.ToInt32 WM_KEYUP OrElse wParam.ToInt32 = WM_SYSKEYUP) Then
            Dim vkCode As Integer = Marshal.ReadInt32(lParam)
            If vkCode = Keys.F12 Then
                Dim dateOfTheDay As Char() = DateAndTime.Now.ToString.ToCharArray
                If Console.CapsLock Then
                    SendKeys.Send("{CAPSLOCK}")
                    For index As Integer = 0 To 9
                        SendKeys.Send(dateOfTheDay(index))
                    Next
                    SendKeys.Send("{CAPSLOCK}")
                Else
                    For index As Integer = 0 To 9
                        SendKeys.Send(dateOfTheDay(index))
                    Next
                End If
            End If
        End If
        Return CallNextHookEx(hookID, nCode, wParam, lParam)
    End Function
 
End Class

4 réponses

BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 19
20 févr. 2010 à 18:16
Virer le CallNextHookEx().

ciao...
BruNews, MVP VC++
0
Nicolas_75 Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 12 juillet 2013
21 févr. 2010 à 21:50
Merci de ton aide.

J'ai supprimé le "Return CallNextHookEx".
Malheureusement, cela ne change pas la situation. :-(

Après recherche plus avancée, j'ai découvert que les hooks spécifiques des threads passent avant les hooks globaux :
"For a specified hook type, thread hooks are called first, then global hooks."
([url]http://msdn.microsoft.com/en-us/library/ms644990%28VS.85%29.aspx/url)

Sauriez-vous comment passer devant ces hooks spécifiques aux threads ?

Merci d'avance,

Nicolas
0
BruNews Messages postés 21041 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 19
21 févr. 2010 à 22:35
C'est le dernier qui s'enregistre (SetWindowsHookEx) qui est en tête de liste, c'est pour cela qu'il est demandé de refiler aux autres par CallNextHookEx.

ciao...
BruNews, MVP VC++
0
Nicolas_75 Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 12 juillet 2013
22 févr. 2010 à 09:20
Merci de ton aide.

Je me plante peut-être complètement, mais il me semble que mon souci vient du fait que les threads particuliers (Word en l'occurrence) interceptent le clavier avant les hooks globaux (et leur chaînage par CallNextHookEx). Cf. mon message précédent.

Je reste preneur de toute idée pour être le premier à intercepter le clavier (avant les hooks spécifiques de chaque thread).

Merci encore,

Nicoals
0