FMX 从系统中获取图片预定义了一个动作,叫 TTakePhotoFromCameraAction,不过它的实现有一个小 Bug,大家要注意一下。
问题出在它默认的 ExecuteTarget 的实现中,它的代码如下:
procedure TTakePhotoFromCameraAction.ExecuteTarget(Target: TObject);
begin
if IsSupportedInterface then
FCameraService.TakePhoto(Target as TControl, GetParamsPhotoQuery);
end;问题就出在 Target 未必是 TControl 的子类。TApplication.ActionExecuteTarget 中的代码:
function TApplication.ActionExecuteTarget(Action: TBasicAction): Boolean;
function ActiveControlByForm(const Form: TCommonCustomForm): TComponent;
begin
if Form.Focused <> nil then
Result := Form.Focused.GetObject
else if (Form is TCustomForm) and (TCustomForm(Form).ActiveControl <> nil) then
Result := TCustomForm(Form).ActiveControl
else
Result := Form;
end;
function FindActiveControl: TComponent;
var
I: Integer;
begin
Result := Application;
if Screen <> nil then
begin
if Screen.ActiveForm <> nil then
Result := ActiveControlByForm(Screen.ActiveForm)
else if (Application.MainForm <> nil) and Application.MainForm.Visible then
Result := ActiveControlByForm(Application.MainForm)
else for I := Screen.FormCount - 1 downto 0 do
if Screen.Forms[I].Visible then
begin
Result := ActiveControlByForm(Screen.Forms[I]);
Break;
end;
end;
end;
var
ActiveComponent: TComponent;
begin
Result := False;
if Action <> nil then
begin
ActiveComponent := FindActiveControl;
if ActiveComponent <> nil then
Result := ActiveComponent.ExecuteAction(Action);
end;
end;只是保证了动作是 ActiveComponent ,而且 ActiveControlByForm 返回的有可能是 TForm,而 TForm 在 FMX 中却不是 TControl 的子类,所以问题就出来了。如果当前窗体没有一个 ActiveControl ,那就会返回当前的窗体,结果就是到了 TTakePhotoFromCameraAction 的 ExecuteTarget 时,由于 Target 是 TForm,不是从 TControl 继承下来的,结果出错。
好吧,这个 Bug 很低级,解决的办法也很简单,自己手动调用 ExecuteTarget,然后将参数设置为你触发动作的控件就好了。
