SophiaFramework UNIVERSE 5.3 |
SFY アプリでは、 BREW 環境から受信したイベント(以下、BREW イベント)は最初にレスポンダに配信されます。
注意 | |
---|---|
厳密に言えば、BREW イベントは最初に アプリケーションクラス(SFYApplication を継承するクラス)が内部に保持する ルートに渡されます。 その後、トレーサの配信規則により、 ルートを頂点とするレスポンダツリー上の各レスポンダに配信されます。 |
アプリが受信した BREW イベントをレスポンダよりも優先して先に渡す関数のことを 優先的イベントハンドラと呼びます。 このイベントハンドラは、SFXEventBypass::Register 関数を使用して BREW アプリ 1 つにつき 1 つまで登録可能です。
優先的イベントハンドラを登録すると、 BREW イベントは『優先的イベントハンドラ→レスポンダ』の順に配信されるようになります。 SFXEventBypass::Unregister 関数を呼び出してコールバックの登録が解除されるまでの間、 BREW イベントはこの順序で配信されます。
UI を表示する BREW インターフェースでは、 アプリが UI 表示中に受信した BREW イベントは最初に BREW インターフェースの HandleEvent 関数に渡す必要があります。
この処理は、 優先的イベントハンドラ内で、 アプリが受け取った BREW イベントを BREW インターフェースの HandleEvent 関数に渡すことで実現できます。
UI 表示終了時は、 その時に起動されるコールバック内で SFXEventBypass::Unregister 関数を使用して 優先的イベントハンドラの登録を解除します。
その後、SFCApplication::RenderDeviceScreen 関数を呼び出して UI 表示により変更された画面を再描画してアプリの画面を復元します (この再描画は、UI 表示終了時に起動されるコールバック内で行うこともあります)。
優先的イベントハンドラについて | |
---|---|
SFXEventBypass クラスの解説を参照してください。 |
BREW インターフェースの UI 表示終了時の処理について | |
---|---|
優先的イベントハンドラの登録を解除すると BREW イベントは最初にレスポンダに配信される設定に戻ります。 UI 処理の結果、再描画後の画面が UI 表示前と異なる場合もあります(例: FEP からテキストを入力したとき)。 再描画は、SFCApplication::RenderDeviceScreen 関数を呼び出して行います。 |
BREW イベントの処理について | |
---|---|
優先的イベントハンドラに関わる BREW イベントの処理については、 SFY アプリの全体的な処理の流れの イベントループを参照してください。 |
注意 | |
---|---|
BREW API ITextCtl インターフェースでは、 UI 表示終了時に呼び出されるコールバックを登録できません。 この場合は、UI 表示終了時に EVT_COMMAND イベントを受信したときに優先的イベントハンドラの登録を解除し、 SFCApplication::RenderDeviceScreen 関数を呼び出して全画面 (デバイス画面とルート以下のレスポンダツリー)を再描画します。 詳細は、 「SophiaFramework UNIVERSE での実装例: ITextCtl / IMenuCtl インターフェース」 を参照してください |
以下では、 ISampleDialog というインターフェース(C++ ラッパークラス名: SFBSampleDialog)が存在したと仮定して解説します。
class SFBSampleDialog : public SFBBase { SFMSEALWRAPPER(SFBSampleDialog) SFMWRAPPERINSTANTIATEONE(SFBSampleDialog, SFBBase) public: static SFBSampleDialogSmp NewInstance (SFCErrorPtr exception = null); static SFBSampleDialogSmp NewInstance (AEECLSID id, SFCErrorPtr exception = null); Bool HandleEvent (AEEEvent evt, UInt16 wp, UInt32 dwp); SFCError StartDialog (UInt32 dialog_type, PFNDLGCB notify, VoidPtr user); }; // notify 引数に指定するダイアログ終了時に呼び出されるコールバックの型 Typedef SIntN(* PFNDLGCB)(VoidPtr reference, SIntN error); // dialog_type 引数に指定するダイアログの種類 #define DIALOG_A 0 #define DIALOG_B 1 #define DIALOG_C 2
SFY アプリ内で SFBSampleDialog クラスを使用するには、 SFBSampleDialog::StartDialog 関数を実行してダイアログを表示した後はダイアログを終了するまでの間、 BREW イベントはレスポンダよりも先に SFBSampleDialog::HandleEvent 関数に渡す必要があります。
これを実現するために、 以下の SophiaDialog クラスを定義、実装します。
class SophiaDialog { SFMSEALCOPY(SophiaDialog) public: typedef SFCError (*CallbackSPP) (SFCError error, VoidPtr reference); SFMTYPEDEFTYPE(CallbackSPP) private: SFBSampleDialogSmp _dialog; CallbackSPP _callback; VoidPtr _reference; public: explicit SophiaDialog (Void); virtual ~SophiaDialog (Void); SFBSampleDialogSmpConstRef GetSFBSampleDialog (Void) const; SFCError StartDialog (UInt32 dialog_type, CallbackSPP callback, VoidPtr reference); Void Close (Void); private: static SIntN OnDialogResultSCP (VoidPtr reference, SIntN error); SFCError OnDialogResult (SFCError error); XALLBACK_DECLARE_SFCAPPLICATION(OnDialogEventBypass) }; // コンストラクタ /*public */SFXDialog::SFXDialog(Void) : _callback(null), _reference(null) { }// SFXDialog::SFXDialog // // デストラクタ /*public virtual*/SFXDialog::~SFXDialog(Void) { Close(); }// SFXDialog::~SFXDialog //
SophiaDialog::StartDialog 関数では、 SFXEventBypass::Register 関数を使用して SophiaDialog::OnDialogEventBypass 優先的イベントハンドラを登録してから SFBSampleDialog::StartDialog 関数を呼び出しています。
SophiaDialog::OnDialogEventBypass 優先的イベントハンドラでは、 最初に SFBSampleDialog::HandleEvent 関数に BREW イベントを渡しています。
SFBSampleDialog::StartDialog 関数の第 2 引数に指定している SophiaDialog::OnDialogResultSCP 関数はダイアログ終了時に起動されるコールバックです。
// SophiaDialog::OnDialogEventBypass 優先的イベントハンドラを登録してダイアログを表示する関数 /*public */SFCError SophiaDialog::StartDialog(UInt32 dialog_type, CallbackSPP callback, VoidPtr reference) { SFCError error; if ((_dialog = SFBSampleDialog::NewInstance(&error)) != null) { // SophiaDialog::OnDialogEventBypass 優先的イベントハンドラを登録する if ((error = SFXEventBypass::Register(XALLBACK_INTERNAL(OnDialogEventBypass))) == SFERR_NO_ERROR) { // OnDialogResultSCP 関数の最後に呼び出されるコールバック _callback = callback; _reference = reference; // UI 表示終了時に起動されるコールバックを指定してダイアログを表示する error = _dialog->StartDialog(dialog_type, OnDialogResultSCP, this); } } if (error != SFERR_NO_ERROR) { Close(); } return error; }// SophiaDialog::StartDialog // // SophiaDialog::OnDialogEventBypass 優先的イベントハンドラ: BREW イベントが優先的に通知される関数 /*private */XALLBACK_IMPLEMENT_SFCAPPLICATION(SophiaDialog, OnDialogEventBypass, event) { Bool result(false); // BREW イベントは優先的に SFBSampleDialog::HandleEvent 関数に通知される result = _dialog->HandleEvent(event.GetType(), event.GetP16(), event.GetP32()); switch (event.GetType()) { case SFEVT_APP_RESUME: result = true; break; case SFEVT_APP_STOP: case SFEVT_APP_SUSPEND: Close(); result = true; break; case SFEVT_KEY: case SFEVT_KEY_PRESS: case SFEVT_KEY_RELEASE: #if TARGET_VERSION_LT(3, 0, 0) case SFEVT_KEY_HELD: #endif result = true; break; default: break; } return result; }// XALLBACK_IMPLEMENT_SFCAPPLICATION(SophiaDialog, OnDialogEventBypass) //
SophiaDialog::OnDialogResultSCP 関数では、 SophiaDialog::Close 関数を呼び出して SophiaDialog::OnDialogEventBypass 優先的イベントハンドラの登録を解除します。
また、SophiaDialog::OnDialogResultSCP 関数の最後で呼び出される、 SophiaDialog::StartDialog 関数の引数に指定したコールバック内では、 SFCApplication::RenderDeviceScreen 関数を呼び出して UI 表示により変更された画面を再描画します。
// ダイアログ終了時に呼び出されるコールバック /*private static*/SIntN SophiaDialog::OnDialogResultSCP(VoidPtr reference, SIntN error) { return SophiaDialogPtr(reference)->OnDialogResult(error); }// SophiaDialog::OnDialogResultSCP // /*private */SFCError SophiaDialog::OnDialogResult(SFCError error) { SFCApplicationPtr application; // 優先的イベントハンドラの登録を解除する(ダイアログ表示の終了処理を行う) Close(); if (_callback != null) { // ダイアログ表示終了時に起動されるコールバック // ※SophiaDialog::StartDialog 関数の引数に指定されたコールバックを起動する error = _callback(error, _reference); } // 全画面を再描画する if ((application = SFCApplication::GetInstance()) != null) { application->RenderDeviceScreen(); } return error; }// SophiaDialog::OnDialogResult // // ダイアログ表示の終了処理を行う関数 /*private */Void SophiaDialog::Close(Void) { // SophiaDialog::OnDialogEventBypass 優先的イベントハンドラの登録を解除する SFXEventBypass::Unregister(XALLBACK_INTERNAL(OnDialogEventBypass)); // ダイアログを解放する _dialog.Release(); return; }// SophiaDialog::Close //
以下は、実際に SophiaDialog クラスを利用して ISampleDialog インターフェース(SFBSampleDialog クラス)のダイアログを表示するコードです。
class sampleapp : SFYApplication { SFMSEALCOPY(sampleapp) public: static SFCInvokePtr Factory(Void); private: SophiaDialog _dialog; // SFYApplication 継承するアプリケーションクラスのメンバ変数として定義する private: explicit sampleapp(Void) static_throws; virtual ~sampleapp(Void); private: // ダイアログ終了時に呼び出されるコールバック(エントリ) static SFCError OnDialogResultSCP(VoidPtr reference, SFCError error); // ダイアログ終了時に呼び出されるコールバック(実体) SFCError OnDialogResult(SFCError error); }; // コンストラクタ sampleapp::sampleapp(Void) static_throws { if (static_try()) { // ダイアログ DIALOG_A を表示する static_throw(_dialog->StartDialog(DIALOG_A, OnDialogResultSCP, this); } } // デストラクタ sampleapp::~sampleapp(Void) { } // ダイアログ終了時に呼び出されるコールバック(エントリ) /*private static*/SFCError sampleapp::OnDialogResultSCP(VoidPtr reference, SFCError error) { return sampleappPtr(reference)->OnDialogResult(error); }// sampleapp::OnDialogResultSCP // // ダイアログ終了時に呼び出されるコールバック(実体) /*private */SFCError sampleapp::OnDialogResult(SFCError error) { TRACE("... OnDialogResult: %X", error); return error; }// sampleapp::OnDialogResult//
SFZSingleEditLabelControl など名前に "Edit" を含むレスポンダクラスでは、 以下のようにしてテキスト入力を行います(FEP を制御します)。
注意 | |
---|---|
SFZSingleEditLabelControl クラスのすべての実装コードは、 fep_for_sf2.zip にあります(関連コードも含まれます)。 |
SFXEditor クラスは、 FEP の各種プロパティの設定や、起動と終了の処理をカプセル化したクラスです。
このクラスは、SFYSingleEditWidget / SFYMultipleEditWidget クラスの内部で使用されます。
SFXEditor::Open 関数は、 各種プロパティの設定を行ってから FEP を起動します。
下記の実装コードにあるように、 SFXEventBypass::Register 関数を使用して OnBypass() 優先的イベントハンドラの登録も行います。
OnBypass() 優先的イベントハンドラでは、 アプリが受信した BREW イベントを最初に BREW API ITEXTCTL_HandleEvent 関数に通知する処理や、 FEP 終了時には SFXEditor::Open 関数の引数に指定された コールバックを呼び出す処理などが行われます。
#define ITEM_NAME ("Done") #define LABEL_OK 1 // FEP を起動する。FEP 終了時は、spp / reference 引数に指定されたコールバックが起動される /*public virtual*/SFCError SFXEditor::Open(SFXEditPropertyPtr property, CallbackSPP spp, VoidPtr reference) { SFBDisplaySmp display; SFXWideString string; SFXRectangle remember; SFXRectangle rectangle; UInt32 flag; SFCError error(SFERR_NO_ERROR); if (property != null) { _property = property; if ((display = SFBDisplay::GetInstance()) != null) { // クリッピング領域を退避する display->GetClipRect(&remember); // クリッピング領域を空の矩形にすることにより、ITextCtl インターフェースは画面に描画できなくなる display->SetClipRect(SFXRectangle::EmptyInstance()); // ITextCtl インターフェースのインスタンスを生成する if ((_textctl = SFBTextCtl::NewInstance(GetSFBTextCtlClassID(), &error)) != null) { // IMenuCtl インターフェースのインスタンスを生成する if ((_menuctl = SFBMenuCtl::NewInstance(GetSFBMenuCtlClassID(), &error)) != null) { if ((error = string.Set(ITEM_NAME)) == SFERR_NO_ERROR) { // IMenuCtl インターフェースに項目を追加する // ※FEP 終了時に通知される SFEVT_COMMAND イベントの P16 パラメータは LABEL_OK となる if (_menuctl->AddItem(LABEL_OK, &string, reinterpret_cast<UInt32>(_menuctl.Get()))) { // ITextCtl インターフェースの各種プロパティを設定する // ITextCtl インターフェースに IMenuCtl インターフェースを関連付ける _textctl->SetSoftKeyMenu(_menuctl); // ITextCtl インターフェース自身が描画されない設定を行う flag = TP_NODRAW | TP_FRAME | TP_NOUPDATE | TP_FIXSETRECT; if (_property->GetPasswordMode()) { flag |= TP_PASSWORD; } _textctl->SetProperties(flag); rectangle.Set(SFXGrid::ZeroInstance(), SFXDevice().GetScreenSize()); rectangle.SubBottom(_menuctl->GetRect().GetHeight()); _textctl->SetRect(rectangle); _textctl->SetMaxSize(_property->GetMaximumLength()); _textctl->SetInputMode(_property->GetInputMode()); if (_textctl->SetText(_property->GetText())) { // 優先的イベントハンドラを登録する // ※FEP 起動中、BREW イベントは優先的に SFXEditor::OnBypass 優先的イベントハンドラに通知される if ((error = RegisterBypass(XALLBACK_INTERNAL(OnBypass))) == SFERR_NO_ERROR) { // FEP 終了時に起動されるコールバックを設定する _spp = spp; _reference = reference; } } else { error = SFERR_FAILED; } } else { error = SFERR_FAILED; } } } } if (error != SFERR_NO_ERROR) { Close(); } // クリッピング領域を復元する display->SetClipRect(remember); if (error == SFERR_NO_ERROR) { _textctl->SetActive(true); _textctl->SetCursorPos(TC_CURSORSTART); } } else { error = SFERR_FAILED; } } else { error = SFERR_INVALID_PARAM; } return error; }// SFXEditor::Open // // SFXEditor::OnBypass 優先的イベントハンドラ: BREW イベントが優先的に通知される関数 /*private */XALLBACK_IMPLEMENT_SFCAPPLICATION(SFXEditor, OnBypass, event) { SFXWideString string; SFCError error; Bool result(false); // アプリが受信した BREW イベントを最初に ITEXTCTL_HandleEvent 関数に通知する result = _textctl->HandleEvent(event); switch (event.GetType()) { case SFEVT_APP_RESUME: result = true; break; case SFEVT_APP_SUSPEND: result = true; break; case SFEVT_KEY: case SFEVT_KEY_PRESS: case SFEVT_KEY_RELEASE: result = true; break; case SFEVT_COMMAND: // FEP 終了時、SFEVT_COMMAND イベント(P16 パラメータ="LABEL_OK")が通知される if (!result) { switch (event.GetP16()) { case LABEL_OK: // FEP が終了したとき // FEP にて入力されたテキストを取得する if ((error = string.Set(_textctl->GetTextPtr())) == SFERR_NO_ERROR) { if ((error = _property->SetText(string)) == SFERR_NO_ERROR) { _property->SetInputMode(_textctl->GetInputMode()); } } // FEP を閉じる Close(); if (_spp != null) { // FEP 終了時に起動されるコールバック // ※1. SFXEditor::Open 関数の引数に指定したコールバック // ※2. このコールバックでは FEP から入力されたテキストをレスポンダに反映させる (*_spp)(error, _reference); } // 全画面(デバイス画面とルート以下のレスポンダツリー)を再描画する if ((application = SFCApplication::GetInstance()) != null) { application->RenderDeviceScreen(); } break; default: break; } result = true; } break; default: break; } return result; }// XALLBACK_IMPLEMENT_SFCAPPLICATION(SFXEditor, OnBypass) // // FEP の終了処理 /*public */Void SFXEditor::Close(Void) { if (_textctl != null) { _textctl->SetSoftKeyMenu(SFBMenuCtlSmp::EmptyInstance()); _textctl->SetActive(false); } // SFXEditor::OnBypass 優先的イベントハンドラの登録を解除する UnregisterBypass(XALLBACK_INTERNAL(OnBypass)); // ITextCtl / IMenuCtl インターフェースを解放する _menuctl.Release(); _textctl.Release(); _property = null; return; }// SFXEditor::Close //
SFXBaseEditor::RegisterBypass 関数の内部実装は、以下の通りです (SFXEventBypass::Register 関数を呼び出します)。
// 優先的イベントハンドラを登録する /*protected static*/inline SFCError SFXBaseEditor::RegisterBypass(SFCApplication::CallbackSPP spp, VoidPtr reference) { return SFXEventBypass::Register(spp, reference); }// SFXBaseEditor::RegisterBypass //
SFXBaseEditor::UnregisterBypass 関数の内部実装は、以下の通りです (SFXEventBypass::Unregister 関数を呼び出します)。
// 優先的イベントハンドラの登録を解除する /*protected static*/inline SFCError SFXBaseEditor::UnregisterBypass(SFCApplication::CallbackSPP spp, VoidPtr reference) { SFXEventBypass::Unregister(spp, reference); }// SFXBaseEditor::UnregisterBypass //
SFZSingleEditLabelControl クラスは、 内部で保持する SFYSingleEditWidget クラスの SFYSingleEditWidget::Edit 関数を呼び出すことにより FEP を起動してその結果を取得します
SFYSingleEditWidget::Edit 関数の内部実装は以下の通りです。
// FEP に遷移し、FEP の入力結果を取得する関数 /*public */SFCError SFYSingleEditWidget::Edit(Void) { SFCError error(SFERR_NO_ERROR); if ((error = _property.SetMaximumLength(_maximum)) == SFERR_NO_ERROR) { if ((error = _property.SetText(_text)) == SFERR_NO_ERROR) { // SFXEditor::Open 関数を呼び出して FEP を起動する // ※ SFYSingleEditWidget::OnEditor 関数は FEP 終了時に起動されるコールバック //(このコールバックでは、FEP から入力されたテキストを取得し、SFEVT_RESPONDER_RESULT イベントを自分自身に送信する) error = _editor->Open(&_property, XALLBACK_INTERNAL(OnEditor)); } } return error; }// SFYSingleEditWidget::Edit //
SFYSingleEditWidget::Edit 関数では、 SFXEditor::Open 関数を呼び出して FEP を起動します。 引数に指定している SFYSingleEditWidget::OnEditor 関数は FEP 終了時に呼び出されます。
SFYSingleEditWidget::OnEditor 関数の内部実装は以下の通りです。
class SFYSingleEditWidget : public SFYWidget { SFMSEALRESPONDER(SFYSingleEditWidget) SFMRESPONDERINSTANTIATETWO(SFYSingleEditWidget, SFYWidget, SFYResponder) // ...(省略)... private: SFYSingleTextWidgetSmp _widget; SFXBaseEditorPtr _editor; SFXEditProperty _property; SFXWideString _text; UInt16 _maximum; // ...(省略)... } // FEP 終了時に起動されるコールバック // ※FEP から入力されたテキストを取得し、SFEVT_RESPONDER_RESULT イベントを自分自身に送信する /*private */XALLBACK_IMPLEMENT_SFXEDITOR(SFYSingleEditWidget, OnEditor, context) { SFYResponderSmp root; SFCError error; if ((error = context) == SFERR_NO_ERROR) { // FEP にて入力されたテキストを取得し、内部で保持する SFYSingleTextWidget クラスに設定する if ((error = SetTextMaximumLength(_property.GetText(), _property.GetMaximumLength())) == SFERR_NO_ERROR) { // SFYSingleEditWidget クラスに SFEVT_RESPONDER_RESULT イベントを送信する InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, 0), false); } } if (error != SFERR_NO_ERROR) { // SFYSingleEditWidget クラスに SFEVT_RESPONDER_RESULT イベントを送信する InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, error), false); } return; }// XALLBACK_IMPLEMENT_SFXEDITOR(SFYSingleEditWidget, OnEditor) //
SFXEditor::OnBypass 関数内で FEP 終了時に呼び出す SFCApplication::RenderDeviceScreen 関数の処理により、 全画面(デバイス画面とルート以下のレスポンダツリー)の再描画が行われます (この再描画では、FEP から入力されたテキストの情報も反映されます)。
SFYSingleEditWidget::SetTextMaximumLength 関数では、 FEP にて取得したテキストを SFYSingleEditWidget::Edit クラスが内部に保持する SFYSingleTextWidget クラスに設定しています。
/*private */SFCError SFYSingleEditWidget::SetTextMaximumLength(SFXWideStringConstRef text, UInt16 maximum) { SFXWideString string; SFXWideString temp; SFCError error(SFERR_NO_ERROR); if (!text.Equals(_text) || maximum != _maximum) { if ((error = string.Set(text.Substring(0, maximum))) == SFERR_NO_ERROR) { if (!string.Equals(_text)) { if ((error = temp.Set(_text)) == SFERR_NO_ERROR) { if ((error = _text.Set(string)) == SFERR_NO_ERROR) { // テキストを内部で保持する SFYSingleTextWidget クラスに設定する if ((error = SetWidgetText(_text, _property.GetPasswordMode())) == SFERR_NO_ERROR) { _maximum = maximum; Invalidate(); InvokeBackward(SFXEvent(SFEVT_RESPONDER_STYLE, SFP16_STYLE_TEXT, 0), true); } else if (temp.IsEmpty()) { _text.Clear(); } else if (_text.Attach(&temp) != SFERR_NO_ERROR) { _text.Clear(); Invalidate(); InvokeBackward(SFXEvent(SFEVT_RESPONDER_STYLE, SFP16_STYLE_TEXT, 0), true); } } } } else if (maximum != _maximum) { _maximum = maximum; Invalidate(); } } } return error; }// SFYSingleEditWidget::SetTextMaximumLength // /*private */SFCError SFYSingleEditWidget::SetWidgetText(SFXWideStringConstRef text, Bool password) { SFXWideString string; SFCError error(SFERR_NO_ERROR); if (password) { if ((error = string.Set(text)) == SFERR_NO_ERROR) { error = SFXShiftJIS::ToPassword(&string); if (error == SFERR_NO_ERROR) { // テキストを内部で保持する SFYSingleTextWidget クラスに設定する error = _widget->SetText(string); } } } else { error = _widget->SetText(text); } return error; }// SFYSingleEditWidget::SetWidgetText //
注意 | |
---|---|
FEP から入力されたテキストは、 最終的に SFYSingleTextWidget クラスのプロパティとなり、 このクラスにより描画されます。 |
SFZSingleEditLabelControl クラスは、 内部に SFYSingleEditWidget クラスを保持しています。
SFZSingleEditLabelControl クラスでは、 コンストラクタ内で SFYSingleEditWidget クラスが SFEVT_RESPONDER_RESULT イベントを受信した場合、 SFZSingleEditLabelControl::OnWidgetResult 関数を起動し、 SFZSingleEditLabelControl クラスに SFEVT_RESPONDER_RESULT イベントを送信する処理を行います。
class SFZSingleEditLabelControl : public SFYLabelControl { SFMSEALRESPONDER(SFZSingleEditLabelControl) SFMRESPONDERINSTANTIATEFOUR(SFZSingleEditLabelControl, SFYLabelControl, SFYControl, SFYWidget, SFYResponder) // ...(省略)... private: SFYSingleEditWidgetSmp _widget; // ...(省略)... } /*protected */SFZSingleEditLabelControl::SFZSingleEditLabelControl(Void) static_throws { static SFXEventRange::AtomRecConst trange[] = { { SFEVT_RESPONDER_STATE, SFEVT_RESPONDER_STATE, SFP16_STATE_FOCUS, SFP16_STATE_FOCUS} }; static SFXEventRange::AtomRecConst crange[] = { { SFEVT_RESPONDER_STYLE, SFEVT_RESPONDER_STYLE, SFP16_BEGIN, SFP16_END}, {SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END} }; SFYHandler::RuleRec trule[lengthof(trange)]; SFYHandler::RuleRec crule[lengthof(crange)]; SFCError error; if (static_try()) { SetType(CODE_TYPE); trule[0].spp = XANDLER_FUNCTION(OnStateFocus); trule[0].reference = this; static_throw(RegisterHandler(atomic_cast(trange), trule, lengthof(trange))); if (static_try()) { if ((_widget = SFYSingleEditWidget::NewInstance(&error)) != null) { // SFEVT_RESPONDER_STYLE イベントのハンドラ crule[0].spp = XANDLER_FUNCTION(OnWidgetStyle); crule[0].reference = this; // SFEVT_RESPONDER_RESULT イベントのハンドラ crule[1].spp = XANDLER_FUNCTION(OnWidgetResult); crule[1].reference = this; // SFYSingleEditWidget クラスへのイベントハンドラの登録 static_throw(_widget->RegisterHandler(atomic_cast(crange), crule, lengthof(crange))); if (static_try()) { static_throw(_widget->SetParent(GetThis())); if (static_try()) { SetPropertyTransparent(true); _widget->SetState(true, true, false, false); Relocate(); } } } else { static_throw(error); } } } }// SFZSingleEditLabelControl::SFZSingleEditLabelControl // // SFYSingleEditWidget クラスが SFEVT_RESPONDER_RESULT イベントを受信したときに呼び出されるハンドラ /*private */XANDLER_IMPLEMENT_VOIDRESULT(SFZSingleEditLabelControl, OnWidgetResult, invoker, reason, result) { unused(invoker); switch (reason) { case SFP16_RESULT_OK: result = GetCurrentValue(); break; default: break; } _widget->StartScroll(); // SFZSingleEditLabelControl クラスに SFEVT_RESPONDER_RESULT イベントを送信する InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, reason, result), false); return; }// XANDLER_IMPLEMENT_VOIDRESULT(SFZSingleEditLabelControl, OnWidgetResult) //
SFZSingleEditLabelControl::HandleOperateKey 関数は、 SFZSingleEditLabelControl クラスの操作キーイベントを受信したときに呼び出されます。
この関数では、以下の内部実装コードにあるように SFYSingleEditWidget::Edit 関数を呼び出して FEP を起動します。
FEP 終了時に SFYSingleEditWidget クラスは SFEVT_RESPONDER_RESULT イベントを受信し、 SFZSingleEditLabelControl::OnWidgetResult ハンドラ関数が起動され、 SFZSingleEditLabelControl クラスも SFEVT_RESPONDER_RESULT イベントを受信することになります。
// SFZSingleEditLabelControl クラスが操作キーのイベントを受信したときのハンドラ関数 /*protected virtual */Void SFZSingleEditLabelControl::HandleOperateKey(Void) { SFCError error; _widget->StopScroll(); // FEP に遷移する if ((error = _widget->Edit()) != SFERR_NO_ERROR) { _widget->StartScroll(); InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, error), false); } return; }// SFZSingleEditLabelControl::HandleOperateKey //
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |