前のページ次のページ上に戻るホーム BREW C++ ライブラリ & GUI フレームワーク & XML ミドルウェア : SophiaFramework UNIVERSE 5.0

9.18. 最適化

同じ動作をするコードでも何通りかの記述方法があり、時と場合によっては動作速度が大きく異なったり、保守性に影響をあたえることがあります。

ここでは、既に動作しているコードをより最適化されたコードに変更するための方法について解説します。

9.18.1. リソースファイルから読み込む

コントロールやダイアログで使用する各種テキストデータやイメージ データは、リソースファイルとして保持しておくと他言語への対応が容易になります。

リソースファイルにあるデータを SFBShell::LoadResString 関数や SFBShell::LoadResImage 関数を利用して読み込みレスポンダに設定する方法もありますが、コントロールやダイアログなどの多くはリソースファイルからの自動的な読み込みをサポートしています。

例 9.137. 最適化されていないコード

SFZTextButtonControlSmp button;
SFBShellSmp shell;
SFXWideString string;
SFCError error(SFERR_NO_ERROR);

...
// テキストデータを直接コード中に記述すると
// 多言語対応時に手間がかかる
error = button->SetText("OK");

// リソースファイルからテキストデータを読み込むように変更したが
// エラー処理が不十分
error = button->SetText(SFBShell::GetInstance()->LoadResString("usrapplication.bar", 128));

// エラー処理を十分に行うとコード量が多くなり実装に手間がかかる
if ((shell = SFBShell::GetInstance()) != null) {
    error = string.Set(shell->LoadResString("usrapplication.bar", 128));
    if (error == SFERR_NO_ERROR) {
        error = button->SetText(string);
    }
}
else {
    error = SFERR_FAILED;
}
...

例 9.138. 最適化されたコード

SFZTextButtonControlSmp button;
SFCError error(SFERR_NO_ERROR);

...
// リソースファイルからテキストデータを読み込み、
// 十分なエラー処理を行うには以下のように記述する
error = button->SetText("usrapplication.bar", 128);
...

イメージ データの読み込みに対してもほとんど同じ方法を使えます。

9.18.2. 状態設定関数を使い分ける

各種状態を設定するには SFYResponder::SetStateVisible 関数や SFYResponder::SetStateFocus 関数などがありますが、複数の状態をまとめて設定する場合は各状態を個別に設定するのではなく SFYResponder::SetState 関数を利用します。

例 9.139. 最適化されていないコード

SFZTextButtonControlSmp button;

...
button->SetStateVisible(true);
button->SetStateActive(true);
button->SetStateEnable(true);
button->SetStateFocus(true);
...

例 9.140. 最適化されたコード

SFZTextButtonControlSmp button;

...
button->SetState(true, true, true, true);
...

9.18.3. 背後のレスポンダを不可視に設定する

複数のウィンドウなどを用いて画面遷移を行う場合、背後に移動されて見えないウィンドウを明示的に不可視に設定すると描画速度が向上します。

描画エンジンのアルゴリズム上、ウィンドウが多くの子レスポンダ(コントロールなど)を包含していればいるほど効果が増大します。

例 9.141. 最適化されていないコード

SFZWindowSmp window_a;
SFZWindowSmp window_b;

...
// 初期状態を設定する
// window_a, window_b はともに大きさが画面サイズと
// 同じであり、window_a を最前面とする
window_a->SetRealBound(GetLocalBound());
window_b->SetRealBound(GetLocalBound());
window_a->SetState(true, true, true, false);
window_b->SetState(true, true, true, false);
window_a->ToFront();

// 次に、window_b を最前面に移動させる
window_b->ToFront();
...

例 9.142. 最適化されたコード

SFZWindowSmp window_a;
SFZWindowSmp window_b;

...
// 初期状態を設定する
// window_a, window_b はともに大きさが画面サイズと
// 同じであり、window_a を最前面とする
window_a->SetRealBound(GetLocalBound());
window_b->SetRealBound(GetLocalBound());
window_a->SetState(true, true, true, false);
window_b->SetState(false, true, true, false);
window_a->ToFront();

// 次に、window_b を最前面に移動させる
window_a->SetStateVisible(false);
window_b->ToFront();
window_b->SetStateVisible(true);
...

9.18.4. 複数のトレーサを一括登録する

1つのレスポンダに複数のトレーサを登録するにはトレーサを1つずつ登録する方法もありますが、一括して登録する方が処理速度が速くなります。

トレーサを一括して登録するには、トレーサ規則の配列を作成します。

例 9.143. 最適化されていないコード

SFCError error(SFERR_NO_ERROR);

error = RegisterTracer(
    SFXEventRange(SFEVT_APP_RESUME, SFEVT_APP_RESUME, SFP16_BEGIN, SFP16_END),
    SFYTracer::ORDER_BACKWARD, SFYTracer::STATE_NONE, true
);
if (error == SFERR_NO_ERROR) {
    error = RegisterTracer(
        SFXEventRange(SFEVT_APP_SUSPEND, SFEVT_APP_SUSPEND, SFP16_BEGIN, SFP16_END),
        SFYTracer::ORDER_FORWARD, SFYTracer::STATE_NONE, true
    );
    if (error == SFERR_NO_ERROR) {
        error = RegisterTracer(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            SFYTracer::ORDER_FORWARD, SFYTracer::STATE_ALL, false
        );
    }
}

例 9.144. 最適化されたコード

static SFXEventRange::AtomRecConst range[] = {
    {         SFEVT_APP_RESUME,      SFEVT_APP_RESUME, SFP16_BEGIN, SFP16_END},
    {        SFEVT_APP_SUSPEND,     SFEVT_APP_SUSPEND, SFP16_BEGIN, SFP16_END},
    {                SFEVT_KEY,             SFEVT_KEY, SFP16_BEGIN, SFP16_END}
};
static SFYTracer::RuleRecConst rule[lengthof(range)] = {
    {SFYTracer::ORDER_BACKWARD, SFYTracer::STATE_NONE,       true},
    { SFYTracer::ORDER_FORWARD, SFYTracer::STATE_NONE,       true},
    { SFYTracer::ORDER_FORWARD,  SFYTracer::STATE_ALL,      false}
};
SFCError error(SFERR_NO_ERROR);

error = RegisterTracer(atomic_cast(range), rule, lengthof(range));

9.18.5. 複数のハンドラを一括登録する

1つのレスポンダに複数のハンドラを登録するにはハンドラを1つずつ登録する方法もありますが、一括して登録する方が処理速度が速くなります。

ハンドラを一括して登録するには、ハンドラ規則の配列を作成します。

例 9.145. 最適化されていないコード

SFCError error(SFERR_NO_ERROR);

error = RegisterHandler(
    SFXEventRange(SFEVT_APP_RESUME, SFEVT_APP_RESUME, SFP16_BEGIN, SFP16_END),
    XANDLER_INTERNAL(OnAppResume)
);
if (error == SFERR_NO_ERROR) {
    error = RegisterHandler(
        SFXEventRange(SFEVT_APP_SUSPEND, SFEVT_APP_SUSPEND, SFP16_BEGIN, SFP16_END),
        XANDLER_INTERNAL(OnAppSuspend)
    );
    if (error == SFERR_NO_ERROR) {
        error = RegisterHandler(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            XANDLER_INTERNAL(OnKey)
        );
    }
}

例 9.146. 最適化されたコード

static SFXEventRange::AtomRecConst range[] = {
    { SFEVT_APP_RESUME,  SFEVT_APP_RESUME, SFP16_BEGIN, SFP16_END},
    {SFEVT_APP_SUSPEND, SFEVT_APP_SUSPEND, SFP16_BEGIN, SFP16_END},
    {        SFEVT_KEY,         SFEVT_KEY, SFP16_BEGIN, SFP16_END}
};
SFYHandler::RuleRec rule[lengthof(range)];
SFCError error(SFERR_NO_ERROR);

rule[0].spp = XANDLER_FUNCTION(OnAppResume);
rule[0].reference = this;
rule[1].spp = XANDLER_FUNCTION(OnAppSuspend);
rule[1].reference = this;
rule[2].spp = XANDLER_FUNCTION(OnKey);
rule[2].reference = this;
error = RegisterHandler(atomic_cast(range), rule, lengthof(range));