Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как отследить двойное нажатие клавиши Shift [D6, WinXP]


leonidus ©   (2005-06-27 08:26:00) 

Мастера подскажите плиз, мне нужно отследить двойное нажатие клавищи Shift в любом приложении. Причем тут должно быть именно двойное нажатие а не просто долговременное удержание.

Я делаю так, по таймеру:

if HiWord(GetKeyState(VK_SHIFT)) <> 0  then
 begin
  Timer_Profile_Detector.Tag:=Timer_Profile_Detector.Tag+1;
  if Timer_Profile_Detector.tag=2 then
   begin
    DoSomething;
   end;
 end
  else Timer_Profile_Detector.Tag:=0;

Смысл тут в том, что если два тика подрят программа засекла нажатый Shift значит типа двойное нажатие. На самом деле это не так, достаточно просто подержать Shift что бы запустилась процедура DoSomething, а как перехватить именно Shift+Shift ?


alpet   (2005-06-27 14:43:00) [1]

Дык вот - для любого приложения (возможности теже):

function  PressedKey (var shift: boolean): Boolean;
var n: dword;
begin
result := false;
shift := false;
for n := 8 to 255 do
 if (GetAsyncKeyState (n) and $F000 <> 0) then
  begin
   // key := n;
   result := true;
   shift := (n = VK_SHIFT) or
            (n = VK_LSHIFT) or
            (n = VK_RSHIFT);
   if not shift then exit; // other key detected!
  end
end; // PressedKey

procedure TForm1.Timer1Timer(Sender: TObject);
var p, s: Boolean;
   k: Byte;
begin
{ Timer.Interval = 10 default
  Flag declared in TForm1.private as Boolean
  nShift declared in TForm1.private as Dword
  timeOut declared on TForm1.private as Dword
 }
p := PressedKey (s); // retrieve press key
if not p and flag then
  begin
   inc (nShift, 1);    // one shift pressed
   timeOut := 50; // startup delay
  end;
flag := s;
if p xor s then nShift := 0; // some other key pressed
if timeOut <> 0 then
 begin
  dec (timeOut);
  if timeOut = 0 then nShift := 0;
 end;
if (nShift > 1) then
 begin
  nShift := 0;
  ShowMessage ('Two shift pressed!');
 end;
end;


default   (2005-06-27 14:39:00) [2]


procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if GetAsyncKeyState(VK_SHIFT) and $8000 <> 0 then begin
   if not Odd(Timer1.Tag) then Timer1.Tag := Timer1.Tag + 1;
 end else begin
   if Odd(Timer1.Tag) then begin
     Timer1.Tag := Timer1.Tag + 1;
     if Timer1.Tag = 4 then begin
       Caption := IntToStr(Random(1000));
       Timer1.Tag := 0
     end;
   end;
 end;
end;

нужно GetAsyncKeyState для "отследить двойное нажатие клавищи Shift в любом приложении"


default   (2005-06-27 14:03:00) [3]


procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if GetKeyState(VK_SHIFT) and $8000 <> 0 then begin
   if Timer1.Tag mod 2 = 0 then Timer1.Tag := Timer1.Tag + 1;
 end else begin
   if Timer1.Tag mod 2 <> 0 then begin
     Timer1.Tag := Timer1.Tag + 1;
     if Timer1.Tag = 4 then begin
       Caption := IntToStr(Random(1000));
       Timer1.Tag := 0
     end;
   end;
 end;
end;

P.S. чуть лучше


alpet   (2005-06-27 14:02:00) [4]

Более сложный код. Проверяется, что не нажимались другие клавиши, и что Shift нажимается монопольно (т.е. без других клавиш).

function  PressedKey (var key: Byte; var shift: boolean): Boolean;
var ks: TKeyboardState;
   n: dword;

begin
result := false;
GetKeyboardState (ks);
shift := false;
for n := 8 to 255 do
 if (ks [n] and $80 <> 0) then
  begin
   key := n;
   result := true;
   shift := (n = VK_SHIFT) or
            (n = VK_LSHIFT) or
            (n = VK_RSHIFT);
   if not shift then exit; // other key detected!            
  end
end; // PressedKey

procedure TForm1.Timer1Timer(Sender: TObject);
var p, s: Boolean;
   k: Byte;
begin
{ Timer.Interval = 10 default
  Flag declared in TForm1.private as Boolean
  nShift declared in TForm1.private as Dword
  timeOut declared on TForm1.private as Dword
 }
p := PressedKey (k, s); // retrieve press key
if not p and flag then
  begin
   inc (nShift, 1);    // one shift pressed
   timeOut := 50; // startup delay
  end;
flag := s;
if p xor s then nShift := 0; // some other key pressed
if timeOut <> 0 then
 begin
  dec (timeOut);
  if timeOut = 0 then nShift := 0;
 end;
if (nShift > 1) then
 begin
  nShift := 0;
  ShowMessage ('Two shift pressed!');
 end;
end;


default   (2005-06-27 13:43:00) [5]


procedure TForm1.Timer1Timer(Sender: TObject);
begin
if GetKeyState(VK_SHIFT) and $8000 <> 0 then begin
  if Timer1.Tag mod 2 = 0 then Timer1.Tag := Timer1.Tag + 1;
end else begin
  if Timer1.Tag mod 2 <> 0 then Timer1.Tag := Timer1.Tag + 1;
  if Timer1.Tag = 4 then begin
    Caption := IntToStr(Random(1000));
    Timer1.Tag := 0
  end;
end;
end;

вот с использованием одной переменной...


Digitman   (2005-06-27 13:10:00) [6]

OnKeyDown + OnKeyUp + таймер


default   (2005-06-27 13:06:00) [7]

leonidus ©   (27.06.05 13:02) [3]
"если нужно просто отследить последовательное нажатие двух любых шифтов, то см. хелп по GetKeyState, из неё можно узнавать нажата или отпущена клавиша"
неужели сам не сообразишь...


leonidus   (2005-06-27 13:02:00) [8]

Речь идет именно о двух подряд нажатых Shift`ах не важно левых или правых.


default   (2005-06-27 09:22:00) [9]

GetKeyState имеет результатом значение типа SmallInt-это два байта
о каком HiWord может быть речь


default   (2005-06-27 09:21:00) [10]

что значит Shift+Shift?
если это нажатие левого и правого шифта, то к сожалению не NT винда не реагирует на VK_LSHIFT, VK_RSHIFT константы в GetKeyState
если нужно просто отследить последовательное нажатие двух любых шифтов, то см. хелп по GetKeyState, из неё можно узнавать нажата или отпущена клавиша


Наверх

Титульная страница Поиск, карта сайта Написать письмо