Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.538 Beiträge
 
Delphi 11 Alexandria
 
#22

AW: Business-Anwendung mit FireMonkey erstellen

  Alt 30. Mär 2014, 20:19
Auch in den einzelnen Eingabefenstern kann ich nicht mit nem Shortcut eine Seite weiter oder sowas (fehlende Accelerators auf den Buttons bzw fehlende Shortcuts auf den Actions dahinter).
Es ist doch ein fruchtbarer Dialog, den wir hier führen. Habe also einen weiteren "Workaround" erstellt, der jetzt die Unterstriche in den Buttons bzw. TTabItems im OnPaint-Event des jeweiligen Controls malt (siehe anliegenden Screenshot).

Im OnkeyDown-Event der Form prüfe ich dann, ob eine Alt+Buchstaben bzw. Alt+Ziffern Kombination gedrückt wurde und rufe dazu das passende Event dafür auf (also entweder ButtonClick oder Wechsel der Seite des TTabControls).

Ich muss da allerdings zu einem wirklich abenteuerlichen Trick greifen, dass bei der Alt+Tastenkombination nicht eine Tonausgabe in Form eines "beep" kommt. Den Wert von Key auf Null oder KeyChar auf #0 zu setzen bringt leider nichts. Das einzige was das "beep" vermeidet, ist kurzfristig den Focus an ein anderes modales Fenster abzugeben. Also erzeuge ich ein kleines Fenster, das ich außerhalb des sichtbaren Anzeigebereichs anzeigen lasse. Sofort schließt es sich wieder und der eigene Dialog hat wieder den Focus (das macht der Aufruf von "Killfocus").

Es sollte noch erwähnt werden, dass das "Beep" seltsamerweise nicht kommt, wenn man eine Alt-Key+Accelerator-Taste Abfrage in der Hauptform macht. In einem modalen Dialog kommt der Ton aber.

So sieht das im OnKeyDown-Event dann aus:

Code:
procedure Tf_Bill.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
begin
  if HandleTabEvent (self.GetFocused, Key, Shift) then exit;

  if key = vkEscape then close;

  if (Shift = [ssAlt]) then begin
    case Key of
      49..52: begin
        pc1.TabIndex := key-49;
        KillFocus (self);
      end;

      87: begin if bnWeiter.Enabled then begin bnWeiterClick(NIL); KillFocus (self); end; end;
      90: begin if bnBack.Enabled then begin bnBackClick(NIL); KillFocus (self); end; end;
      70: begin if bnReady.Enabled then begin bnReadyClick(NIL); KillFocus (self); end; end;
      72: begin bnHelpClick(NIL); KillFocus (self); end;
    end;
  end;

end;
Was übrigens seltsam ist, das Abfragen der Alt-Key-Taste funktioniert nur, wenn die Optimierung in Delphi ausgeschaltet ist. Schräg, oder?

Hat jemand vielleicht noch eine andere Idee, wie man das "beep" vermeiden kann? Die Lösung funktioniert zwar, aber ein leichtes Flackern ergibt sich und ehrlich gesagt, ist mir es ja ziemlich peinlich, so was machen zu müssen.

Das mit dem Malen des Accelerator-Zeichen erreicht man dann, indem man in dem jeweiligen Paintereignis folgende Prozedur aufruft:

procedure Tf_Bill.bnWeiterPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
DrawAccelerator (Sender, canvas, ARect);
end;

Das "&" Zeichen könnt Ihr in den Buttons wie gewohnt setzen (im TTabItem geht das leider nicht, da wird dann immer das erste Zeichen mit einem Unterstrich versehen).

Die DrawAccelerator procedure sieht aus wie folgt, derzeit werden TButton, TSpeedButton und TTabItem unterstützt. Könnt Ihr natürlich frei verwenden.

Code:
procedure DrawAccelerator (Sender: TObject; canvas: TCanvas; ARect: TRectF);
var
  tf: tfilltextflags;
  a: TTextalign;
  r: TRectF;
  T: string;
  p: Integer;
  aw: extended;
  start, w: extended;
  col: TAlphaColor;
begin
  canvas.BeginScene;

  r := ARect;
  col := TAlphaColorRec.black;

  if sender is TButton then begin
    T := TButton(sender).Text;
    w := TButton(sender).canvas.TextWidth(T);
    if TButton(sender).Enabled = false then col := TAlphaColorRec.gray;
   
    case TButton(sender).TextAlign of
      TTextAlign.taCenter: start := (TSpeedButton(sender).Width -w) / 2;
      TTextAlign.taLeading: start := 1;
      TTextAlign.taTrailing: start := TSpeedButton(sender).Width -w;
    end;
  end;

  if sender is TSpeedButton then begin
    T := TSpeedButton(sender).Text;
    w := canvas.TextWidth(T);

    case TSpeedButton(sender).TextAlign of
      TTextAlign.taCenter: start := (TSpeedButton(sender).Width -w) / 2;
      TTextAlign.taLeading: start := 1;
      TTextAlign.taTrailing: start := TSpeedButton(sender).Width -w;
    end;

    if TSpeedButton(sender).Enabled = false then col := TAlphaColorRec.gray;
  end;

  if sender is TTabItem then begin
    T := TTabitem(sender).Text;
    w := canvas.TextWidth(T);

    case TTabItem(sender).TextAlign of
      TTextAlign.taCenter: start := (TSpeedButton(sender).Width -w) / 2;
      TTextAlign.taLeading: start := 8;
      TTextAlign.taTrailing: start := TSpeedButton(sender).Width -w;
    end;

    start := start + 10;
  end;

  if T = '' then begin
    canvas.EndScene;
    exit;
  end;

  P := pos ('&', T);

  aw := canvas.TextWidth(copy (T, 1, p));
  tf := [];

  a := TTextAlign.taLeading;
  r.Top := r.Top + 6;
  r.left := start + aw-7;

  canvas.Fill.Color := col;
  Canvas.FillText(r,'_',false,1,tf,a,a);
  canvas.EndScene;
end;
Miniaturansicht angehängter Grafiken
rechnung.jpg  
  Mit Zitat antworten Zitat