Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 1 066

/ вопрос решён /

Здравствуйте, эксперты! Как назначить глобальные "горячие" клавиши? Можно ли использовать сочетания клавиш, используя клавишу "Windows"?

alone Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: alone (статус: Посетитель)
Вопрос отправлен: 1 ноября 2007, 01:13
Состояние вопроса: решён, ответов: 3.

Ответ #1. Отвечает эксперт: min@y™

Первый нормальный вопрос за сегодня.

Цитата:

Как назначить глобальные "горячие" клавиши?

Читай хэлп или гугл по поводу функций RegisterHotkey() и UnregisterHotkey(). Вот что говорит SDK:
The RegisterHotKey function defines a hot key for the current thread.

BOOL RegisterHotKey(
HWND hWnd, // window to receive hot-key notification
int id, // identifier of hot key
UINT fsModifiers, // key-modifier flags
UINT vk // virtual-key code
);


Parameters

hWnd

Identifies the window that will receive WM_HOTKEY messages generated by the hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.

id

Specifies the identifier of the hot key. No other hot key in the calling thread should have the same identifier. An application must specify a value in the range 0x0000 through 0xBFFF. A shared dynamic-link library (DLL) must specify a value in the range 0xC000 through 0xFFFF (the range returned by the GlobalAddAtom function). To avoid conflicts with hot-key identifiers defined by other shared DLLs, a DLL should use the GlobalAddAtom function to obtain the hot-key identifier.

fsModifiers

Specifies keys that must be pressed in combination with the key specified by the nVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers parameter can be a combination of the following values:

Value Meaning
MOD_ALT Either ALT key must be held down.
MOD_CONTROL Either CTRL key must be held down.
MOD_SHIFT Either SHIFT key must be held down.


vk

Specifies the virtual-key code of the hot key.


Вот один из примеров.

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 1 ноября 2007, 08:29
Оценка за ответ: 5

Ответ #2. Отвечает эксперт: Feniks

Здравствуйте, Гадлевский Олег Вячеславович!
Держите примеры с разных сайтов:
1. http://forum.sources.ru
2. http://www.swissdelphicenter.ch
3. рассылка "Мастера DELPHI. Новости мира компонент, FAQ, статьи..."
4. http://forum.vingrad.ru

Приложение:
  1.  
  2.  
  3. unit Unit1;
  4. interface
  5. uses
  6. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;
  7.  
  8. type
  9. TForm1 = class(TForm)
  10. procedure FormActivate(Sender: TObject);
  11. procedure FormDestroy(Sender: TObject);
  12. private
  13. procedure WMHotKey(var Message: TMessage); message WM_HOTKEY;
  14. end;
  15.  
  16. var
  17. Form1: TForm1;
  18. implementation
  19.  
  20. {$R *.DFM}
  21. procedure Tform1.WMHotKey(var Message: TMessage);
  22. begin
  23. application.Restore;
  24. application.bringtofront;
  25.  
  26. end;
  27.  
  28. procedure TForm1.FormActivate(Sender: TObject);
  29. begin
  30. RegisterHotKey(form1.Handle,123,mod_control,vk_f7);
  31. end;
  32.  
  33. procedure TForm1.FormDestroy(Sender: TObject);
  34. begin
  35. UnregisterHotKey(Handle, 123)
  36. end;
  37.  
  38. end.
  39. // =======================================================
  40.  
  41.  
  42.  
  43. {
  44. The following example demonstrates registering hotkeys with the
  45. system to globally trap keys.
  46.  
  47. Das Folgende Beispiel zeigt, wie man Hotkeys registrieren und
  48. darauf reagieren kann, wenn sie gedruckt werden. (systemweit)
  49. }
  50.  
  51. unit Unit1;
  52.  
  53. interface
  54.  
  55. uses
  56. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  57. Dialogs;
  58.  
  59. type
  60. TForm1 = class(TForm)
  61. procedure FormCreate(Sender: TObject);
  62. procedure FormDestroy(Sender: TObject);
  63. private
  64. { Private declarations }
  65. id1, id2, id3, id4: Integer;
  66. procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
  67. public
  68. { Public declarations }
  69. end;
  70.  
  71. var
  72. Form1: TForm1;
  73.  
  74. implementation
  75.  
  76. {$R *.dfm}
  77.  
  78. // Trap Hotkey Messages
  79. procedure TForm1.WMHotKey(var Msg: TWMHotKey);
  80. begin
  81. if Msg.HotKey = id1 then
  82. ShowMessage('Ctrl + A pressed !');
  83. if Msg.HotKey = id2 then
  84. ShowMessage('Ctrl + Alt + R pressed !');
  85. if Msg.HotKey = id3 then
  86. ShowMessage('Win + F4 pressed !');
  87. if Msg.HotKey = id4 then
  88. ShowMessage('Print Screen pressed !');
  89. end;
  90.  
  91. procedure TForm1.FormCreate(Sender: TObject);
  92. // Different Constants from Windows.pas
  93. const
  94. MOD_ALT = 1;
  95. MOD_CONTROL = 2;
  96. MOD_SHIFT = 4;
  97. MOD_WIN = 8;
  98. VK_A = $41;
  99. VK_R = $52;
  100. VK_F4 = $73;
  101. begin
  102. // Register Hotkey Ctrl + A
  103. id1 := GlobalAddAtom('Hotkey1');
  104. RegisterHotKey(Handle, id1, MOD_CONTROL, VK_A);
  105.  
  106. // Register Hotkey Ctrl + Alt + R
  107. id2 := GlobalAddAtom('Hotkey2');
  108. RegisterHotKey(Handle, id2, MOD_CONTROL + MOD_Alt, VK_R);
  109.  
  110. // Register Hotkey Win + F4
  111. id3 := GlobalAddAtom('Hotkey3');
  112. RegisterHotKey(Handle, id3, MOD_WIN, VK_F4);
  113.  
  114. // Globally trap the Windows system key "PrintScreen"
  115. id4 := GlobalAddAtom('Hotkey4');
  116. RegisterHotKey(Handle, id4, 0, VK_SNAPSHOT);
  117. end;
  118.  
  119. // Unregister the Hotkeys
  120. procedure TForm1.FormDestroy(Sender: TObject);
  121. begin
  122. UnRegisterHotKey(Handle, id1);
  123. GlobalDeleteAtom(id1);
  124. UnRegisterHotKey(Handle, id2);
  125. GlobalDeleteAtom(id2);
  126. UnRegisterHotKey(Handle, id3);
  127. GlobalDeleteAtom(id3);
  128. UnRegisterHotKey(Handle, id4);
  129. GlobalDeleteAtom(id4);
  130. end;
  131.  
  132. end.
  133.  
  134. {
  135. RegisterHotKey fails if the keystrokes specified for the hot key have
  136. already been registered by another hot key.
  137.  
  138. Windows NT4 and Windows 2000/XP: The F12 key is reserved for use by the
  139. debugger at all times, so it should not be registered as a hot key. Even
  140. when you are not debugging an application, F12 is reserved in case a
  141. kernel-mode debugger or a just-in-time debugger is resident.
  142. }
  143. // =======================================================
  144.  
  145.  
  146.  
  147. type
  148. TForm1 = class(TForm)
  149. procedure FormCreate(Sender: TObject);
  150. procedure FormDestroy(Sender: TObject);
  151. protected
  152. procedure hotykey(var msg:TMessage); message WM_HOTKEY;
  153. end;
  154.  
  155. var
  156. Form1: TForm1;
  157. id,id2:Integer;
  158.  
  159. implementation
  160.  
  161. {$R *.DFM}
  162.  
  163. procedure TForm1.hotykey(var msg:TMessage);
  164. begin
  165. if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=81) then
  166. begin
  167.  
  168. end;
  169. if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=82) then
  170. begin
  171.  
  172. end;
  173. end;
  174.  
  175. procedure TForm1.FormCreate(Sender: TObject);
  176. begin
  177. id:=GlobalAddAtom('hotkey');
  178. RegisterHotKey(handle,id,mod_control,81);
  179. id2:=GlobalAddAtom('hotkey2');
  180. RegisterHotKey(handle,id2,mod_control,82);
  181. end;
  182.  
  183. procedure TForm1.FormDestroy(Sender: TObject);
  184. begin
  185. UnRegisterHotKey(handle,id);
  186. UnRegisterHotKey(handle,id2);
  187. end;
  188. // =======================================================
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196. If not RegisterHotkey
  197. (Handle, 1, MOD_ALT or MOD_SHIFT, VK_F9) Then
  198. ShowMessage('Unable to assign Alt-Shift-F9 as hotkey.');
  199.  
  200.  
  201.  
  202. UnRegisterHotkey( Handle, 1 );
  203.  
  204.  
  205. //WM_HOTKEY:
  206.  
  207.  
  208. Procedure WMHotkey( Var msg: TWMHotkey );
  209. message WM_HOTKEY;
  210.  
  211. Procedure TForm1.WMHotkey( Var msg: TWMHotkey );
  212. Begin
  213. If msg.hotkey = 1 Then Begin
  214. If IsIconic( Application.Handle ) Then
  215. Application.Restore;
  216. BringToFront;
  217. End;
  218. End;


Ответ отправил: Feniks (статус: Бакалавр)
Время отправки: 1 ноября 2007, 10:26
Оценка за ответ: 5

Ответ #3. Отвечает эксперт: Вадим К

Здравствуйте, Гадлевский Олег Вячеславович!
Добавлю.
Некоторые клавиши нельзя перехватывать. Это относиться Ctrl+Alt+Del. также не рекомендовано перехватывать F12. Эта клавиша зарезервирована за системой для отладчика ядра, хотя его на компьютерах обычных пользователей нет.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 1 ноября 2007, 11:32


Мини-форум вопроса

Всего сообщений: 3; последнее сообщение — 2 ноября 2007, 08:23; участников в обсуждении: 2.
min@y™

min@y™ (статус: Доктор наук), 1 ноября 2007, 08:37 [#1]:

Да, про клавишу Windows, кстати, есть такой примерчик. Недавно я наткнулся на прогу с исходниками, которая служит для показа меню вставки спецсимволов в любое поле редактирования любого окна любой программы. Называется она SpecChar. Написана на Delphi, но на чистом WinAPI. Вот что у неё там в Readme.txt:

Цитата:

Вставка спец.символов

Поместите ярлык в Автозагрузку.
Меню вызывается Win+C.


Там тоже используются функции RegisterHotkey() и UnregisterHotkey(). Найди её и скачай (или могу прислать) и изучи сорцы.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
alone

alone (статус: Посетитель), 1 ноября 2007, 22:29 [#2]:

Пришлите пожалуйста программу с исходным кодом, заранее благодарен
min@y™

min@y™ (статус: Доктор наук), 2 ноября 2007, 08:23 [#3]:

Файл SpecChar.dpr:
program SpecChar;
 
uses
  Windows,
  Messages,
  BaseUtils;
 
{$R WindowsXP.res}
 
var
  Menu: HMENU;
  Wnd, ForeWnd: HWND;
  MenuDisplay: Boolean;
  Terminated: Boolean = False;
 
function WindowProc(Wnd: HWND; Msg: UINT; WParam, LParam: Longint): Longint; stdcall;
var
  P: TPoint;
begin
  case Msg of
    WM_HOTKEY:
      if MenuDisplay then
        EndMenu
      else
      begin
        GetCursorPos(P);
        ForeWnd := GetForegroundWindow;
        SetForegroundWindow(Wnd);
        MenuDisplay := True;
        try
          TrackPopupMenu(Menu, TPM_CENTERALIGN, P.X, P.Y, 0, Wnd, nil);
        finally
          MenuDisplay := False;
          SetForegroundWindow(ForeWnd);
        end;
      end;
    WM_COMMAND:
      begin
        SetClipboard(CF_UNICODETEXT, WParam, 4);
        // Paste
        SetForegroundWindow(ForeWnd);
        keybd_event(VK_CONTROL, 0, 0, 0);
        keybd_event(Ord('V'), 0, 0, 0);
        keybd_event(Ord('V'), 0, KEYEVENTF_KEYUP, 0);
        keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
      end;
  end;
  Result := DefWindowProc(Wnd, Msg, WParam, LParam);
end;
 
procedure Init;
 
  procedure InitError(const Text: string; Code: Integer);
  begin
    MessageBox(0, PChar(Text), 'Special characters', MB_ICONERROR);
    Halt(Code);
  end;
 
var
  Mutex: THandle;
  F: file;
  UnicodeSign: WideChar;
  Chars: array[0..255] of WideChar;
  I, Count: Integer;
  NewCol: Boolean;
begin
  Mutex := CreateMutex(nil, True, 'SpecChar_Running');
  if WaitForSingleObject(Mutex, 0) <> WAIT_OBJECT_0 then
    InitError('Already running', 1);
 
  AssignFile(F, 'Chars.ini');
  FileMode := 0;
{$I-}
  Reset(F, 2);
  if IOResult <> 0 then
    InitError('Ini-file miss', 2);
 
  BlockRead(F, UnicodeSign, 1);
  if (IOResult <> 0) or (UnicodeSign <> #$FEFF) then
    InitError('Ini-file is not Unicode', 3);
 
  BlockRead(F, Chars, Length(Chars), Count);
  if Count = 0 then
    InitError('Ini-file is empty', 4);
 
  CloseFile(F);
{$I+}
  Menu := CreatePopupMenu;
  NewCol := False;
  for I := 0 to Count - 1 do
    case Chars[I] of
      '|': AppendMenuW(Menu, MF_SEPARATOR, 0, nil);
      #10, #13: NewCol := True;
    else
      AppendMenuW(Menu, Ord(NewCol) * MF_MENUBARBREAK, Ord(Chars[I]), Pointer(
        WideString(Chars[I])));
      NewCol := False;
    end;
end;
 
var
  Cls: WNDCLASS = (lpfnWndProc: @WindowProc; lpszClassName: 'AppWin');
  Msg: TMsg;
begin
  Init;
  Cls.hInstance := HInstance;
  Windows.RegisterClass(Cls);
  Wnd := CreateWindow(Cls.lpszClassName, '', WS_POPUP, 0, 0, 0, 0, 0, 0,
    HInstance, nil);
  RegisterHotKey(Wnd, 0, MOD_WIN, Ord('C'));
  repeat
    GetMessage(Msg, 0, 0, 0);
    DispatchMessage(Msg);
  until Terminated;
  UnregisterHotKey(Wnd, 0); 
  DestroyMenu(Menu);
  DestroyWindow(Wnd);
end.

Файл BaseUtils.pas:
unit BaseUtils;
 
interface
 
uses
  Windows;
 
procedure SetClipboard(Format: Cardinal; const Buffer; Size: Integer);
 
implementation
 
procedure SetClipboard(Format: Cardinal; const Buffer; Size: Integer);
var
  Data: THandle;
  DataPtr: Pointer;
begin
  OpenClipboard(0);
  EmptyClipboard;
  OpenClipboard(0);
  try
    Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, Size);
    try
      DataPtr := GlobalLock(Data);
      try
        Move(Buffer, DataPtr^, Size);
        SetClipboardData(Format, Data);
      finally
        GlobalUnlock(Data);
      end;
    except
      GlobalFree(Data);
      raise;
    end;
  finally
    CloseClipboard;
  end;
end;
 
end.

Файл chars.ini:

–—«»•·¶§|¹²³
±≈≠≥≤÷√∆∞|½¼¾
°µ‰Ω|?¥|©®™


Копирайтов автор не проставил, так что неизвестен. :(
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

31 января 2011, 20:02: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 12:01
Выполнено за 0.04 сек.