Question

Lorsque je place un contrôle du TRIBBON sur un formulaire qui n'est pas la principale forme de l'application, que les actions de Tribbon (c.-à-d. Coup, pâte) renverront toujours la mise au point à la mainforme après l'exécution de l'action.

Cela se produit même si le TFORM qui maintient le TRIBBON n'est pas un enfant de la mainforme.

J'utilise Windows 7 64 bits, Embarcadero Rad Studio XE version 15.0.3953.35171.

Suis-je en utilisant le contrôle du TRBBON de manière incorrecte, ou est-ce un problème avec le Tribbon?

Était-ce utile?

La solution

C'est évidemment par le design. Exemple d'extrait de code de 'rubbonactnctrls.pas':

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

Comme vous le voyez, il n'y a pas de conditions vérifiées qui nous aideraient à éviter l'appel. Il y a également le même code dans la sélection des éléments de menu et les gestionnaires d'appui de touche.


Je modifierais probablement la source commentant les appels de mise au point et j'essaierais de voir s'il y a des effets secondaires.

En tant qu'alternative, vous pouvez redonner le focus à votre formulaire une fois qu'il est passé au formulaire principal. Supposons que 'ActionList1' est la Tactionlist qui contient des actions standard sur le ne pas forme principale:

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;

Cela entraînera cependant un clignotant brièvement du formulaire principal à chaque fois qu'une action est exécutée. Si vous ne voulez pas cela, vous pouvez modifier la conception afin que le formulaire principal sache quand il obtient une concentration indésirable, et faux qu'elle ne se concentre pas.

Dans Unit1:

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;

Dans Unit2:

uses
  unit1;

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


Cependant, cela ne suffit pas si vous n'avez pas défini `` Mainformontaskbar 'dans la source de projet, car lors, le formulaire principal ne se concentrera pas seulement, mais sera mis en front. Dans ce cas, les deux formes pourraient répondre au changement / activation de mise au point indésirable en gelant leurs ordres z. Le code deviendrait alors pour Unit1:

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;

Et pour l'unité2:

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top