Tìm hiểu quy trình đã đăng ký một phím nóng toàn cầu? (API Windows)


114

Theo những gì tôi có thể tìm hiểu, Windows không cung cấp hàm API để cho biết ứng dụng nào đã đăng ký phím nóng toàn cầu (thông qua RegisterHotkey). Tôi chỉ có thể phát hiện ra rằng một phím nóng được đăng ký nếu RegisterHotkey trả về false, nhưng không phải ai "sở hữu" phím nóng.

Trong trường hợp không có API trực tiếp, có thể có một con đường vòng nào không? Windows duy trì xử lý được liên kết với mỗi phím nóng đã đăng ký - hơi khó chịu là không có cách nào lấy được thông tin này.

Ví dụ về một cái gì đó có thể sẽ không hoạt động: gửi (mô phỏng) một phím nóng đã đăng ký, sau đó chặn thông báo phím nóng mà Windows sẽ gửi tới tiến trình đã đăng ký nó. Đầu tiên, tôi không nghĩ rằng việc chặn thông báo sẽ tiết lộ tay cầm cửa sổ đích. Thứ hai, ngay cả khi có thể, đó sẽ là một điều tồi tệ để làm, vì việc gửi phím nóng sẽ kích hoạt tất cả các loại hoạt động không mong muốn tiềm ẩn từ các chương trình khác nhau.

Nó không có gì là quan trọng, nhưng tôi đã thấy các yêu cầu thường xuyên cho chức năng như vậy và bản thân tôi đã từng là nạn nhân của các ứng dụng đăng ký phím nóng mà thậm chí không tiết lộ nó ở bất kỳ đâu trong giao diện người dùng hoặc tài liệu.

(Làm việc ở Delphi, và không hơn một người học việc tại WinAPI, xin hãy tử tế.)

Câu trả lời:


20

Câu hỏi của bạn đã thu hút sự quan tâm của tôi, vì vậy tôi đã tìm hiểu kỹ một chút và trong khi đó, rất tiếc là tôi không có câu trả lời thích hợp cho bạn, tôi nghĩ tôi sẽ chia sẻ những gì tôi có.

Tôi đã tìm thấy ví dụ này về tạo móc bàn phím (trong Delphi) được viết vào năm 1998, nhưng có thể biên dịch được trong Delphi 2007 với một vài chỉnh sửa.

Đó là một DLL với lệnh gọi SetWindowsHookExđi qua một hàm gọi lại, sau đó có thể chặn các thao tác gõ phím: Trong trường hợp này, nó đang tìm kiếm chúng cho vui, thay đổi con trỏ từ trái sang phải, v.v. Một ứng dụng đơn giản sau đó gọi DLL và báo cáo lại kết quả của nó dựa trên sự kiện TTimer. Nếu bạn quan tâm, tôi có thể đăng mã dựa trên Delphi 2007.

Nó được ghi chép và bình luận đầy đủ và bạn có thể sử dụng nó như một cơ sở để tìm ra vị trí của một lần nhấn phím. Nếu bạn có thể nhận được xử lý của ứng dụng đã gửi các phím bấm, bạn có thể theo dõi nó theo cách đó. Với tay cầm đó, bạn có thể lấy thông tin bạn cần một cách khá dễ dàng.

Các ứng dụng khác đã thử xác định phím nóng bằng cách xem qua Phím tắt của chúng vì chúng có thể chứa phím Phím tắt, chỉ là một thuật ngữ khác của phím nóng. Tuy nhiên, hầu hết các ứng dụng không có xu hướng đặt thuộc tính này nên nó có thể không trả về nhiều. Nếu bạn quan tâm đến tuyến đường đó, Delphi có quyền truy cập vào IShellLinkgiao diện COM mà bạn có thể sử dụng để tải một phím tắt lên và lấy phím nóng của nó:

uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;

procedure GetShellLinkHotKey;
var
  LinkFile : WideString;
  SL: IShellLink;
  PF: IPersistFile;

  HotKey : Word;
  HotKeyMod: Byte;
  HotKeyText : string;
begin
  LinkFile := 'C:\Temp\Temp.lnk';

  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));

  // The IShellLink implementer must also support the IPersistFile
  // interface. Get an interface pointer to it.
  PF := SL as IPersistFile;

  // Load file into IPersistFile object
  OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));

  // Resolve the link by calling the Resolve interface function.
  OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));

  // Get hotkey info
  OleCheck(SL.GetHotKey(HotKey));

  // Extract the HotKey and Modifier properties.
  HotKeyText := '';
  HotKeyMod := Hi(HotKey);

  if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
    HotKeyText := 'ALT+';
  if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
    HotKeyText := HotKeyText + 'CTRL+';
  if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
    HotKeyText := HotKeyText + 'SHIFT+';
  if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
    HotKeyText := HotKeyText + 'Extended+';

  HotKeyText := HotKeyText + Char(Lo(HotKey));

  if (HotKeyText = '') or (HotKeyText = #0) then
    HotKeyText := 'None';

  ShowMessage('Shortcut Key - ' + HotKeyText);
end;

Nếu bạn có quyền truy cập vào Safari Books Online , có một phần hay về cách làm việc với các phím tắt / liên kết shell trong Hướng dẫn dành cho nhà phát triển Borland Delphi 6 của Steve Teixeira và Xavier Pacheco. Ví dụ của tôi ở trên là một phiên bản bị giết từ đó và trang web này .

Hy vọng rằng sẽ giúp!


59

Một cách khả thi là sử dụng công cụ Visual Studio Spy ++ .

Hãy thử cái này:

  1. Chạy công cụ (đối với tôi, đó là lúc C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe)
  2. Trong thanh menu, chọn Gián điệp -> Nhật ký tin nhắn ... (hoặc nhấn Ctrl+ M)
  3. Kiểm tra Tất cả Windows trong Hệ thống trong khung Windows bổ sung
  4. Chuyển sang tab Tin nhắn
  5. Nhấp vào Xóa tất cả nút
  6. Chọn WM_HOTKEYtrong hộp danh sách hoặc chọn Bàn phím trong Nhóm tin nhắn (nếu bạn ổn với nhiều tiếng ồn tiềm ẩn hơn)
  7. Nhấp vào nút OK
  8. Nhấn phím nóng được đề cập ( Win+ R, chẳng hạn)
  9. Chọn WM_HOTKEYdòng trong cửa sổ Tin nhắn (Tất cả Windows) , nhấp chuột phải và chọn Thuộc tính ... trong menu ngữ cảnh
  10. Trong hộp thoại Thuộc tính Thư , hãy nhấp vào liên kết Xử lý Cửa sổ (đây sẽ là xử lý cho cửa sổ đã nhận thư)
  11. Nhấp vào nút Đồng bộ hóa trên hộp thoại Thuộc tính cửa sổ . Điều này sẽ hiển thị cửa sổ trong dạng cây cửa sổ Spy ++ chính.
  12. Trên hộp thoại Thuộc tính cửa sổ , chọn tab Quy trình
  13. Nhấp vào liên kết ID quy trình . Điều này sẽ cho bạn thấy quy trình (Trong Win+ Rtrường hợp của tôi EXPLORER:)

6
Câu trả lời chính xác! Chỉ cần lưu ý rằng phiên bản 64-bit của Spy ++ chỉ bắt tin nhắn cho các ứng dụng 64-bit , vì vậy nếu bạn không thấy WM_HOTKEYthông báo trong Nhật ký tin nhắn sau khi nhấn phím nóng, bạn có thể cần chạy phiên bản 32-bit của Spy ++ .
David Ferenczy Rogožan

CẢM ƠN BẠN RẤT NHIỀU!!! Về cơ bản, tôi đã từ bỏ việc sử dụng một số phím tắt cho đến khi tôi tìm thấy điều này.
thewindev

3
Trong bước 8, nó không yêu cầu phím nóng, cửa sổ tin nhắn vẫn trống sau khi nhấn bất kỳ phím nóng nào. Đã sử dụng phiên bản 32 và 64 bit từ github.com/westoncampbell/SpyPlusPlus (trong Windows 10).
CoolMind

9

Sau một số nghiên cứu, có vẻ như bạn cần truy cập vào cấu trúc bên trong mà MS sử dụng để lưu trữ các phím nóng. ReactOS có một triển khai phòng sạch thực hiện GetHotKeycuộc gọi bằng cách lặp lại danh sách nội bộ và trích xuất phím nóng khớp với các tham số cho cuộc gọi.

Tùy thuộc vào mức độ gần gũi của việc triển khai ReactOS với việc triển khai MS, bạn có thể lục lọi trong bộ nhớ để tìm ra cấu trúc, nhưng đó là điều tôi nghĩ ...

BOOL FASTCALL
GetHotKey (UINT fsModifiers,
           UINT vk,
           struct _ETHREAD **Thread,
           HWND *hWnd,
           int *id)
{
   PHOT_KEY_ITEM HotKeyItem;

   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
   {
      if (HotKeyItem->fsModifiers == fsModifiers &&
            HotKeyItem->vk == vk)
      {
         if (Thread != NULL)
            *Thread = HotKeyItem->Thread;

         if (hWnd != NULL)
            *hWnd = HotKeyItem->hWnd;

         if (id != NULL)
            *id = HotKeyItem->id;

         return TRUE;
      }
   }

   return FALSE;
}

Tôi cho rằng chủ đề này trên sysinternals đã được hỏi bởi một người nào đó liên quan đến câu hỏi này, nhưng tôi nghĩ dù sao thì tôi cũng muốn liên kết với nó để giữ cả hai cùng nhau. Chủ đề trông rất hấp dẫn, nhưng tôi nghi ngờ rằng một số spelunking lặn sâu sẽ cần phải xảy ra để tìm ra điều này mà không cần truy cập vào nội bộ MS.


3

Ngoài ra, bạn có thể thử liệt kê tất cả các cửa sổ bằng EnumWindows, sau đó trong lệnh gọi lại, hãy gửi WM_GETHOTKEY đến từng cửa sổ.

Chỉnh sửa: Thực sự là tôi đã sai về điều đó. MSDN có thêm thông tin:

WM_HOTKEY không liên quan đến các phím nóng WM_GETHOTKEY và WM_SETHOTKEY. Thông báo WM_HOTKEY được gửi cho các phím nóng chung trong khi các thông báo WM_SETHOTKEY và WM_GETHOTKEY liên quan đến các phím nóng kích hoạt cửa sổ.

Lưu ý: Đây là một chương trình nhằm mục đích có chức năng mà bạn đang tìm kiếm. Bạn có thể thử dịch ngược nó.


3
Liên kết đến chương trình hiện đã bị hỏng hoàn toàn. Đó là chương trình gì? Đã rất nhiều lần tôi muốn tìm ra chương trình nào đã đăng ký phím nóng của mình vì đột nhiên chúng không hoạt động nữa hoặc làm những điều mới khó chịu.
James Oltmans

(Thông thường, Wayback Machine có thể trợ giúp trong trường hợp trang web biến mất, nhưng ở đây nó cũng chỉ phản ánh lỗi 404 Not Found: http://web.archive.org/web/*/tds.diamondcs.com.au/dse/ phát hiện / phím nóng.php )
Aaron Thoma

2

Điều này dường như cho bạn biết rất nhiều điều: http://hkcmdr.anymania.com/help.html


1
Phải không? Một DLL cải trang thành trình điều khiển? Hàm DLL được xuất dưới dạng hoosử dụng SetWindowHookExđể đặt hai móc, một WH_KEYBOARD_LLvà một WH_GETMESSAGE... phần còn lại sẽ được ghi lại khá nhiều trên MSDN.
0xC0000022L

Không sử dụng ứng dụng này trên Windows 8 hoặc 10.
Jeff Lange

1

Một chủ đề khác đề cập đến móc bàn phím cấp NT toàn cầu:

Gán lại / ghi đè phím nóng (Win + L) để khóa cửa sổ

có thể bạn có thể nhận được xử lý của quy trình được gọi là hook theo cách đó, sau đó bạn có thể giải quyết tên quy trình

(tuyên bố từ chối trách nhiệm: Tôi đã có nó trong dấu trang của mình, chưa thực sự thử / kiểm tra)


0

Tôi biết bạn có thể chặn luồng thông báo trong bất kỳ cửa sổ nào trong quy trình của riêng bạn - cái mà chúng ta thường gọi là phân lớp trong VB6. (Mặc dù tôi không nhớ chức năng, có lẽ là SetWindowLong?) Tôi không chắc liệu bạn có thể thực hiện việc này cho các cửa sổ bên ngoài quy trình của riêng mình hay không. Nhưng vì lợi ích của bài đăng này, hãy giả sử bạn tìm ra cách để làm điều đó. Sau đó, bạn có thể chỉ cần chặn các thông báo cho tất cả các cửa sổ cấp cao nhất, giám sát thông báo WM_HOTKEY. Bạn sẽ không thể biết tất cả các phím ngay lập tức, nhưng khi chúng được nhấn, bạn có thể dễ dàng tìm ra ứng dụng nào đang sử dụng chúng. Nếu bạn lưu kết quả vào đĩa và tải lại mỗi lần chạy ứng dụng màn hình, bạn có thể tăng hiệu suất của ứng dụng theo thời gian.


-1

Điều này không trả lời chính xác phần câu hỏi về Windows API, nhưng nó trả lời phần câu hỏi về danh sách các phím nóng toàn cầu và các ứng dụng "sở hữu" chúng.

Hotkey Explorer miễn phí tại http://hkcmdr.anymania.com/ hiển thị danh sách tất cả các phím nóng toàn cầu và các ứng dụng sở hữu chúng. Điều này chỉ giúp tôi tìm ra lý do tại sao một phím tắt dành riêng cho ứng dụng ngừng hoạt động và cách khắc phục nó (bằng cách định cấu hình lại phím nóng chung đã đăng ký trong ứng dụng đã đăng ký), trong vòng vài giây.


4
đã cài đặt nó và nó hoạt động giống như một con virus, ít nhất là một chương trình có mục đích mua sắm, giống như một trò đùa dở khóc dở cười. Mở tất cả các loại cửa sổ, kích hoạt trình điều hướng giọng nói, v.v.
Flion

3
@Flion: Xem thảo luận trên superuser.com/a/191090/3617 . Về cơ bản, một số tính năng sử dụng phím nóng hoạt động bằng cách thăm dò mọi tổ hợp phím có thể. Trên Windows 8+, (và ở mức độ thấp hơn trên Windows 7), kỹ thuật thăm dò này kích hoạt mọi tổ hợp phím, thay vì chỉ truy vấn nó.
Brian

@Flion FWIW, tôi đã sử dụng nó trên Win7 thành công. Nhưng nếu tôi hiểu Brian một cách chính xác, điều này có thể không hoạt động tốt với các phiên bản sau và nó hoạt động tốt như thế nào cũng có thể phụ thuộc vào các phím nóng tùy chỉnh được xác định.
Gerhard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.