トップ 一覧 検索 ヘルプ RSS ログイン

【C/C++】 POL におけるワイドディスプレイ対応のサンプルの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
{{category 開発情報}}

{{category 陰郎の書いた記事,nolink}}
!!概要
 このトピックでは、POL を使用したアプリケーションで Dynamic Input Area を使用する方法とそのサンプルを提示します。

 

!!説明
 ここでは、WideDisplaySample という名前の POL プロジェクトで、Dynamic Input Area( 以下 DIA ) を非表示にした際に画面上のボタンがそれにあわせて移動する、というものを作成します。

 まずは POL プロジェクトを作成します。ここは別に説明は必要ないでしょう。作成したら、MainForm の OnOpen イベントハンドラ( frmOpenEvent に対応 )を以下のように記述します。

 Boolean CMainForm::OnOpen(EventPtr pEvent, Boolean& bHandled) {
     UInt32 version;
     Err err = ::FtrGet( pinCreator, pinFtrAPIVersion, &version );
     if( !err && version ) {
         ::FrmSetDIAPolicyAttr( GetFormPtr( ), frmDIAPolicyCustom );
         err = ::PINSetInputTriggerState( pinInputTriggerEnabled );
         WinHandle frmHandle = ::FrmGetWindowHandle( GetFormPtr( ) );
         ::WinSetConstraintsSize( frmHandle, 160, 225, 225, 160, 160, 225 );
     }
     bHandled = false;
     return true;
 }

 なにをやっているかというと、FtrGet で PenInputManager の存在を確認し、あれば DIA 関連のセットアップをしているわけです。重要なのが if ブロック内の最後でやっている ::WinSetConstraintsSize( ) 呼び出しで、ここでフォームの縦幅と横幅を指定しています。それぞれ minimum, prefer, maximum を指定します。

 ちなみに、上記コードで呼び出している API には以下のヘッダファイルが必要になりますので、MainForm.cpp に #include 指令を追加しましょう。

 #include "PenInputMgr.h"

 これで、ワイドディプレイをサポートするデバイスであれば DIA エリアを閉じることができるようになります。ユーザーが DIA をオープン/クローズするとアプリケーションに通知がくるのですが、ここが少し厄介なところで、Pen Input Manager には現時点で version 1.0 と1.1 があり、挙動が少し異なります。具体的には、1.0 では notification で sysNotifyDisplayResizedEvent が送られてきます。1.1 では、それに加えて winDisplayChangedEvent というイベントが通知されます。PalmSource のドキュメントでは、両方に対応するために sysNotifyDisplayResizedEvent に反応してアプリ内で winDisplayChangedEvent を ::EvtAddUniqueEventToQueue( ) するようにと書いています。

 それではやってみましょう。POL プロジェクトでは PilotMain 関数が DEFAULT_STARTER マクロで隠されていますから、これを展開します。デバッグビルドとリリースビルドで内容が異なりますが、マクロの定義元から持って来れば以下のように両方に対応できます。

 UInt32 PilotMain( UInt16 wCommand, MemPtr pCommandParameters, UInt16 wLaunchFlags ) {
     TRACE_INIT();
     CWideDisplaySampleApp palmApp;
     palmApp.m_wCommand = wCommand;
     palmApp.m_pCommandParameters = pCommandParameters;
     palmApp.m_wLaunchFlags = wLaunchFlags;
     Err error = palmApp.AppStart( );
     if( error == errNone ) {
         palmApp.EventLoop( );
         error = palmApp.AppStop( );
     }
     TRACE_DONE();
     return error;
 }

 次に、PilotMain 関数の冒頭に以下のようなコードを追加します。これで、Pen Input Manager のバージョンに関わらず winDisplayChangedEvent が通知されるようになりました。

    if( wCommand == sysAppLaunchCmdNotify ) {
        SysNotifyParamType* pNotifyParams = static_cast<SysNotifyParamType*>( pCommandParameters );
        if( pNotifyParams->notifyType == sysNotifyDisplayResizedEvent ) {
            EventType resizedEvent;
            ::MemSet( &resizedEvent, sizeof(EventType), 0 );
            resizedEvent.eType = static_cast<eventsEnum>( winDisplayChangedEvent );
            ::EvtAddUniqueEventToQueue( &resizedEvent, 0, true );
        }
        return errNone;
    }

 notification 関連ではあと1つやることがあります。アプリが動いている間は、sysNotifyDisplayResizedEvent を通知してもらわなければ上記コードを書いた意味がありません。なので、notification の登録と解除をするメソッドを作成し、以下のように実質的なアプリ実行部分を包んであげます( 詳細はダウンロードサンプルを確認してください )。

     RegisterNotify( );
     Err error = palmApp.AppStart( );
     if( error == errNone ) {
         palmApp.EventLoop( );
         error = palmApp.AppStop( );
     }
     UnregisterNotify( );


 では、MainForm に戻って winDisplayChangedEvent をハンドリングしましょう。MainForm.h のイベントマップマクロに winDisplayChangedEvent のエントリを追加します。ハンドラ名は OnDisplayChanged( ) としました。

 public:
     // Form event handlers
     Boolean OnOpen(EventType* pEvent, Boolean& bHandled);
     Boolean OnDisplayChanged(EventPtr pEvent, Boolean& bHandled);
 
     // Event map
     BEGIN_EVENT_MAP(CForm)
         EVENT_MAP_ENTRY(frmOpenEvent, OnOpen)
         EVENT_MAP_ENTRY(winDisplayChangedEvent, OnDisplayChanged)
     END_EVENT_MAP()

 で、この OnDisplayChanged( ) の中でディプレイ領域にあわせてボタンなどのコントロールを移動するコードを書くわけですが、その前に、どんな画面になっているかを。だいたい以下のような感じです。外周に沿ってボタンが4つあるだけですね。

 FORM ID MainForm AT (0 0 160 160)
     NOSAVEBEHIND NOFRAME
 BEGIN
     TITLE "WideDisplaySample"
     BUTTON "Top" ID MAINFORMTOPBUTTON  AT (CENTER 22 AUTO AUTO)
     BUTTON "Bottom" ID MAINFORMBOTTOMBUTTON  AT (CENTER 144 AUTO AUTO)
     BUTTON "Left" ID MAINFORMLEFTBUTTON AT (3 CENTER AUTO AUTO)
     BUTTON "Right" ID MAINFORMRIGHTBUTTON AT (123 CENTER AUTO AUTO)
 END

 では OnDisplayChanged( ) はどんな実装になるか。長くなるのでボタンの移動部分は書きませんが、以下のような感じ。

 Boolean CMainForm::OnDisplayChanged(EventType* pEvent, Boolean& bHandled) {
 
     // get the current bounds for the form
     FormType* pForm = ::FrmGetActiveForm( );
 
     RectangleType displayBounds;
     RectangleType formBounds;
     WinHandle frmHandle = ::FrmGetWindowHandle( pForm );
     ::WinGetBounds( frmHandle, &formBounds );                    // current form bounds
     ::WinGetBounds( ::WinGetDisplayWindow( ), &displayBounds );  // new display window bounds
 
     if( !::MemCmp( &formBounds, &displayBounds, sizeof(RectangleType) ) )
         return;
 
     ::WinSetBounds( frmHandle, &displayBounds );
 
     // ここでボタンなどのコントロールを移動...
 
     ::FrmDrawForm( pForm );
 
     bHandled = false;
     return true;
 
 }

 まず、ディスプレイウィンドウとフォームの矩形領域を比較しています。同じなら何もせず復帰ですが、異なればフォームの領域をディスプレイの矩形にあわせます。そしてボタンなどのコントロールを移動。終わったらフォームを描画...簡単ですね。

 ここまで実装すれば一応動くのですが、Tungsten T5 や TX などで Landscape view にした状態でメニューをイジると、なぜか Portrait view に戻ってしまいます。このあたり、英語力に欠けるせいで読み取りきれないのですが、winEnterEvent に対しても frmOpenEvent でやったのと同じ DIA 関連のセットアップをしなければならないようなことが書かれています。この部分はダウンロードサンプルでは対応していますのでそちらを参照してください。また、ダウンロードサンプルでは、起動直後にもコントロールの位置調整をするために OnDisplayChanged( ) と同じコトをしています。そのため、OnDisplayChanged( ) 内の実装は ReCalcLayout( ) という処理に移動しています。

 
 
!!サンプルのダウンロード
 {{ref WideDisplaySample.zip}}

 

!!参考情報
 このページのサンプルは、PalmSource 提供の「 Applications and Dynamic Input Areas 」というドキュメントを参考にして作成しました。このドキュメントは、Palm OS SDK に付属しています。Palm OS SDK の入手については、「 [[【SDK】Palm OS SDK のダウンロードについて]] 」 を参照してください。

 

!!注意事項
 CodeWarrior に付属している Palm OS SDK は、Dynamic Input Area を利用するために必要な Pen Input Manager が登場する以前のバージョンのため、このページのサンプルをビルドすることができません。PalmSource 社のサイトから最新の Palm OS SDK をダウンロードし、CodeWarrior の環境に反映する必要があります。その方法については、「 [[【C/C++】 CodeWarrior で Palm OS SDK を最新にする方法]] 」 を参照してください。

 また、手元に Pen Input Manager 1.0 を搭載しているデバイスが無いため、完全に動作確認ができているとは言い難い状態です。おそらく Tungsten T3 などは Pen Input Manager 1.0 と思われますので、動作確認をされた方はコメントにてご一報いただけると幸いです。


 

!!コメント
::TH55で動作せず - 陰郎 (2007年02月12日 13時11分01秒)
:::  ...TH55 ではこの方式で DIA エリアを非表示にできないらしいことがわかりました。詳細は今後の調査となりますが、SONY 独自の feature を使用しているのかもしれません。マズは報告まで。

※ コメントスパムが来ますので、コメント用フォームを使用不可としました。コメントを記入したい方は、申し訳ありませんが直接入力するか、あるいは編集してコメント用フォームを有効にして入力願います。
//{{comment multi}}