2010-05-25 26 views
5

Tôi làm việc trên một dự án có tên là UAWKS (Hỗ trợ bàn phím không dây của Apple không chính thức) giúp người dùng Windows sử dụng bàn phím bluetooth của Apple. Một trong những mục tiêu chính của UAWKS là để trao đổi các Cmd chủ chốt (mà cư xử như WinKey trong Windows) với Ctrl, cho phép người dùng làm Cmd + C cho sao chép, Cmd + T cho tab mới, v.v.Bàn phím mức thấp Hooks/SendInput với Winkey + L có thể? (khóa máy trạm bị chặn trong Vista và cao hơn)

Nó hiện đang được phát triển bằng cách sử dụng AutoHotkey, hoạt động khá tốt trong Windows XP. Tuy nhiên, trên Vista và Windows 7, Cmd + L gây ra vấn đề:

  • Bất kể móc bàn phím ở mức độ thấp, Win + L luôn bị chặn lại bởi Windows và thường khóa các máy trạm. ..
  • Bạn có thể vô hiệu hóa máy trạm khóa với this registry hack, nhưng nhấn Win + L vẫn không thể hồi phục trong AHK
  • Nhấn Giành chiến thắng + L để Winkey ở trạng thái Keydown cho đến lần tiếp theo (bổ sung) Winkey Up. Mô phỏng một sự kiện Keyup dường như không hoạt động!

Dường như Win + L là một hợp âm đặc biệt mà messes mọi thứ khác lên.

Tôi đã xem xét mã nguồn AHK và cố gắng giải quyết vấn đề này trong SendKey() trong keyboard_mouse.cpp (gần dòng 883 trong v1.0.48.05), nhưng nó không hoạt động. Tôi đã viết ứng dụng hook bàn phím mức thấp của riêng mình trong C# và tôi thấy cùng một vấn đề.

Có ai khác chạy vào điều này không? Có cách giải quyết nào không?

+0

Tôi nên thêm rằng có các bài đăng trên diễn đàn tại AutoHotkey.com, nhưng các giải pháp là lỗi thời hoặc không chính xác (xem bên dưới). Ngoài ra, câu hỏi của tôi không thực sự giới hạn đối với AutoHotkey. Cuối cùng tôi muốn thực hiện lại toàn bộ chương trình trong C#. Đây là một câu hỏi về cách Windows Vista và Windows 7 xử lý Winkey + L một cách khác nhau, và nếu có ai đã xem/giải quyết vấn đề này trước đây. 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 –

Trả lời

1

Tôi đã tìm ra cách để thực hiện việc này trong C#. Có bốn quốc gia tham gia vào một Win + L chuỗi bấm phím có thể (Không, Win, Win + L, L). Bất cứ khi nào đạt được trạng thái giành chiến thắng + L, hãy đặt cờ ("winLSet" bên dưới). Bất cứ khi nào tất cả các phím đã được phát hành, chúng tôi kiểm tra cờ này và mô phỏng báo chí nếu nó đã được thiết lập.

Giai đoạn cuối cùng của câu đố là để mô phỏng KeyUp của WinKey trước Ctrl - L (không KeyDown). Tôi đã thử các cách tiếp cận tương tự trong AutoHotkey và nó không bao giờ hoạt động, nhưng có vẻ như nó hoạt động hoàn hảo ở đây.

Mã bên dưới. Vui lòng xem ghi chú giải thích ở phía dưới nếu bạn dự định sử dụng mã này.

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'); 
     } 
    } 
} 

Để biết thêm: hãy lưu ý rằng mã này sử dụng InputSimulator và LowLevelKeyboardHook, không phải từ .NET Framework. LowLevelKeyboardHook là một lớp tôi đã viết một thời gian trở lại cho thấy sự kiện KeyDown và KeyUp toàn cầu dưới dạng sự kiện C#. Có các ví dụ tương tự here, here và một nhóm có thể được tìm thấy here.

Cũng lưu ý rằng tôi đang sử dụng System.Windows.Input.Key, không phải System.Windows.Forms.Keys, điều này có thể gây nhầm lẫn cho một số người. System.Windows.Input.Key là liệt kê các khóa mới trong .NET 3.0 trở lên, trong khi System.Windows.Forms.Keys là kiểu liệt kê cũ từ Windows Forms.

0

Nếu bạn có thể phát hiện các Cmd +phím L có thể bạn chỉ cần đi trước và khóa máy trạm mà không làm phiền để chuyển tiếp WinKey + L? bạn có thể làm điều đó với API LockWorkstation (hoặc rundll32.exe user32.dll,LockWorkStation)

+0

Thực ra, tôi đang cố gắng _prevent_ máy trạm khỏi bị khóa. Tôi có thể làm điều này với registry hack, nhưng nhà nước Winkey vẫn bị rối tung lên bất cứ khi nào bạn nhấn Winkey + L/Cmd + L (chúng giống nhau; Tôi đã sử dụng Cmd và Winkey hoán đổi cho nhau ở trên, xin lỗi vì sự nhầm lẫn này. một bàn phím táo được gọi là Cmd, nhưng trình điều khiển bàn phím Windows giải thích nó là Winkey.) –

0

Tôi đã cố gắng ngắt khóa cửa sổ bằng cách sử dụng thư viện Windows Input Simulator. Đây là callback của tôi:

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); 
} 

Sử dụng này treo cửa sổ bên trái của tôi hoạt động chủ yếu như một phím shift (như thực hiện & dự kiến) theo Win XP.
Nhấn WinKey + l trả về chỉ L.

CHỈNH SỬA: Tuy nhiên, tôi có thể xác nhận quan sát của bạn rằng mã này không hoạt động trong Windows 7 nữa:/Rất tiếc, tôi không thể trợ giúp thêm cho bạn.

+0

Cảm ơn, nhưng tôi thực sự đang sử dụng InputSimulator cho ứng dụng C# sandbox của tôi. Đối với một số lý do, Winkey bị kẹt trước khi tôi gọi InputSimulator.SimulateKeyDown (vkCode), vì vậy hiệu ứng kết thúc là Winkey + vkCode. Và điều này chỉ xảy ra với Winkey + L. –

+0

Được đánh giá cao, cảm ơn! –

Các vấn đề liên quan