Autor Beitrag
Balu
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: Do 21.09.06 14:29 
also, interessante frage, aber ich hab ne lösung rausgefunden:

ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  TasteBereitsGedrueckt: Boolean; // globale variable


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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 929
Erhaltene Danke: 1


Delphi 7 Professional
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: 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:
ausblenden volle Höhe 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:
  
//...
private
  FLiestVor : Boolean;
  procedure VorLesen;
  procedure WndProc(var Message: TMessage); override;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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:

ausblenden 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
          //Sprache im Pausenmodus oder fertig
          inc(i);
      end else
      begin
          //Es wird gesprochen
          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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Mo 25.09.06 10:10 
Hallo,
user profile iconBalu 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.

user profile iconBalu hat folgendes geschrieben:
Aber aus dem Lautsprecher kommt kein Ton
anderes Problem?

user profile iconBalu 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.



user profile iconLannes hat folgendes geschrieben:
Wodurch wird das Vorlesen gestartet?
:?:

Folgendes funktioniert:

ausblenden volle Höhe 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:
//...  
private  
  procedure VorLesen;  
  procedure WndProc(var Message: TMessage); override;  
    { Private-Deklarationen }  
  public  
    { Public-Deklarationen }  
  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 Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: 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