Но в отличии от андроида, если используете Android Studio, где достаточно реализовать только фейс - то в ХЕ7 необходимо помудохаться, особенно на С++Билдере .
Для делфи реализован класс для авто сохранения свойств , но он точно не сохраняет состояние TComboBox.
Вообще в Рад Студии со свойствами намутили , слов нет.
К примеру :
TCheckBox = class(TTextControl, IIsChecked)
То есть к свойству IsChecked можно добраться через интерфейс IIsChecked
А вот для RadioButton к IsChecked через интерфейс IIsChecked не доберешься.
Короче приходится изобретать свой трахтер.
Итак:
Для записи/восстановления будем использовать JSON и XML - кому что больше нравиться. Преимущество XML в том, что можно сохранить состояние нескольких форм,с JSON у меня не получилось записать состояние нескольких форм - файл перезаписывается. При записи текстовых полей будем кодировать в Бейс 64 - так как теоретически могут храниться любые символы, а JSON и XML файлы имеют определенную структуру и есть возможность не прочитать состояние.
С вступлением закончили - идем по коду
SaveStateHelper.h
// --------------------------------------------------------------------------- #ifndef SaveStateHelperH #define SaveStateHelperH // --------------------------------------------------------------------------- #include#include #include #include #include #include #include #include #include #include #include #include // --------------------------------------------------------------------------- class TSaveStateHelper { public: void SaveFormStateJSON(TForm *forma); void LoadFormStateJSON(TForm *forma); void SaveFormStateXML(TForm *forma); void LoadFormStateXML(TForm *forma); TStrings* GetPropertyList(TFmxObject *Component,bool includePropType); }; #endif
SaveStateHelper.срр
//--------------------------------------------------------------------------- #include#pragma hdrstop #include "SaveStateHelper.h" //--------------------------------------------------------------------------- #pragma package(smart_init) const System::String SavePathJSON=System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), System::Ioutils::TPath::GetFileNameWithoutExtension(ParamStr(0))+".json"); const System::String SavePathXML=System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), System::Ioutils::TPath::GetFileNameWithoutExtension(ParamStr(0))+".xml"); TFmxObject *FMXObj; TJSONObject *FMXJObj; TJSONObject *FormJSONObject; TStrings *jsonList; TXMLDocument *xmlDoc; //--------------------------------------------------------------------------- TStrings* TSaveStateHelper::GetPropertyList(TFmxObject *Component,bool includePropType) { Typinfo::TTypeKinds SupportKinds; SupportKinds << tkUnknown << tkInteger << tkChar << tkEnumeration << tkFloat << tkString << tkSet << tkClass << tkMethod << tkWChar << tkLString << tkWString << tkVariant << tkArray << tkRecord << tkInterface << tkInt64 << tkDynArray << tkUString << tkClassRef << tkPointer << tkProcedure; Typinfo::TPropList pList; TStrings *propList = new TStringList(); AnsiString propName,propType; //получаем список свойств int nPropCount = GetPropList((Typinfo::PTypeInfo)(Component->ClassInfo()), SupportKinds, ((Typinfo::PPropList)(&pList))); for( int j = 0; j < nPropCount; j++) { propName=pList[j]->Name; propType=(*(pList[j]->PropType))->Name; if (includePropType)propList->Add(propName + " : "+ propType); else propList->Add(propName); } return propList; } //--------------------------------------------------------------------------- void TSaveStateHelper::SaveFormStateJSON(TForm *forma) { jsonList = new TStringList(); FormJSONObject = new TJSONObject(); FMXJObj = new TJSONObject(); for (int i = 0; i < forma->ComponentCount; i++) { if (dynamic_cast (forma->Components[i])) { FMXObj=dynamic_cast (forma->Components[i]); if (GetPropertyList(FMXObj,false)->IndexOf("Text")>0 && FMXObj->ClassName().Pos("Edit")>0) FMXJObj->AddPair(FMXObj->Name,EncodeString(GetPropValue(FMXObj,"Text",true))); if (GetPropertyList(FMXObj,false)->IndexOf("ItemIndex")>0 && FMXObj->ClassName().Pos("Combo")>0)FMXJObj->AddPair(FMXObj->Name,GetPropValue(forma->Components[i],"ItemIndex",true)); if (GetPropertyList(FMXObj,false)->IndexOf("IsChecked")>0 && (FMXObj->ClassName().Pos("Check")>0 || FMXObj->ClassName().Pos("Radio")>0 || FMXObj->ClassName().Pos("Switch")>0) ) if (BOOL(GetPropValue(FMXObj,"IsChecked",true))) FMXJObj->AddPair(FMXObj->Name, new TJSONTrue()); else FMXJObj->AddPair(FMXObj->Name, new TJSONFalse()); if (GetPropertyList(FMXObj,false)->IndexOf("Date")>0 && (FMXObj->ClassName().Pos("Calendar")>0 || FMXObj->ClassName().Pos("Calendar")>0)) FMXJObj->AddPair(FMXObj->Name,GetPropValue(FMXObj,"Date",true)); if (GetPropertyList(FMXObj,false)->IndexOf("Time")>0 && FMXObj->ClassName().Pos("Time")>0) FMXJObj->AddPair(FMXObj->Name,GetPropValue(FMXObj,"Time",true)); if (GetPropertyList(FMXObj,false)->IndexOf("Value")>0 ) FMXJObj->AddPair(FMXObj->Name,GetPropValue(FMXObj,"Value",true)); } } try { FormJSONObject->AddPair(forma->Name, FMXJObj->ToJSON()); jsonList->Text=FormJSONObject->ToJSON(); jsonList->SaveToFile(SavePathJSON); } __finally { FormJSONObject->Free(); FMXJObj->Free(); jsonList->Free(); } } //--------------------------------------------------------------------------- void TSaveStateHelper::LoadFormStateJSON(TForm *forma) { if (FileExists(SavePathJSON)) { jsonList = new TStringList(); jsonList->LoadFromFile(SavePathJSON); TStringBuilder *jsonStr = new TStringBuilder(jsonList->Text.Trim()); try { if (jsonList->Text.Pos("\\")>0) { jsonStr->Replace("\\",""); } if (jsonStr->Chars[forma->Name.Length()+4]=='\"') { jsonStr->Remove(forma->Name.Length()+4,1); jsonStr->Remove(jsonStr->Length-2,1); } TJSONObject *JSON = (TJSONObject*)TJSONObject::ParseJSONValue(jsonStr->ToString()); TJSONPair *formPair = JSON->Get(forma->Name); FormJSONObject = (TJSONObject*) formPair->JsonValue; TJSONPair *compPair; for (int i = 0; i < forma->ComponentCount; i++) { if (dynamic_cast (forma->Components[i])) { FMXObj=dynamic_cast (forma->Components[i]); compPair = FormJSONObject->Get(FMXObj->Name); if (GetPropertyList(FMXObj,false)->IndexOf("Text")>0 && FMXObj->ClassName().Pos("Edit")>0) SetPropValue(FMXObj,"Text",DecodeString(compPair->JsonValue->Value())); if (GetPropertyList(FMXObj,false)->IndexOf("ItemIndex")>0 && FMXObj->ClassName().Pos("Combo")>0)SetPropValue(FMXObj,"ItemIndex",compPair->JsonValue->Value()); if (GetPropertyList(FMXObj,false)->IndexOf("IsChecked")>0 && (FMXObj->ClassName().Pos("Check")>0 || FMXObj->ClassName().Pos("Radio")>0 || FMXObj->ClassName().Pos("Switch")>0) ) SetPropValue(FMXObj,"IsChecked",compPair->JsonValue->Value()); if (GetPropertyList(FMXObj,false)->IndexOf("Date")>0 && (FMXObj->ClassName().Pos("Calendar")>0 || FMXObj->ClassName().Pos("Calendar")>0)) SetPropValue(FMXObj,"Date",compPair->JsonValue->Value()); if (GetPropertyList(FMXObj,false)->IndexOf("Time")>0 && FMXObj->ClassName().Pos("Time")>0) SetPropValue(FMXObj,"Time",compPair->JsonValue->Value()); if (GetPropertyList(FMXObj,false)->IndexOf("Value")>0 ) SetPropValue(FMXObj,"Value",compPair->JsonValue->Value()); } } } __finally {jsonList->Free();jsonStr->Free();} } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void TSaveStateHelper::SaveFormStateXML(TForm *forma) { xmlDoc = new TXMLDocument(Application); xmlDoc->Active = true; xmlDoc->Encoding = "UTF-8"; xmlDoc->Options = xmlDoc->Options << doNodeAutoIndent; _di_IXMLNode parentNode,formaNode; if (FileExists(SavePathXML)) { xmlDoc->LoadFromFile(SavePathXML); parentNode=xmlDoc->DocumentElement; } else { parentNode=xmlDoc->AddChild("xml"); } if(xmlDoc->DocumentElement->ChildNodes->FindNode(forma->Name))formaNode=xmlDoc->DocumentElement->ChildNodes->FindNode(forma->Name); else formaNode = parentNode->AddChild(forma->Name); try { for (int i = 0; i < forma->ComponentCount; i++) { if (dynamic_cast (forma->Components[i])) { FMXObj=dynamic_cast (forma->Components[i]); _di_IXMLNode nodNew = formaNode->ChildNodes->FindNode(FMXObj->Name); if (!nodNew)nodNew = formaNode->AddChild(FMXObj->Name); if (GetPropertyList(FMXObj,false)->IndexOf("Text")>0 && FMXObj->ClassName().Pos("Edit")>0) nodNew->NodeValue=EncodeString(GetPropValue(FMXObj,"Text",true)); if (GetPropertyList(FMXObj,false)->IndexOf("ItemIndex")>0 && FMXObj->ClassName().Pos("Combo")>0) nodNew->NodeValue=GetPropValue(forma->Components[i],"ItemIndex",true); if (GetPropertyList(FMXObj,false)->IndexOf("IsChecked")>0 && (FMXObj->ClassName().Pos("Check")>0 || FMXObj->ClassName().Pos("Radio")>0 || FMXObj->ClassName().Pos("Switch")>0) )nodNew->NodeValue=GetPropValue(FMXObj,"IsChecked",true); if (GetPropertyList(FMXObj,false)->IndexOf("Date")>0 && (FMXObj->ClassName().Pos("Calendar")>0 || FMXObj->ClassName().Pos("Calendar")>0)) nodNew->NodeValue=GetPropValue(FMXObj,"Date",true); if (GetPropertyList(FMXObj,false)->IndexOf("Time")>0 && FMXObj->ClassName().Pos("Time")>0) nodNew->NodeValue=GetPropValue(FMXObj,"Time",true); if (GetPropertyList(FMXObj,false)->IndexOf("Value")>0 ) nodNew->NodeValue=GetPropValue(FMXObj,"Value",true); } } xmlDoc->SaveToFile(SavePathXML); }__finally { xmlDoc->Free(); } } //--------------------------------------------------------------------------- void TSaveStateHelper::LoadFormStateXML(TForm *forma) { if (FileExists(SavePathXML)) { xmlDoc =new TXMLDocument(Application); try { xmlDoc->Active = true; xmlDoc->Encoding = "UTF-8"; xmlDoc->Options = xmlDoc->Options << doNodeAutoIndent; xmlDoc->LoadFromFile(SavePathXML); _di_IXMLNode formaNode=xmlDoc->DocumentElement->ChildNodes->FindNode(forma->Name); if(formaNode) { for (int i = 0; i < forma->ComponentCount; i++) { if (dynamic_cast (forma->Components[i])) { FMXObj=dynamic_cast (forma->Components[i]); _di_IXMLNode nodNew = formaNode->ChildNodes->FindNode(FMXObj->Name); if (nodNew ) { if (nodNew->Text!="") { if (GetPropertyList(FMXObj,false)->IndexOf("Text")>0 && FMXObj->ClassName().Pos("Edit")>0) SetPropValue(FMXObj,"Text",DecodeString(nodNew->Text)); if (GetPropertyList(FMXObj,false)->IndexOf("ItemIndex")>0 && FMXObj->ClassName().Pos("Combo")>0)SetPropValue(FMXObj,"ItemIndex",nodNew->Text); if (GetPropertyList(FMXObj,false)->IndexOf("IsChecked")>0 && (FMXObj->ClassName().Pos("Check")>0 || FMXObj->ClassName().Pos("Radio")>0 || FMXObj->ClassName().Pos("Switch")>0) ) SetPropValue(FMXObj,"IsChecked",nodNew->Text); if (GetPropertyList(FMXObj,false)->IndexOf("Date")>0 && (FMXObj->ClassName().Pos("Calendar")>0 || FMXObj->ClassName().Pos("Calendar")>0)) SetPropValue(FMXObj,"Date",nodNew->Text); if (GetPropertyList(FMXObj,false)->IndexOf("Time")>0 && FMXObj->ClassName().Pos("Time")>0) SetPropValue(FMXObj,"Time",nodNew->Text); if (GetPropertyList(FMXObj,false)->IndexOf("Value")>0 ) SetPropValue(FMXObj,"Value",nodNew->Text); } } } } } } __finally {xmlDoc->Free();} } }
Вызов
// --------------------------------------------------------------------------- void __fastcall TfrmMain::SaveXMLButtonClick(TObject *Sender) { TSaveStateHelper *st; st->LoadFormStateXML(frmMain); } // --------------------------------------------------------------------------- void __fastcall TfrmMain::LoadXMLButtonClick(TObject *Sender) { TSaveStateHelper *st; st->SaveFormStateXML(frmMain); } // --------------------------------------------------------------------------- void __fastcall TfrmMain::SaveJSONButtonClick(TObject *Sender) { TSaveStateHelper *st; st->LoadFormStateJSON(frmMain); } // --------------------------------------------------------------------------- void __fastcall TfrmMain::LoadXMLButtonJSON(TObject *Sender) { TSaveStateHelper *st; st->SaveFormStateJSON(frmMain); }Как то так, по идее должно работать на всех платформах
Комментариев нет:
Отправить комментарий