前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

9.22. 最適化

一般に、同じ機能をプログラミングする方法はひとつ以上あり、 各々の方法によってコードの処理速度や保守性は大きく異なるものです。

この節では、 SophiaFramework UNIVERSE におけるコードの最適化について解説します。

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

コントロールやダイアログで使用するテキストや画像などの各種データをリソースファイルに保存しておくと、 多言語サポートを提供しやすくなります。

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

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

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.154. 最適化されたコード

SFZTextButtonControlSmp button;
SFCError error(SFERR_NO_ERROR);

// ...(省略)...

// 直接リソースファイルからテキストを読み込みテキストボタンコントロールに設定する
// このままでエラー処理は十分
error = button->SetText("usrapplication.bar", 128);

// ...(省略)...

直接リソースファイルから画像を読み込みレスポンダに設定する方法も上記と同様です。

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

個々の状態を設定するための関数として SFYResponder::SetStateVisible 関数や SFYResponder::SetStateFocus 関数などがあります。 しかし、すべての状態を一度にまとめて設定する場合は、 SFYResponder::SetState 関数を利用することが推奨されます。

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

SFZTextButtonControlSmp button;

// ...(省略)...

// ボタンコントロールの可視状態を "true" に設定する
button->SetStateVisible(true);

// ボタンコントロールの活性状態を "true" に設定する
button->SetStateActive(true);

// ボタンコントロールの操作可能状態を "true" に設定する
button->SetStateEnable(true);

// ボタンコントロールのフォーカス状態を "true" に設定する
button->SetStateFocus(true);

// ...(省略)...

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

SFZTextButtonControlSmp button;

// ...(省略)...

// ボタンコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
button->SetState(true, true, true, true);

// ...(省略)...

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

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

SophiaFramework UNIVERSE の描画エンジンのアルゴリズムにより、 ウィンドウ内にコントロールなどの子レスポンダがたくさん配置されていればいるほどその効果は増大します。

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

SFZWindowSmp window_a;
SFZWindowSmp window_b;

// ...(省略)...

// 初期設定を行う
// window_a, window_b の領域は親レスポンダと同じ
window_a->SetRealBound(GetLocalBound());
window_b->SetRealBound(GetLocalBound());
// window_a, window_b の状態を「可視+活性+操作可能+非フォーカス」にまとめて設定する
window_a->SetState(true, true, true, false);
window_b->SetState(true, true, true, false); // window_b は可視状態
// window_a を最前面とする
window_a->ToFront(); // window_b は可視状態のまま

// 次に、window_b を最前面に移動させる

window_b->ToFront(); // window_a は可視状態のまま
// ...(省略)...

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

SFZWindowSmp window_a;
SFZWindowSmp window_b;

// ...(省略)...

// 初期設定を行う
// window_a, window_b の領域は親レスポンダと同じ
window_a->SetRealBound(GetLocalBound());
window_b->SetRealBound(GetLocalBound());
// window_a の状態を「可視+活性+操作可能+非フォーカス」にまとめて設定する
window_a->SetState(true, true, true, false);
// window_b の状態を「不可視+活性+操作可能+非フォーカス」にまとめて設定する
window_b->SetState(false, true, true, false); // window_b は不可視状態
// window_a を最前面とする
window_a->ToFront(); // window_b は不可視状態

// 次に、window_b を最前面に移動させる
// window_a を不可視状態にする
window_a->SetStateVisible(false);
// window_b を最前面に移動させる
window_b->ToFront(); // window_a は不可視状態
// window_b を可視状態にする
window_b->SetStateVisible(true);

// ...(省略)...

9.22.4. 複数の配信規則をトレーサに一括登録する

通常、配信規則は 1 つずつトレーサに登録しますが、 以下のように配列を用いて複数の配信規則をトレーサに一括登録する効率の良い方法もあります。

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

SFCError error(SFERR_NO_ERROR);

// SFEVT_APP_RESUME イベントに関する配信規則をトレーサに登録する
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) {

    // SFEVT_APP_SUSPEND イベントに関する配信規則をトレーサに登録する
    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) {

        // SFEVT_KEY イベントに関する配信規則をトレーサに登録する
        error = RegisterTracer(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            SFYTracer::ORDER_FORWARD, SFYTracer::STATE_ALL, false
        );
    }
}

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

// SFEVT_APP_RESUME / SFEVT_APP_SUSPEND / SFEVT_KEY イベントの配列
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}
};

// SFEVT_APP_RESUME / SFEVT_APP_SUSPEND / SFEVT_KEY イベントに対応する配信規則の配列
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);

// 配列を用いて SFEVT_APP_RESUME / SFEVT_APP_SUSPEND / SFEVT_KEY イベントに関する配信規則をトレーサに一括登録する
error = RegisterTracer(atomic_cast(range), rule, lengthof(range));

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

通常、ハンドラは 1 つずつレスポンダに登録しますが、 以下のように配列を用いて複数のハンドラをレスポンダに一括登録する効率の良い方法もあります。

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

SFCError error(SFERR_NO_ERROR);

// SFEVT_APP_RESUME イベントに関するハンドラをレスポンダに登録する
error = RegisterHandler(
    SFXEventRange(SFEVT_APP_RESUME, SFEVT_APP_RESUME, SFP16_BEGIN, SFP16_END),
    XANDLER_INTERNAL(OnAppResume)
);
if (error == SFERR_NO_ERROR) {

    // SFEVT_APP_SUSPEND イベントに関するハンドラをレスポンダに登録する
    error = RegisterHandler(
        SFXEventRange(SFEVT_APP_SUSPEND, SFEVT_APP_SUSPEND, SFP16_BEGIN, SFP16_END),
        XANDLER_INTERNAL(OnAppSuspend)
    );
    if (error == SFERR_NO_ERROR) {

        // SFEVT_KEY イベントに関するハンドラをレスポンダに登録する
        error = RegisterHandler(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            XANDLER_INTERNAL(OnKey)
        );
    }
}

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

// SFEVT_APP_RESUME / SFEVT_APP_SUSPEND / SFEVT_KEY イベントの配列
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}
};

// SFEVT_APP_RESUME / SFEVT_SUSPEND / SFEVT_KEY イベントに対応するハンドラの配列
SFYHandler::RuleRec rule[lengthof(range)];

SFCError error(SFERR_NO_ERROR);

rule[0].spp = XANDLER_FUNCTION(OnAppResume);  // SFEVT_APP_RESUME イベントのハンドラ
rule[0].reference = this;
rule[1].spp = XANDLER_FUNCTION(OnAppSuspend); // SFEVT_APP_SUSPEND イベントのハンドラ
rule[1].reference = this;
rule[2].spp = XANDLER_FUNCTION(OnKey);        // SFEVT_KEY イベントのハンドラ
rule[2].reference = this;

// 配列を用いて SFEVT_APP_RESUME / SFEVT_APP_SUSPEND / SFEVT_KEY イベントのハンドラをレスポンダに一括登録する
error = RegisterHandler(atomic_cast(range), rule, lengthof(range));