Powiązanie klawisza z przyciskiem programu

0

Witam

Mam taki problem:
Chce zrobić aby naciśnięcie klawisza na klawiaturze wykonało jakąś operacje, która normalnie jest przypisana do Buttona.
W onkeydown w formie daje warunek if key = 37 to, żeby wykonywał operacje (niestety je przepisuje).
Dodatkowy problem to to ze gdy kliknę myszą na button to już wszelkie skróty klawiaturowe nie działają.

0

Możesz zrobić funkcję która będzie wywoływana w momencie naciśnięcia klawisza oraz tego przycisku aby nie przepisywać.

0

Tak, mogę utworzyć klase z tą instrukcja. i podac ją zarówno w buttonClick jak i Form1.OnKeyDown, ale to nie rozwiązuje problemu. Jak klikne myszą na jakiś przycisk (zostanie on zaznaczony kropkami) to juz klawiatura nie działa, już pomijam to, że nie mogę przypisać klawiszy strzałek oraz enter czy spacji :(

0

ponieważ jak przycisk jest zaznaczony (Focus) to Form1 nie odbiera eventu keydown. musisz nadpisać (override) WndProc bo inaczej musiałbyś dla każdej kontrolki dodać onkeydown.

maxiu1989 napisał(a)

Tak, mogę utworzyć klase z tą instrukcja.

jaką klasę? starczy metoda...

0
procedure WndProc(var Mesg: TMessage); override;
 procedure xx;
procedure TForm2.WndProc(var Mesg: TMessage);
begin
   if mesg = VK_LEFT then xx;


inherited WndProc(Mesg) ;
end;

Coś takiego? (przy okazji zrozumiałem cos dot. klas :P)

procedure TForm2.WndProc(var Mesg: TMessage);
begin
   if mesg.WParam = VK_LEFT then xx;

inherited WndProc(Mesg) ;
end;

Jak daje tak to wykonuje mi 2x :( (showmessage)

2

A ustawienie właściwości formularza KeyPreview na true nie załatwia sprawy?

0

W 50% załatwia... lecz gdy zaznacze button to juz nie mozna uzywać strzalek :( nie wykonują swojej akcji tylko przeskakuja po buttonach.

Chyba tak powinno być:

if Mess.Msg = VK_LEFT then
    begin 
...
end;

ale to w ogole nie dziala :(

0

Jak daje tak to wykonuje mi 2x

jak masz w WndProc to już masz nie mieć tego w OnKeyDown.

0

Zrobilem w nowym projekcie. I mam taki kod:

unit Proba_wndproc;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
procedure WndProc(var Mesg: TMessage); override;
 procedure Show;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure Tform2.Show;
begin
showmessage('sddd');
end;


procedure TForm2.WndProc(var Mesg: TMessage);
begin
   if (mesg.msg = VK_LEFT) then Show;

inherited WndProc(Mesg);
end;


procedure TForm2.Button1Click(Sender: TObject);
begin
form2.Show;
end;

end.
0

Nie wiem czy właśnie o to Ci chodzi, ale sprawdź załącznik, masz w nim prostą aplikację rozpoznającą klawisz Escape bez względu na to która kontrolka jest aktualnie zfokusowana; Wszysto dzięki KeyPreview := True; Można używać strzałek do zaznaczania sąsiednich button'ów;

0

Działa, ale jak zmienie VK_ESCAPE na VK_LEFT to przestaje :P

50% to to że w ogole udało się przypisać takie klawisze jak CTRL, ALT, SHIFT, ESC, czy ENTER.
Natomiast mam kłopot z przypisaniem akcji do klawiszy A,B,C,D... i 1,2,3 (70%).
A jeśli chodzi o strzałki to chciałbym także do nich przypisać jakąś akcję. A jedynie co robią to przestawiają focus na inne buttony (100%).

Mając na myśli % mniej wiecej o to chodzilo :)

EDIT 2 :

Mam 3 problemy:

  1. Przypisanie procedury do klawisza
  2. Przypisane akcji do klawisza A,B,C oraz 1,2,3 (bo VK_A jakos nie dziala)
  3. Przypisane akcji do strzalek

Problemy 2,3 powstały gdy przetestowałem działanie kilku rozwiązań.
Byłbym w 100% zadowolony gdyby udało się rozwiązać wszystke 3 problemy, ale że od biedy 1 sposób (z wykorzystaniem klawiszy CTRL lub ALT) mogło by wystarczyc uznałem ze to takie 50% :P

1
maxiu1989 napisał(a)

(bo VK_A jakos nie dziala)

Ponieważ nie ma czegoś takiego jak VK_A, VK_B ... VK_Z, tych stałych nie zadeklarowano; Za to parametr Key w zdarzeniu OnKeyDown jest typu Word, więc możesz się odwołać po numerze ASCII znaku w systemie szesnastkowym; W załaczniku masz plik z wszystkimi (przynajmniej najważniejszymi) kodami klawiszy;


Jeśli chodzi o klawisze specjalne, takie jak Shift, Control czy Alt - w zdarzeniach OnKeyDown i OnKeyUp masz parametr Shift typu TShiftState - jest to zbiór, w którym przechowywany jest stan wciśniętych klawiszy specjalnych;

Możliwe wartości w tym typie (źródło - pomoc DB7):

Value Meaning
ssShift The Shift key is held down
ssAlt The Alt key is held down
ssCtrl The Ctrl key is held down
ssLeft The left mouse button is held down
ssRight The right mouse button is held down
ssMiddle The middle mouse button is held down
ssDouble The mouse was double-clicked
Jeśli chcesz sprawdzić, czy wciśnięty jest np. klawisz Shift, sprawdzasz to w standardowy sposób dla zbiorów:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if ssShift in Shift then
    ShowMessage('Klawisz SHIFT wciśnięty!')
  else
    ShowMessage('Brak klawisza SHIFT...');
end;

Jak widać sprawdzenie nie jest najtrudniejsze; Jeżeli potrzebujesz sprawdzić stan wciśnięcia jednego ze specjalnych klawiszy (któregoś z powyższej tabelki) - sprawdź to w parametrze Shift, resztę odczytuj z parametru Key;


Na inne pytania odpowiem jutro, sam już trochę procentów mam...

0

Wielkie Dzieki, odpowiadać o prawie 2 w nocy... rzeczywiście jesteś Furious Programming XD

0

A co z pkt 3? Jak prawidłowo podmienić klawisze w Wndproc.

Cos wpisalem do delphi to sprawdzanie czy jest wciśnięty klawisz Shift i w Delphi XE2 nie dziala w ogole, a w Delphi 7 pokazuje komunikat jak kliknę myszką (wychodzi ze brak klawisza) jak kliknę z shiftem (to wychodzi ze jest wcisniety). Myslałem że to będzie działać tak, że wystarczy klikać sam shift :/

EDIT:
Albo już działa. Wpisalem jeszcze raz i ok. Poza tym nie można sprawdzić w taki sposób bo jak jest wpisane w Down to zawsze pokaże że jest wciśnięty a jak w UP to że nie jest, ale ważne że coś działa :)

0

A co z pkt 3? Jak prawidłowo podmienić klawisze w Wndproc.

Wasze używanie WndProc wynika tylko z nieznajomości Delphi. Wywal ten WndProc i napisz wszystko w czystym delfi.

Wytłumacz raz jeszcze co chcesz osiągnąć to może ogarnę i będę w stanie pomóc.

0

ok.

Chcę aby po kliknięciu literki A, Shift i lewej strzałki pokazał się komunikat.

Gdy mam czystą formę to delphi wyswietla komunikat gdy kliknę klawisz np. Shift lub lewa strzałkę.
Do literki A mam taki kod:
if key = 41 then show; // ale nie działa

Jak dodam na formę kilka przycisków to przestaje działać lewa strzałka :(

Sprawdzilem jakie kody mają moje klawisze i literka 'A' ma 65 :D

0

Chcę aby po kliknięciu literki A, Shift i lewej strzałki pokazał się komunikat.

Wszystkiego naraz? To może być problem w czystym Delfi, ja bym próbował się pobawić z tym:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx

względnie tym też się da:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299(v=vs.85).aspx

W każdym razie tutaj raczej ani delfi, ani WndProc nie jest skutecznym rozwiązaniem, bo można się bawić, tylko po co.

Nawet sobie szybko napisałem mały kodzik, który używa pierwszej metody którą wspomniałem. Kodu nie dam ze względu na motywujący i uczący charakter moich wypowiedzi. Albo, no dobra, tutaj masz część, która sprawdza czy dany klawisz jest w danym momencie wciśnięty (to jest dosyć problematyczne):

function MyGetAsyncKeyState(w:word):boolean;
var
  b:smallint;
begin
  b:=smallint(GetAsyncKeyState(w));
  result:=(b and $8000)<>0;
end; 
0

Kurcze, sorki źle napisałem, co prawda twoja interpretacja podsuneła mi kolejne pytanie i problem ale chodziło mi o osobne wciskanie a efekt ten sam

Oddzielnie? No to co za problem napisać zmienną która odpowiada temu jak daleko zaszliśmy w autoryzacji, i analizować klawisze które wciskamy. Jeżeli klawisz odpowiada poziomowi autoryzacji, to zwiększamy poziom autoryzacji, jeżeli nie, to zerujemy.
Problem może być z Shiftem, ale tutaj musisz sam sobie to sprawdzić, jak się zachowują callbacki w zależności od stanu shifta.

Wyglądać to będzie o jakoś tak:

if (auth=0)and(key='A') then auth:=1 else
if (auth=1)and(key='B') then auth:=2 else
if (auth=2)and(key='C') then {O mamy kolejność ABC} else auth:=0;
0

Heh :P

Może jeszcze raz.
Klawisz A ma wykonać showmessage,
Klawisz shift ma wykonać showmessage,
Klawisz lewa strzałka ma wykonać showmessage,

Umiem zrobić tak żeby po kliknieciu A czy shift czy lewj strzalki wykonala sie operacja lecz problem pojawia sie gdy na formie sa buttony, wtedy lewa strzalka zamiast wykonywać showmessage, przestawia focus na kolejne przyciski.

0

Umiem zrobić tak żeby po kliknieciu A czy shift czy lewj strzalki wykonala sie operacja lecz problem pojawia sie gdy na formie sa buttony, wtedy lewa strzalka zamiast wykonywać showmessage, przestawia focus na kolejne przyciski.

Boże taki banał a nikt przez dwie strony Ci nie pomógł? No gratulacje dla kolegów...

Jak się tyle namęczyłeś to masz kod, powinien działać.
W OnKeyPress:

case key of
  'A':begin ShowMessage('A'); key:=#0; end;
 #16:begin ShowMessage('Shift'); key:=#0; end;
 #37:begin ShowMessage('lewo'); key:=#0; end;
 end;
0

Ale shift i lewo nic nie wyswietla, Chciałem sprawdzić jaki char umnie zwrocą te klawisze i zwracają ' ' czyli nic

Nie zwracają nic, tylko to są znaki specjalne, których wyświetlanie jest bez sensu.
Pomyliłem się w czasie debuggowania na szybko, event który wtedy jest wywoływany to FormKeyDown.
Czyli w FormKeyDown:

if key=16 then begin ShowMessage('Shift'); key:=0; end else
  if key=37 then begin ShowMessage('Lewo'); key:=0; end;

To dla A można zostawić, ale lepiej jest dać:
if upcase(key)='A' then begin ShowMessage('A'); key:=#0; end; - będzie działać też dla dużych A.

0

Tak :) teraz działa... lecz gdy dodam buttony na forme przestaje działać lewo :( i to jest mój największy problem.

A czy KeyPreview masz na true jak już ktoś powiedział a ja zapomniałem przypomnieć?

1

Tak juz nawet probuje z wyl i wl :)

U mnie działa.
Reklama mojej ulubionej alternatywy dla Delphi, pod którą piszę to i działa, chcesz to sobie sprawdź czy wolisz to nad swoje Delfi: http://www.lazarus.freepascal.org/
Ja Ci nie pomogę, bo widać to problem Delphi, Lazarus nie ma z tym problemów.

0

Chyba coś chcę przekombinować. W takim wypadku musiałbym stworzyc buttony ktore sie nie focusują. (Image?) Wtedy klawisz strzalki wykonywał by operacje a nie zmienial przycisk hmm...:/

Ok. Dzieki sprawdze jak działa Lazarus :) i Dziekuję za wszystkie wskazówki i odpowiedzi.

0

Chyba coś chcę przekombinować. W takim wypadku musiałbym stworzyc buttony ktore sie nie focusują.

Tak tak, i jeszcze jakieś magiczne sztuczki chcesz robić?

Najlepsze co teraz możesz zrobić to podać wersję Delphiego i czekać aż ktoś ci znajdzie dlaczego to nie jest tak jak powinno, albo pobrać Lazarusa, którego osobiście cenie dużo wyżej niż Delphi i się nie przejmować problemami Delfiego.

Co prawda do błędów Lazarusa trzeba się przyzwyczaić, ale da się z tym żyć, jak się już przyzwyczaisz do problemów typu zły katalog na FPC, czy złe unity do tego FPC wgrane...

i Dziekuję za wszystkie wskazówki i odpowiedzi.

Nie ma problemu, mam nadzieję że się do czegoś przydadzą.

0

Tak na Lazarusie dziala.

Co ciekawe ani w Delphi 7 ani w XE2... nie działa :P

0

Aby nie zakończyć dyskusji stwierdzeniem, że w Delphi się nie da, kawałek kodu:

var
  Form1: TForm1;
  KBHook: HHook;

function KeyboardHookProc(Code: Integer; WParam: Word; LParam: LongInt): LongInt; stdcall;

{...}

procedure TForm1.FormCreate(Sender: TObject);
begin
  KBHook:= SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, GetCurrentThreadId);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnHookWindowsHookEx(KBHook);
end;

function KeyboardHookProc(Code: Integer; WParam: Word; LParam: LongInt): LongInt; stdcall;
begin
  if LParam shr 31 = 0 then  // Magic numbers ;)
  case WParam of
    VK_LEFT:  ShowMessage('Strzałka w lewo');
    VK_SHIFT: ShowMessage('Klawisz "shift"');
    Ord('A'): ShowMessage('Klawisz "A"');
  end;
  Result:= 0;
end;

A pomysł zaczerpnąłem stąd: http://delphi.about.com/od/windowsshellapi/a/keyboard_hook.htm

PS. Co sprawdza ten dziwny warunek i co by było, gdyby go pominąć, pozostawiam już dociekliwości autora tego tematu (albo dociekliwości każdego, kto jest albo lubi być dociekliwy)

1 użytkowników online, w tym zalogowanych: 0, gości: 1