[FMX]从系统摄像头中获取图片

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

分享到: