2010-05-25 6 views
5

Io lavoro su un progetto chiamato UAWKS (supporto non ufficiale per tastiera wireless Apple) che aiuta gli utenti Windows ad usare la tastiera bluetooth di Apple. Uno dei principali obiettivi di UAWKS è quello di scambiare il Cmd chiave (che si comporta come Winkey in Windows) con Ctrl, che consente agli utenti di fare Cmd + C per la copia, Cmd + T per la nuova scheda, ecc.Ganci tastiera/SendInput di basso livello con Winkey + L possibile? (Il blocco della workstation è intercettato in Vista e superiore)

Attualmente è stato sviluppato utilizzando AutoHotkey, che ha funzionato abbastanza bene in Windows XP. Tuttavia, su Vista e Windows 7, Cmd + L causa problemi:

  • Indipendentemente ganci basso livello della tastiera, Win + L è stato intercettato sempre da Windows e normalmente blocca la workstation. ..
  • è possibile disabilitare il blocco workstation con this registry hack, ma premendo Win + L ancora non può essere ripresa nel AHK
  • Premere Win + L lascia Winkey nello stato Keydown fino alla successiva (aggiuntiva) Winkey Up. Anche la simulazione di un evento Keyup non funziona!

Sembra che Win + L è un accordo speciale che scombina tutto il resto in su.

Ho esaminato il codice sorgente AHK e tentano di risolvere questo problema in SendKey() in keyboard_mouse.cpp (vicino alla riga 883 in v1.0.48.05), ma non funziona. Ho scritto la mia applicazione di aggancio per tastiera di basso livello in C# e vedo lo stesso problema.

Qualcun altro ha incontrato questo? C'è una soluzione?

+0

Devo aggiungere che ci sono post sul forum su AutoHotkey.com, ma le soluzioni sono obsolete o errate (vedi sotto). Inoltre, la mia domanda non è veramente limitata a AutoHotkey. Alla fine voglio reimplementare l'intero programma in C#. Questa è più una domanda su come Windows Vista e Windows 7 considerano Winkey + L in modo diverso, e se qualcuno lo ha già visto/risolto prima. http://www.autohotkey.com/forum/viewtopic.php?t=27554&highlight=winkey http://www.autohotkey.com/forum/viewtopic.php?t=15513&postdays=0&postorder=asc&start=0 –

risposta

1

Ho trovato un modo per farlo in C#. Ci sono quattro stati coinvolti in una possibile Win + L sequenza di pressione dei tasti (Nessuno, Win, Win + L, L). Ogni volta che viene raggiunto lo stato Win + L, impostare un flag ("winLSet" di seguito). Ogni volta che tutti i tasti sono stati rilasciati, controlliamo questo flag e simuliamo la stampa se è stata impostata.

L'ultimo pezzo del puzzle è quello di simulare KeyUp del WinKey prima della Ctrl - L (senza KeyDown). Ho provato approcci simili in AutoHotkey e non ha mai funzionato, ma sembra funzionare perfettamente qui.

Il codice è di seguito. Si prega di vedere le note esplicative in fondo se si prevede di utilizzare questo codice.

public partial class MainWindow : Window 
{ 
    LowLevelKeyboardHook hook; 

    bool winKeyDown; 
    bool lKeyDown; 
    bool winLSet; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     hook = new LowLevelKeyboardHook(); 

     hook.KeyDown += OnKeyDown; 
     hook.KeyUp += OnKeyUp; 
    } 

    void OnKeyDown(object sender, LowLevelKeyEventArgs e) 
    { 
     e.EventHandled = true; 

     switch (e.Key) 
     { 
      case Key.L: 
       lKeyDown = true; 
       UpdateWinLState(); 
       e.EventHandled = winKeyDown; 
       break; 

      case Key.LWin: 
       winKeyDown = true; 
       UpdateWinLState(); 
       InputSimulator.SimulateKeyDown(VirtualKeyCode.LCONTROL); 
       break; 

      case Key.LeftCtrl: 
       InputSimulator.SimulateKeyDown(VirtualKeyCode.LWIN); 
       break; 

      default: 
       e.EventHandled = false; 
       break; 
     } 
    } 

    void OnKeyUp(object sender, LowLevelKeyEventArgs e) 
    { 
     e.EventHandled = true; 

     switch (e.Key) 
     { 
      case Key.L: 
       lKeyDown = false; 
       UpdateWinLState(); 
       e.EventHandled = winKeyDown; 
       break; 

      case Key.LWin: 
       winKeyDown = false; 
       UpdateWinLState(); 
       InputSimulator.SimulateKeyUp(VirtualKeyCode.LCONTROL); 
       break; 

      case Key.LeftCtrl: 
       InputSimulator.SimulateKeyUp(VirtualKeyCode.LWIN); 
       break; 

      default: 
       e.EventHandled = false; 
       break; 
     } 
    } 

    void UpdateWinLState() 
    { 
     if (winKeyDown && lKeyDown) 
     { 
      winLSet = true; 
     } 
     else if (!winKeyDown && !lKeyDown && winLSet) 
     { 
      winLSet = false; 

      InputSimulator.SimulateKeyUp(VirtualKeyCode.LWIN); 

      InputSimulator.SimulateModifiedKeyStroke(
       VirtualKeyCode.LCONTROL, 
       (VirtualKeyCode)'L'); 
     } 
    } 
} 

Ai posteri: si prega di notare che questo codice utilizza InputSimulator e LowLevelKeyboardHook, che non sono da .NET Framework. LowLevelKeyboardHook è una classe che ho scritto qualche tempo fa che espone eventi KeyDown e KeyUp globali come eventi C#. Esistono esempi simili here, here e un gruppo può essere trovato here.

Si noti inoltre che sto utilizzando System.Windows.Input.Key, non System.Windows.Forms.Keys, che potrebbe confondere alcune persone. System.Windows.Input.Key è la nuova enumerazione di chiavi in ​​.NET 3.0 e versioni successive, mentre System.Windows.Forms.Keys è la vecchia enumerazione di Windows Forms.

0

Se è possibile rilevare la chiave Cmd +L potrebbe solo andare avanti e bloccare la stazione di lavoro senza preoccuparsi di inoltrare Winkey + L? puoi farlo con l'API LockWorkstation (o rundll32.exe user32.dll,LockWorkStation)

+0

In realtà, sto provando a _prevent_ la workstation dal blocco. Posso farlo con l'hack del registro, ma lo stato di Winkey continua a incasinare ogni volta che premi Winkey + L/Cmd + L (sono la stessa cosa, ho usato Cmd e Winkey in modo intercambiabile sopra, mi dispiace per la confusione. una tastiera Apple si chiama Cmd, ma il driver della tastiera di Windows lo interpreta come Winkey.) –

0

Ho provato ad interrompere il tasto di Windows utilizzando la libreria Windows Input Simulator. Questo è il mio callback:

private static unsafe IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    if(nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN)) 
    { 
     var replacementKey = (KBDLLHOOKSTRUCT*)lParam; 
     if(replacementKey->vkCode == (int)VirtualKeyCode.LWIN) 
     { 
      InputSimulator.SimulateKeyDown(VirtualKeyCode.SHIFT); 
      return (IntPtr)1; 
     } 
    } 
    return CallNextHookEx(m_HookID, nCode, wParam, lParam); 
} 

Utilizzando questo amo le mie finestre lasciate tasto funge da tasto shift (come attuato & previsto) con Win XP.
Premendo WinKey + l restituisce solo L.

MODIFICA: Tuttavia, posso confermare la tua osservazione, che questo codice non funziona più in Windows 7:/Spiacente, non posso aiutarti ulteriormente.

+0

Grazie, ma in realtà sto usando InputSimulator per la mia app C# sandbox. Per qualche motivo, Winkey down si blocca prima di chiamare anche InputSimulator.SimulateKeyDown (vkCode), quindi l'effetto finisce con Winkey + vkCode. E questo succede SOLO con Winkey + L. –

+0

Molto apprezzato, grazie! –