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,然后将参数设置为你触发动作的控件就好了。