注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

鑫淼梦园的博客

圆你的梦想 从这里开始

 
 
 

日志

 
 

Delphi XE8 Update1 Form状态的保存  

2015-07-03 13:45:05|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在XE8 Update1下试用,发现在Win32下正常,而到了Android下则不正常。
原文作者的实现思路值得赞赏,利用Helper的方式,为Form增加了两个方法:

  TSaveStateHelper = class helper for TCustomForm
  public const
    DATA_FIELD = 'data';
    procedure SaveFormState;//保存窗口状态
    procedure LoadFormState;//加载窗口状态
  end;

然后,利用XE8支持的JSON对象,将Form上的控件值保存到Form.SaveState.Stream中:
procedure TSaveStateHelper.SaveFormState;
var
  FormJSONObject: TJSONObject;
  I: Integer;
  FMXObj: TFmxObject;
  FMXJObj: TJSONObject;
  W: TBinaryWriter;
begin
  try
    FormJSONObject := TJSONObject.Create;
    try
      for I := 0 to Self.ComponentCount - 1 do
      begin
        if not(Self.Components[I] is TFmxObject) then
          continue;
        FMXObj := Self.Components[I] as TFmxObject;
        FMXJObj := TJSONObject.Create;
        case FMXObj.Data.Kind of
          tkUnknown:
            ;
          tkInteger:
            FMXJObj.AddPair(DATA_FIELD,
              TJSONNumber.Create(FMXObj.Data.AsInteger));
          tkChar:
            ;
          tkEnumeration:
            if FMXObj.Data.AsBoolean then
              FMXJObj.AddPair(DATA_FIELD, TJSONTrue.Create)
            else
              FMXJObj.AddPair(DATA_FIELD, TJSONFalse.Create);
          tkFloat:
            FMXJObj.AddPair(DATA_FIELD,
              TJSONNumber.Create(FMXObj.Data.AsExtended));
          tkString, tkUString, tkLString, tkWString:
            FMXJObj.AddPair(DATA_FIELD, FMXObj.Data.AsString);
          tkSet:
            ;
          tkClass:
            ;
          tkMethod:
            ;
          tkWChar:
            ;
          tkVariant:
            ;
          tkArray:
            ;
          tkRecord:
            ;
          tkInterface:
            ;
          tkInt64:
            FMXJObj.AddPair(DATA_FIELD,
              TJSONNumber.Create(FMXObj.Data.AsInt64));
          tkDynArray:
            ;
          tkClassRef:
            ;
          tkPointer:
            ;
          tkProcedure:
            ;
        end;
        FormJSONObject.AddPair(FMXObj.Name, FMXJObj)
      end;
      SaveState.Stream.Clear;
      W := TBinaryWriter.Create(SaveState.Stream);
      try
        W.Write(FormJSONObject.ToJSON);
      finally
        W.Free;
      end;
    finally
      FormJSONObject.Free;
    end;
  except
    on e: Exception do
      Log.d('SaveStateHelper', Self, e.Message);
  end;
end;

上面的代码,只是简单读取窗口上的控件,如果控件放到TLayout等布局控件中,或者使用了Frame,那则不能保存,这一点要注意,当然,可以进一步完美代码。

我们再看看作者如何加载保存过的内容到窗口控件:
procedure TSaveStateHelper.LoadFormState;
var
  R: TBinaryReader;
  FormJSONObject: TJSONObject;
  I: Integer;
  FMXObj: TFmxObject;
  FMXJObj: TJSONObject;
  s: string;
begin
  try
    if not(SaveState.Stream.Size > 0) then
      exit;
    // Recover previously typed values in all control.
    R := TBinaryReader.Create(SaveState.Stream);
    try
      FormJSONObject := TJSONObject.ParseJSONValue(R.ReadString) as TJSONObject;
      try
        for I := 0 to Self.ComponentCount - 1 do
        begin
          if not(Self.Components[I] is TFmxObject) then
            continue;
          FMXObj := Self.Components[I] as TFmxObject;
          FMXJObj := FormJSONObject.Values[FMXObj.Name] as TJSONObject;
          if FMXJObj = nil then//这里,我加了判断
            continue;
          if FMXJObj.Values[DATA_FIELD] <> nil then//这里,我加了判断
            continue;

          case FMXObj.Data.Kind of
            tkUnknown:
              ;
            tkInteger:
              FMXObj.Data :=
                (FMXJObj.GetValue(DATA_FIELD) as TJSONNumber).AsInt;
            tkChar:
              ;
            tkEnumeration:
              if FMXJObj.GetValue(DATA_FIELD) is TJSONTrue then
                FMXObj.Data := true
              else
                FMXObj.Data := false;
            tkFloat:
              FMXObj.Data :=
                (FMXJObj.GetValue(DATA_FIELD) as TJSONNumber).AsDouble;
            tkString, tkUString, tkLString, tkWString:
                FMXObj.Data :=
                  (FMXJObj.GetValue(DATA_FIELD) as TJSONString).Value;
            tkSet:
              ;
            tkClass:
              ;
            tkMethod:
              ;
            tkWChar:
              ;
            tkVariant:
              ;
            tkArray:
              ;
            tkRecord:
              ;
            tkInterface:
              ;
            tkInt64:
              FMXObj.Data :=
                (FMXJObj.GetValue(DATA_FIELD) as TJSONNumber).AsInt64;
            tkDynArray:
              ;
            tkClassRef:
              ;
            tkPointer:
              ;
            tkProcedure:
              ;
          end;
        end;
      finally
        FormJSONObject.Free;
      end;
    finally
      R.Free;
    end;
  except
    on e: Exception do
      Log.d('SaveStateHelper', Self, e.Message);
  end;
end;

关于SaveState对象,是TForm的一个属性,是Delphi实现的用来保存窗口的状态,当使用SaveState.Stream时,会自动读取 前期保存过的内容到SaveState.Stream中,即当我们使用SaveState.Stream进,Stream会自动加载。

通过上面的代码,我们很清晰的看到如何操作SaveState.Stream这个对象,值得学习。
由于在Android下不能正常运行,通过跟踪delphi的实现,发现Delphi在Android下存在bug,暂时我也没清楚,不过,找到暂时避开这个bug的方法,那就是设置保存内容的路径,下面代码红色部分是设置SaveState的路径,测试,在Win32及Android通过。

procedure TForm1.FormCreate(Sender: TObject);
begin
   if TPlatformServices.Current.SupportsPlatformService(IFMXSaveStateService, SaveStateService) then
     SaveStateService.SetStoragePath(System.IOUtils.TPath.GetDocumentsPath);
  LoadFormState;
end;

通过跟踪关于Delphi对Form状态的管理的实现,能够理解,原来Delphi是想在我们不设置这个路径的情况下,只是操作SateState对象,也能正常工作,即最大的简化开发者的代码量,只可惜在Android上没实现好。(没有在Xe7下试是否正常工作,只是在XE8 update1测试)

此外,在android下,如果直接在MainForm上直接退出应用,Form.OnSaveState事件,没有触发,如果在这个事件中保存Form状态,则不能保存。如果用Home返回应用,再进应用,这个事件工作正常。

另,没有取得原文作者的同意,如果侵权,可留言告之,我会删除此文。

  评论这张
 
阅读(154)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017