読者です 読者をやめる 読者になる 読者になる

Haruyuki Mohri

毛利春幸のブログです。

Using The FireMonkey Save State(OnSaveState) , TFileStream and TBinaryReader, TBinaryWriter

The FireMonkey TForm OnSaveState events is implemented.

http://docwiki.embarcadero.com/RADStudio/Berlin/en/FireMonkey_Save_State
OnSaveState is a TForm of events. OnSaveState is very useful in mobile.
It is, because generated at the time of the background switching.

Useful this event even Windows.
f:id:mojeld:20160905110441j:plain

Use the OnSaveState, save the form content at the time of occurrence.

I used the TBinaryWriter and TFileStream.
Arranging two of TEdit to The Form.
f:id:mojeld:20160905112724j:plain

#include <memory>

void __fastcall TForm1::FormSaveState(TObject *Sender)
{
    std::unique_ptr<TFileStream> fs{std::make_unique<TFileStream>(FSaveFileName, fmOpenReadWrite + fmCreate)};
    std::unique_ptr<TBinaryWriter> bw{std::make_unique<TBinaryWriter>(fs.get(), TEncoding::Unicode, False)};
    try
    {
        for (int i = 0; i < this->ComponentCount; i++)
            bw->Write((static_cast<TEdit* >(this->Components[i]) )->Text);
    }
    catch(Exception& e)
    {
        ShowMessage(e.Message);
    }
}

This saved in the "FSaveFileName".
Location here....

#include <System.IOUtils.hpp>

#if defined(_PLAT_MSWINDOWS)
    FSaveFileName = ChangeFileExt(ParamStr(0), ".bin");
#else
    using tpath_ = System::Ioutils::TPath;
    FSaveFileName = tpath_::GetDocumentsPath() + tpath_::DirectorySeparatorChar + L"save.bin";
#endif

Create the "SaveFile" read method.

void __fastcall TForm1::LoadBinaly()
{
    std::unique_ptr<TFileStream> fs{std::make_unique<TFileStream>(FSaveFileName, fmOpenRead)};
    std::unique_ptr<TBinaryReader> br{std::make_unique<TBinaryReader>(fs.get(), TEncoding::Unicode, false)};
    try
    {
        for (int i = 0; i < this->ComponentCount; i++)
            (static_cast<TEdit* >(this->Components[i]) )->Text = br->ReadString();
    }
    catch(Exception* e)
    {
        ShowMessage(e->Message);
    }
}

I uses the C++11. "unique_ptr" and "using" etc..

Using FireMonkey SaveState in C++Builder - YouTube

Berlin C++11 lambdaでstd::function<>とTFunc<>両方使う方法

std::function<>とTFunc<>両方を同じ関数でセットできるようにする。

std::function<>用

#include <functional>
template<typename T, bool=true >
int __fastcall func2(T fn1, int i1, int i2)
{
    return fn1(i1, i2);
}

TFunc<>用

template<typename T, bool=false>
int __fastcall func2(_di_TFunc__3<int, int, int > fn1, int i1, int i2)
{
    return (*fn1).Invoke(i1, i2);
}

共通で呼ぶ関数

#include <type_traits>
template<typename T>
unsigned int __fastcall TForm1::func1(T fn1)//std::function<>とTFunc__3<>両方対応させる
{
    int result_{0};
    for (int i = 0; i < 10; i++)
    {
        result_ = func2<T,  std::is_same<T, std::function<int(int, int)> >::value>(fn1, i, result_);
    }
    return  static_cast<unsigned int>(result_);
}

呼び方

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    Memo1->Clear();
    ///std::function<>を使って実行
    unsigned int i3{func1<std::function<int(int, int)> >([](int i1, int i2)->int
    {
        return i1 + i2;
    })};

    ///TFunc__3<>を使って実行
    unsigned int i4{func1<_di_TFunc__3<int, int, int > >([](int i1, int i2)->int
    {
        return i1 + i2+ i2;//上とは若干違う内容
    })};
    OutputDebugString(Format(L"%d, %d", ARRAYOFCONST((i3, i4)) ).c_str() );
    Memo1->Lines->Append(Format(L"std::function<int(int, int)> = %d", ARRAYOFCONST((i3))));
    Memo1->Lines->Append(Format(L"TFunc__3<int, int, int > = %d", ARRAYOFCONST((i4))));

}

同じ関数名で型を変えるとそれぞれに対応した関数に飛んでく。

f:id:mojeld:20160819195533j:plain

gist.github.com

Let template of TNotifyEvent<TObject* >

TNotifyEvent is without the need for templates.

Because the event template unaware.

typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender);

OK remain now.

Making a template with TNotifyEvent

TNotifyEvent is set to TNotifyEvent1(New Name)

template <class T>
using TNotifyEvent1 = void __fastcall (__closure *)(T Sender);

こんな事が可能になる

TNotifyEvent1<TComponent* > FOnEvent;
void __fastcall TForm1::thread_event(TComponent* Sender)
{
    ....
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    FOnEvent = thread_event;
}

実装部メソッドもtemplateできると嬉しいのですが。。。

f:id:mojeld:20160727135609g:plain

10.1 Berlin WebBroker 文字列をSJISにする

10.1 Berlin WebBroker TWebResponse

いつからなのかWebBrokerのTWebResponse.Contentを返すとUTF8になっている。

Response.Content  := '文字列'

SJISで返す簡単な方法

昔からのインターフェイスSJISを返したい場合

{Delphiの場合}
  Response.ContentStream  := TStringStream.Create('SJIS文字列', TEncoding.ANSI);
//C++Builderの場合
void __fastcall TWebModule1::WebModule1DefaultHandlerAction(TObject *Sender, TWebRequest *Request,
          TWebResponse *Response, bool &Handled)
{
    Response->ContentStream = new TStringStream("<html>"
    "<head><title>Web Server Application</title></head>"
    "<body>SJIS日本語</body>"
    "</html>", TEncoding::ANSI, False);
}

f:id:mojeld:20160619215608g:plain

TJSONObject::ParseJSONValue()で文字列からTJSONArrayにする

TJSONObject::ParseJSONValue()

文字列をTJSONObjectなどに変換してくれる。
TJSONArrayにも変換可能。

JSONファイル

//こんなJSONがあったとして
UnicodeString us = L"[{\"Key\":\"00\",\"n\":\"会社名\"},{\"Key\":\"01\",\"n\":\"ABC社\"}]";

Delphiの場合

uses System.JSON;
var
  ja: TJSONArray;
  s: String;
begin
  ja := TJSONObject.ParseJSONValue(us) as TJSONArray;
  s := ja.Items[0].GetValue<TJSONValue>('n').Value; {こんな感じで文字を取れる}
end;

C++Builderの場合

#include <System.JSON.hpp>
#include <memory>
std::shared_ptr<TJSONArray> __fastcall TForm1::StrToJson(const UnicodeString stValue)
{
    std::shared_ptr<TJSONArray> ja((static_cast<TJSONArray*>(TJSONObject::ParseJSONValue(stValue))));

    //ここで別名つけてみる
    TJSONObject* jo1 = (static_cast<TJSONObject* >(ja->Get(0) ) );
    String stValue1 = jo1->GetValue("n")->Value() ;

    //これでもいい
    String stValue2 = (static_cast<TJSONObject* >(ja->Get(0) ) ) ->GetValue("n")->Value() ;

    return ja;
}

f:id:mojeld:20160617103731j:plain