| Autor |
Beitrag |
Balu
Hält's aus hier
Beiträge: 11
|
Verfasst: Do 21.09.06 13:45
Wie kann ich auf einen langen Tastendruck nur einmal reagieren?
Wenn ich in meinem Programm das Menü auswähle und mit den Pfeiltasten navigieren möchte, aber die Taste zu lange drücke rennt der Cursor unaufhörlich durch die Menüpunkte.
Ich möchte immer nacheinander nur das nächste Menü angezeigt bekommen. Wie kann ich den Tastendruck innerhalb des Menüs nur einmal annehmen?
Gibt es eine eigenschaft füt TMenuItem, die ich übersehen habe?
Danke & Gruß Balu
|
|
Jakob Schöttl
      
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Do 21.09.06 14:29
also, interessante frage, aber ich hab ne lösung rausgefunden:
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:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) ListBox1: TListBox; procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure ListBox1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); private public end;
var Form1: TForm1; TasteBereitsGedrueckt: Boolean;
implementation
{$R *.dfm}
procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Tastebereitsgedrueckt then Key := 0; Tastebereitsgedrueckt := True; end;
procedure TForm1.ListBox1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin Tastebereitsgedrueckt := False; end;
end. |
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Do 21.09.06 14:34
Vielen Dank für die Antwort.
Genauso habe ich das auch für meine Dialoge gelöst.
Aber im Menü habe ich das Probelm, dass ich leider nicht auf ein OnKeyDown-Ereignis regieren kann. Das gibt es in der Form für die Menüs nicht.
Wenn du noch eine Idee hast, wäre ich sehr dankbar!
Gruß Balu
|
|
Jakob Schöttl
      
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Do 21.09.06 14:46
Achso, daran hab ich nicht gedacht, dass es dieses Ereignis bei TMainMenu nicht geben könnte! Dann fällt mir leider wirklich nix ein...
Darf ich fragen (reines Interesse), für was du das brauchst?
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Do 21.09.06 14:50
Klar darfst du fragen.
Nur eine Antwort bekommst du nicht... nein, spaß beiseite.
Wir machen ein System für Blinde. Diese Menschen können beim Navigieren im Menü nicht sehen, wo der Cursor steht bzw. welches menü gerade angewählt ist. Aus diesem Grund wird ihnen der Menüpunkt immer angesagt. Wenn die Auswahl im Menü aber zu schnell ist, kommt die Ansage nicht hinterher und man hört gar nichts. Deshalb wäre es sinnvoll nach jedem Tastendruck nur einen Menüpunkt wieterzugehen.
War das Verständlich?
Gruß Balu
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Do 21.09.06 23:02
Hallo,
die Message WM_MENUSELECT abfangen, Flag setzen und das Vorlesen starten.
Am Ende des Vorlesens den Tastaturpuffer leeren damit die während des Vorlesens gedrückten Tasten keine weiteren Messages WM_MENUSELECT auslösen können.
Ein Beispiel(geht eventuell besser/anders ..?.) durch überschreiben der wndProc:
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:
| private FLiestVor : Boolean; procedure VorLesen; procedure WndProc(var Message: TMessage); override; public end;
var Form1: TForm1;
implementation
{$R *.DFM} function ClearKeyboardBuffer:Integer; var Msg: TMsg; begin Result := 0; while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do Inc(Result); end;
procedure TForm1.VorLesen; var i : Integer; begin FLiestVor := True; Sleep(2000); i := ClearKeyboardBuffer; Memo1.Lines.Add('Tasten gelöscht: '+IntToStr(i)); FLiestVor := False; end;
procedure TForm1.WndProc(var Message: TMessage); var mgsTemp: TMsg; begin if Message.Msg = WM_MENUSELECT then if FLiestVor then Message.Result := 0 else VorLesen;
inherited WndProc(Message); end;
procedure TForm1.FormCreate(Sender: TObject); begin FLiestVor := False; end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Fr 22.09.06 12:10
Nach längerem Testen bin ich leider noch nicht weitergekommen.
Der Vorschlag hört sich aber sehr gut an.
Ich habe alle Abfragen in eine Procedure gepackt. Vielleicht siehts du an irgendeiner Stelle ja Schwierigkeiten.
Hier der Code:
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:
| procedure TFormMainLeseAs.WndProc(var Message: TMessage); var mgsTemp: TMsg; msg : tagMsg; i : integer; begin if Message.Msg = WM_MENUSELECT then begin i := 0; if (DlgOptionVoiceMenu.SpSpeech.VoiceStatus = SPEAKINGDONE) or (DlgOptionVoiceMenu.SpSpeech.VoiceStatus = SPEAKINGPAUSED) then begin inc(i); end else begin sleep(2000); Message.Result := 0; while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do begin Inc(i); end; end; end; inherited WndProc(Message); end; |
Danke Balu
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Fr 22.09.06 13:49
Hallo,
Wodurch wird das Vorlesen gestartet?
Wird WM_MENUSELECT ausgelöst während das Vorlesen läuft?
Sollte das nicht der Fall sein reicht es eventuell aus nur den Tastaturpuffer mit der Funktion ClearKeyboardBuffer zu leeren, wenn SPEAKINGDONE oder SPEAKINGPAUSED zutrifft.
Leg Dir doch mal ein Memo mit auf die Form und lass dir im Memo folgendes eintragen:
-> Start Vorlesen
-> Pause Vorlesen
-> Ende Vorlesen
-> auftreten von WM_MENUSELECT in der WndProc
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Fr 22.09.06 14:27
Guter Tipp, vielen Dank, werde ich am Montag mal ausprobieren, gehe nämlich jetzt ins Wochenende.
Dir wünsche ich auch ein schönes WE
Gruß Balu
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Mo 25.09.06 09:16
So, das Wochenende ist rum und ich bin wieder da.
Ich habe mal die Tipps beachtet. Ich weiß jetzt, dass laut Programm das Vorlesen beendet ist, wenn das nächste mal WM_MENUSELECT angewählt wird. Aber aus dem Lautsprecher kommt kein Ton und die Menüs werden immer noch zu schnell nacheinander ausgewählt.
Anscheinend muss ich in eine andere Richtung denken! O man...
Mal sehen, was mir so einfällt.
Gruß Balu
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mo 25.09.06 10:10
Hallo,
Balu hat folgendes geschrieben: | | Ich weiß jetzt, dass laut Programm das Vorlesen beendet ist, wenn das nächste mal WM_MENUSELECT angewählt wird. |
also direkt nach dem Vorlesen den Tastaturpuffer leeren.
Balu hat folgendes geschrieben: | | Aber aus dem Lautsprecher kommt kein Ton |
anderes Problem?
Balu hat folgendes geschrieben: | | und die Menüs werden immer noch zu schnell nacheinander ausgewählt. |
deshalb Tastaturpuffer leeren, denn die aufgezeichneteten Tasten im Tastaturpuffer bewirken das auswählen der Menüitems > WM_MENUSELECT.
Lannes hat folgendes geschrieben: | | Wodurch wird das Vorlesen gestartet? |
Folgendes funktioniert:
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:
| private procedure VorLesen; procedure WndProc(var Message: TMessage); override; public end; var Form1: TForm1;
implementation
{$R *.DFM} function ClearKeyboardBuffer:Integer; var Msg: TMsg; begin Result := 0; while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do Inc(Result); end; procedure TForm1.VorLesen; var i : Integer; begin Sleep(3000); i := ClearKeyboardBuffer; Memo1.Lines.Add('Tasten gelöscht: '+IntToStr(i)); end; procedure TForm1.WndProc(var Message: TMessage); var mgsTemp: TMsg; begin if Message.Msg = WM_MENUSELECT then VorLesen; inherited WndProc(Message); end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
Balu 
Hält's aus hier
Beiträge: 11
|
Verfasst: Mo 25.09.06 11:07
Ich habe den Tastaturpuffer geleert. Das habe ich getestet. Es folgt aber der gleiche Effekt.
Die Sprechfunktion reagiert, als ob schon gesprochen wurde, obwohl nichts aus dem Lautsprecher kam, also nicht gesprochen wurde. Die Funktionen reagieren richtig.
Ich denke, das Problem liegt an der Sprachausgabe. Dass dein Programm funktioniert glaube ich dir und kann es auch nachvollziehen. Bedenke, dass die Sprechfunktion in deinem Testprogramm nicht spricht.
Ich habe in der Sprechfunktion eingestellte Flags gefunden. Bei dem einen wird der zu sprechende Text in die Queue geschrieben, das Programm kehrt zurück, bei dem anderen hat der gesprochene Text Vorranng. Diese beiden Flags sind mit or verknüpft.
Wenn ich nur das "Vorrang"-Flag setze habe ich keine Probleme mehr. Jetzt muss ich nur noch abklären, ob das andere Flag benötigt wird oder nicht.
Nochmals DANKE!!!
Balu
|
|