Delphi Xe - Les actions du TRIBBON envoient toujours une mise au point à Mainform
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?
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;