当我将TRibbon控件放在不是应用程序MainForm的表单上时,TRibbon的操作(即剪切,粘贴)将始终在执行操作后将焦点返回到MainForm。
即使持有TRibbon的TForm不是MainForm的子代,也会发生这种情况。
我使用的是Windows 7 64位,Embarcadero RAD Studio XE版本15.0.3953.35171。
我是否错误地使用了TRibbon控件,或者这是TRibbon的一个问题?
答案 0 :(得分:2)
这显然是设计上的。来自'ribbonactnctrls.pas'的示例代码段:
procedure TRibbonBaseButtonControl.Click;
begin
inherited;
SetFocus(Application.MainForm.Handle);
end;
如您所见,没有检查条件可以帮助我们避免通话。菜单项选择和按键处理程序中也有相同的代码。
我可能会修改评论焦点调用的来源,并尝试查看是否有任何副作用。
作为替代方案,您可以在切换到主窗体后将焦点恢复到窗体。假设'ActionList1'是包含 not 主表单上的标准操作的TActionList:
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;
但是,每次执行操作时,这将导致主窗体短暂闪烁。如果您不想这样做,您可以更改设计,以便主表单知道何时获得不需要的焦点,并伪造它没有聚焦。
在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;
第二单元中的:
uses
unit1;
procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
begin
Form1.IgnoreFocus := True;
PostMessage(Form1.Handle, UM_CANCELIGNOREFOCUS, NativeInt(Self), 0);
end;
但是,如果你没有在项目源中设置'MainFormOnTaskBar',这还不够,因为那时主窗体不仅会获得焦点,而且会被带到前面。在这种情况下,两种形式都可以通过冻结它们的z顺序来响应不需要的焦点变化/激活。然后代码将变为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;
和unit2:
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;