Entwickler-Ecke

Sonstiges (Delphi) - dynamische Tastenkombinationen?


cs-schmarotzer - Do 29.05.03 19:44
Titel: dynamische Tastenkombinationen?
Ich habe momentan ein Programm, dass konstante Tastenbombinationen in einem Timer abfragt und bei erfolgt eine funktion ausfuehrt. So siehts aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm.Timer_checkkeys (bla);
begin
   if GetAsyncKeyState(VK_CONTROL) AND GetAsyncKeyState(VK_F9)
      then HideMainForm();
//noch ein paar andere abfragen der gleichen art
end;

Ich habe eine Listbox, in der alle Funktionen aufgelistet sind, die ich per Tastenkombination starten will. Wie kann ich dafuer jetzt neue Kombinationen einlesen und dann im Timer abfragen, ob die entsprechenden Tasten gedrueckt werden?
Danke
Christian


mimi - So 01.06.03 18:04


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  keys:array[0..255of Bool;

KeyDown
  keys[key]:=True

KeyUP
  keys[key]:=False

so würde ich es machen


Simon Joker - Mo 02.06.03 10:27

Hi cs-schmarotzer

Ich hatte mal sowas entwickelt. Das Testproggie ist nicht perfekt, aber es sollte dir den Weg weisen. Es enthält noch viel Müll vom ausbrobieren. Anhander der Komponenten solltest du dir das Proggram nach bauen können.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
unit UnitMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids, IniFiles, ComCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;    
    SG: TStringGrid;
    BuSaveKeyMap: TButton;
    BuLoadKeyMap: TButton;
    Button3: TButton;
    Label3: TLabel;
    Label4: TLabel;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure BuSaveKeyMapClick(Sender: TObject);
    procedure BuLoadKeyMapClick(Sender: TObject);
    procedure SGSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure ShowKeyState;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Button3Click(Sender: TObject);
    procedure SGDblClick(Sender: TObject);
    procedure SGKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  OrderRect=record
    Name :string[10];
    Key1_1  :byte;
    Key1_2  :byte;
    Key2_1  :byte;
    Key2_2  :byte;
  end;

var
  Form1: TForm1;
  CaptureKeyCode1:boolean=false;
  CaptureKeyCode2:boolean=false;
  CaptureFirst:boolean=false;
  CaptureSecond:boolean=false;
  col:integer;
  row:integer;
  KeyState: array [0..255of boolean;
  KeyNames: array [0..255of string[10];
  Orders: array [1..20of OrderRect;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
    KeyMap:TIniFile;
begin
  SG.Cells[0,0]:='Befehl';
  SG.Cells[1,0]:='Taste1';
  SG.Cells[2,0]:='Taste2';
  //Beschriftung
  for i:=1 to 20 do begin
    SG.Cells[0,i]:='Befehl'+IntToStr(i);
    Orders[i].Name:='Befehl'+IntToStr(i);
    Orders[i].Key1_1:=0;
    Orders[i].Key1_2:=0;
    Orders[i].Key2_1:=0;
    Orders[i].Key2_2:=0;
  end;
  // Initialise
  KeyMap:=TIniFile.Create(ExtractFilePath(Application.ExeNAme)+'SpecialKeyName.ini');
  for i:=0 to 255 do begin
    KeyNames[i]:=KeyMap.ReadString('KeyNames',IntToStr(i),Chr(MapVirtualKey(i,2)));
  end;
  KeyMap.Free;
end;

procedure TForm1.SGSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
  CaptureKeyCode1:=false;
  CaptureKeyCode2:=false;
  Label4.Caption:='false/false';
  if Orders[Row].Key1_1=0 then
    SG.Cells[1,Row]:='';
  if Orders[Row].Key2_1=0 then
    SG.Cells[2,Row]:='';
  Row:=ARow;
  Col:=ACol;
end;

procedure TForm1.SGDblClick(Sender: TObject);
begin
  if (Row>0and (Col=1then begin
    CaptureKeyCode1:=true;
    Orders[row].Key1_1:=0;
    Orders[row].Key1_2:=0;
    SG.Cells[1,Row]:='??????';
  end;
  if (Row>0and (Col=2then begin
    CaptureKeyCode2:=true;
    Orders[row].Key2_1:=0;
    Orders[row].Key2_2:=0;
    SG.Cells[2,Row]:='??????';
  end;
  if CaptureKeyCode1 then
    Label4.Caption:='true/'
  else
    Label4.Caption:='false/';
  if CaptureKeyCode2 then
    Label4.Caption:=Label4.Caption+'true'
  else
    Label4.Caption:=Label4.Caption+'false';
  if CaptureKeyCode1 or CaptureKeyCode2 then begin
    CaptureFirst:=true;
    CaptureSecond:=true;
  end;
end;

procedure TForm1.SGKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if CaptureKeyCode1 then
    CaptureKeyCode1:=false;
  if CaptureKeyCode2 then
    CaptureKeyCode2:=false;
  if CaptureKeyCode1 then
    Label4.Caption:='true/'
  else
    Label4.Caption:='false/';
  if CaptureKeyCode2 then
    Label4.Caption:=Label4.Caption+'true'
  else
    Label4.Caption:=Label4.Caption+'false';
  CaptureFirst:=false;
  CaptureSecond:=false;
end;


//******************************************************//

procedure TForm1.ShowKeyState;
var i:integer;
    S:string;
    Keys:TKeyboardState;

begin
  GetKeyboardState(Keys);
  S:='';          //GetAsyncKeyState
  for i:=0 to 255 do
    //if Keys[i]>=128 then begin
    if (Keys[i] shr 7 =1then begin
      if S<>'' then S:=S+'&&';
      if KeyNames[i]='' then
        S:=S+IntToStr(i)
      else
        S:=S+KeyNames[i];     
    end;
  Label1.Caption:=s;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var  s:string;
begin
  KeyState[Key]:=true;
  Label2.Caption:=IntToStr((Key));
  if CaptureKeyCode1 then begin
    if CaptureFirst then begin
      Orders[Row].Key1_1:=key;
      CaptureFirst:=false;
    end else
      if CaptureSecond and (Orders[Row].Key1_1<>key) then begin 
        Orders[Row].Key1_2:=key;
        CaptureSecond:=false;
      end;
    if Orders[Row].Key1_1<>0 then begin
      s:=KeyNames[Orders[Row].Key1_1];
      if Orders[Row].Key1_2<>0 then
        s:=s+'+'+KeyNames[Orders[Row].Key1_2];
      SG.Cells[1,Row]:=s;
    end else s:='';
  end;
  if CaptureKeyCode2 then begin
    if CaptureFirst then begin
      Orders[Row].Key2_1:=key;
      CaptureFirst:=false;
    end else
      if CaptureSecond and (Orders[Row].Key2_1<>key) then begin
        Orders[Row].Key2_2:=key;
        CaptureSecond:=false;
      end;
    if Orders[Row].Key2_1<>0 then begin
      s:=KeyNames[Orders[Row].Key2_1];
      if Orders[Row].Key2_2<>0 then
        s:=s+'+'+KeyNames[Orders[Row].Key2_2];
      SG.Cells[2,Row]:=s;
    end else s:='';
  end;
  //ShowKeyState;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var  s:string;
begin
  KeyState[Key]:=false;
  Label2.Caption:=IntToStr((Key));
  if CaptureKeyCode1 then begin
    if CaptureFirst then begin
      Orders[Row].Key1_1:=key;
      CaptureFirst:=false;
    end else
      if CaptureSecond and (Orders[Row].Key1_1<>key) then begin 
        Orders[Row].Key1_2:=key;
        CaptureSecond:=false;
      end;
    if Orders[Row].Key1_1<>0 then begin
      s:=KeyNames[Orders[Row].Key1_1];
      if Orders[Row].Key1_2<>0 then
        s:=s+'+'+KeyNames[Orders[Row].Key1_2];
      SG.Cells[1,Row]:=s;
    end else s:='';
  end;
  if CaptureKeyCode2 then begin
    if CaptureFirst then begin
      Orders[Row].Key2_1:=key;
      CaptureFirst:=false;
    end else
      if CaptureSecond and (Orders[Row].Key2_1<>key) then begin
        Orders[Row].Key2_2:=key;
        CaptureSecond:=false;
      end;
    if Orders[Row].Key2_1<>0 then begin
      s:=KeyNames[Orders[Row].Key2_1];
      if Orders[Row].Key2_2<>0 then
        s:=s+'+'+KeyNames[Orders[Row].Key2_2];
      SG.Cells[2,Row]:=s;
    end else s:='';
  end;
end;



//********************************************************//

procedure TForm1.BuSaveKeyMapClick(Sender: TObject);
var KeyMap:TIniFile;
    i:integer;
begin
  KeyMap:=TIniFile.Create(ExtractFilePath(Application.ExeNAme)+'KeyMap.ini');
  for i:=1 to 20 do
    begin
      KeyMap.WriteInteger(SG.Cells[0,i],'K1_1',Orders[i].Key1_1);
      KeyMap.WriteInteger(SG.Cells[0,i],'K1_2',Orders[i].Key1_2);
      KeyMap.WriteInteger(SG.Cells[0,i],'K2_1',Orders[i].Key2_1);
      KeyMap.WriteInteger(SG.Cells[0,i],'K2_2',Orders[i].Key2_2);
    end;
  KeyMap.Free;
end;

procedure TForm1.BuLoadKeyMapClick(Sender: TObject);
var KeyMap:TIniFile;
    i:integer;
    s:string;
begin
  KeyMap:=TIniFile.Create(ExtractFilePath(Application.ExeNAme)+'KeyMap.ini');
  for i:=1 to 20 do
    begin
      Orders[i].Key1_1:=KeyMap.ReadInteger(SG.Cells[0,i],'K1_1',0);
      Orders[i].Key1_2:=KeyMap.ReadInteger(SG.Cells[0,i],'K1_2',0);
      Orders[i].Key2_1:=KeyMap.ReadInteger(SG.Cells[0,i],'K2_1',0);
      Orders[i].Key2_2:=KeyMap.ReadInteger(SG.Cells[0,i],'K2_2',0);
      if Orders[i].Key1_1<>0 then begin
        s:=KeyNames[Orders[i].Key1_1];
        if Orders[i].Key1_2<>0 then
          s:=s+'+'+KeyNames[Orders[i].Key1_2];
        SG.Cells[1,i]:=s;
      end else s:='';
      if Orders[i].Key2_1<>0 then begin
        s:=KeyNames[Orders[i].Key2_1];
        if Orders[i].Key2_2<>0 then
          s:=s+'+'+KeyNames[Orders[i].Key2_2];
        SG.Cells[2,i]:=s;
      end else s:='';
    end;
  KeyMap.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
var KeyMap:TIniFile;
    i:integer;
begin
  KeyMap:=TIniFile.Create(ExtractFilePath(Application.ExeNAme)+'SpecialKeyName.ini');
  for i:=1 to SG.RowCount-1 do
    if SG.Cells[1,i]<>'' then
      begin
        KeyMap.WriteString('KeyNames',SG.Cells[1,i],SG.Cells[2,i]);
      end;
  KeyMap.Free;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled:=False;
  ShowKeyState;
  Timer1.Enabled:=true;
end;

end.


Die SpacialKeyName.ini:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
[KeyNames]
1=MausRecht
2=MausLinks
4=MausMitte
19=Pause
9=Tab
44=Print
27=ESC
112=F1
113=F2
114=F3
115=F4
116=F5
117=F6
118=F7
119=F8
120=F9
121=F10
122=F11
123=F12
44=Druck
145=Rollen
19=Pause
20=CapsLook
36=Pos1
16=Shift
17=Strg
18=Alt
38=Up
40=Down
35=Ende
37=Left
39=Right
45=Einfg
46=Entf
144=NUM
96=NUM0
97=NUM1
98=NUM2
99=NUM3
100=NUM4
101=NUM5
102=NUM6
103=NUM7
104=NUM8
105=NUM9
13=Enter
107=NUM+
109=NUM-
106=NUM*
111=NUM/
110=NUM,
8=Back
32=Space
[/delphi]


mimi - Mo 02.06.03 13:02

ich habe auch mal sowas gemacht, mein code ist kürtzer und übersichtlicher wenn du willst packe ich es in einer unit rein und sende es dir:)


cs-schmarotzer - Mo 02.06.03 21:51

Holy Shit das wird ne weile dauern, um duch das ganze ding durchzukommen!
@Mimi: Jo das waer genial.

DANKE!!
Christian


Simon Joker - Di 03.06.03 08:39

Hi Leutz

ich habe je gesagt, daß das ein Testprogramm ist. Das meiste dient nur der Darstelleung der Tastenkombinationen. Für jeden Befehl sin zwei Kombinationen möglich. Alles was mit Labels zu tun hat, dient der Statusanzeige des KeyCaptures und der gedrückten Tasten. Die SpecialKeyName.ini ist für die Anzeige von nichtsichtbaren Tasten, wie Funktionstasten usw. Die KeyMap kann gespeichert und geladen werden. Es gibt auch eine Funktion, mit der ich die SpecialKeyName erzeugte.

@Mimi
Bitte schick mir auch deine Unit, ich bin immer an besseren Code interessiert. :D


mimi - Di 03.06.03 14:33

ich werde die unit gleich mal erstellen und dann hochladen ein test programm werde ich bei legen:)


mimi - Di 03.06.03 19:48

so hier ist die unit:)
habe es warscheinlich auf eine dumme art und weise gemacht, aber wer einen besseren code hat kann ihn mir ja senden :)

der link ist:
http://www.simhansi.de/hosted/mimi/downloads/tasten.zip


mimi - Mi 04.06.03 17:10

habe da einen vorschlag: wie wäres wenn wir uns zusammen tuen und eine perfkete unit entwicklen die das alles kann was wir uns vorgestellt haben ???


Simon Joker - Do 05.06.03 12:17

Hi mimi

da habe ich gestern auch schon dran gedacht. Wenn wir das machen, dann aber bitte ein Objekt!

meine Anforderungen wären:
- ALLE tasten können gewählt werden (auch Druck,Pause ect. (gehen bei dir nich, mimi))
- Beliebige Kombinationen möglich
- beliebig viele Befehle
- Befehle sind nach Behlsgruppen zu ordnen
- Speicheranbindung für ini-Datei/binini-Datei
- Möglichkeit mehrerer Profile
- Statusabfrage mehrer Befehle gleichzeitig
- Prüfung auch doppelte Belegungen / Einstellung doppelte Befehle in verschiedenen Gruppen erlaubt;nicht erlaubt
- enablen/disablen der Gruppen

Mehr fällt mir auf Anhieb nich ein.


cs-schmarotzer - Do 05.06.03 14:02

Hmm kewle idee.
Aber das wird ein wenig schwerer :)


mimi - Do 05.06.03 14:20

ok, und ich bin dafür ein allgemeins objekt zu schreiben das weder direcx oder opengl voraussetzt.
also wer würde mitmachen ???


Simon Joker - Do 05.06.03 14:47

ich

ohne DirectX und/oder OpenGl ist ok; davon bin ich ausgegangen.

ach ja wir müssten uns noch auf eine Delphi-Version einigen. Ich kann 4,5,6 anbieten.


mimi - Do 05.06.03 15:14

ok, ich kann d5 und d6 anbieten jewals in der standart version.
ich gehe davon aus das die meisten d6 pe nutzen also würde ich sagen wir schreiben es unter d6 bzw für alle delphi versionen am besten oder ?
so eine allgemeine unit:)

wollen wir eine einge Benutzergruppe einrichten lassen vom admin ?
für diese projekt ?
wenn ja, wer will fragen(ich habe schon eine BG:) )