Frage

Wenn ich ein TRibbon-Steuerelement in einem Formular platziere, das nicht die Hauptform der Anwendung ist, wird durch die Aktionen von TRibbon (d. h. Ausschneiden, Einfügen) nach Ausführung der Aktion immer der Fokus auf die Hauptform zurückgesetzt.

Dies tritt auch dann auf, wenn die TForm, die den TRibbon enthält, kein untergeordnetes Element der Hauptform ist.

Ich verwende Windows 7 64-Bit, Embarcadero RAD Studio XE Version 15.0.3953.35171.

Benutze ich das TRibbon-Steuerelement falsch oder ist dies ein Problem mit dem TRibbon?

War es hilfreich?

Lösung

Dies ist offensichtlich beabsichtigt. Beispielcode-Snippet aus 'ribbonactnctrls.pas':

procedure TRibbonBaseButtonControl.Click;
begin
  inherited;
  SetFocus(Application.MainForm.Handle);
end;

Wie Sie sehen, wurden keine Bedingungen überprüft, die uns helfen würden, den Anruf zu vermeiden. Diesen Code gibt es auch bei der Auswahl von Menüelementen und den Handgriffen für Tastendruck.


Ich würde wahrscheinlich die Quelle ändern, die die Fokusaufrufe kommentiert, und versuchen, festzustellen, ob es irgendwelche Nebenwirkungen gibt.

Alternativ können Sie den Fokus wieder auf Ihr Formular zurücksetzen, nachdem es auf das Hauptformular umgeschaltet wurde. Angenommen, 'ActionList1' ist die TActionList, die Standardaktionen im Hauptformular not enthält:

type
  TForm2 = class(TForm)
    ..
    procedure ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
  private
   ..

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
begin
  PostMessage(Handle, WM_SETFOCUS, WPARAM(True), 0);
end;

Dies führt jedoch dazu, dass das Hauptformular bei jeder Ausführung einer Aktion kurz blinkt. Wenn Sie das nicht möchten, können Sie das Design so ändern, dass das Hauptformular weiß, wann es einen unerwünschten Fokus erhält, und vortäuschen, dass es nicht fokussiert ist.

In Einheit1:

const
  UM_CANCELIGNOREFOCUS = WM_USER + 7;

type
  TForm1 = class(TForm)
    ..
  private
    FIgnoreFocus: Boolean;
    procedure UMCancelIgnoreFocus(var Msg: TMessage); message UM_CANCELIGNOREFOCUS;
    procedure WMNCActivate(var Msg: TWMNCActivate); message WM_NCACTIVATE;
  public
    property IgnoreFocus: Boolean write FIgnoreFocus;
  end;

...
uses Unit2;

procedure TForm1.WMNCActivate(var Msg: TWMNCActivate);
begin
  Msg.Result := 0;
  if not (Msg.Active and FIgnoreFocus) then
    inherited;
end;

procedure TForm1.UMCancelIgnoreFocus(var Msg: TMessage);
begin
  FIgnoreFocus := False;
  TForm(Msg.WParam).SetFocus;
end;

in Einheit2:

uses
  unit1;

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
begin
  Form1.IgnoreFocus := True;
  PostMessage(Form1.Handle, UM_CANCELIGNOREFOCUS, NativeInt(Self), 0);
end;


Dies reicht jedoch nicht aus, wenn Sie 'MainFormOnTaskBar' nicht in der Projektquelle festgelegt haben, da dann das Hauptformular nicht nur den Fokus erhält, sondern in den Vordergrund gerückt wird. In diesem Fall könnten beide Formen auf die unerwünschte Änderung / Aktivierung des Fokus reagieren, indem sie ihre Z-Ordnungen einfrieren. Der Code würde dann für unit1: werden

const
  UM_CANCELIGNOREFOCUS = WM_USER + 7;

type
  TForm1 = class(TForm)
    ..
  private
    FIgnoreFocus: Boolean;
    procedure UMCancelIgnoreFocus(var Msg: TMessage); message UM_CANCELIGNOREFOCUS;
    procedure WMNCActivate(var Msg: TWMNCActivate); message WM_NCACTIVATE;
    procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging);
        message WM_WINDOWPOSCHANGING;
  public
    property IgnoreFocus: Boolean read FIgnoreFocus write FIgnoreFocus;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.WMNCActivate(var Msg: TWMNCActivate);
begin
  Msg.Result := 0;
  if not (Msg.Active and FIgnoreFocus) then
    inherited;
end;

procedure TForm1.WMWindowPosChanging(var Msg: TWMWindowPosChanging);
begin
  inherited;
  if FIgnoreFocus then
    Msg.WindowPos.flags := Msg.WindowPos.flags or SWP_NOZORDER;
end;

procedure TForm1.UMCancelIgnoreFocus(var Msg: TMessage);
begin
  FIgnoreFocus := False;
  TForm(Msg.WParam).SetFocus;
end;

und für Einheit2:

type
  TForm2 = class(TForm)
    ..
    procedure ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
  private
    procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging);
        message WM_WINDOWPOSCHANGING;
  public
  end;

var
  Form2: TForm2;

implementation

uses
  unit1;

{$R *.dfm}

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
begin
  Form1.IgnoreFocus := True;
  PostMessage(Form1.Handle, UM_CANCELIGNOREFOCUS, NativeInt(Self), 0);
end;

procedure TForm2.WMWindowPosChanging(var Msg: TWMWindowPosChanging);
begin
  inherited;
  if Form1.IgnoreFocus then
    Msg.WindowPos.flags := Msg.WindowPos.flags or SWP_NOZORDER;
end;

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top