[[← 4 節に戻る|Palm OS Programmer's Companion Volume II/1-4]] [[↑1 章トップへ|Palm OS Programmer's Companion Volume II/1]] [[6 節に進む →|Palm OS Programmer's Companion Volume II/1-6]] ---- !!!1-5 データの受信   Exchange Manager からデータを受信するには、以下のようにします。 +受信するデータの形式を登録します。詳しくは[[データの登録|Palm OS Programmer's Companion Volume II/1-3]]を参照して下さい。 +表示される確認ダイアログを制御したいなら、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}起動コードを処理します。詳しくは{{a Exchange ダイアログの制御|#p1}}を参照して下さい。 +受信データのプレビューを表示したいなら、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgPreview}}起動コードを処理します。詳しくは{{a プレビューの表示|#p2}}を参照して下さい。 +データを受信するために、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgReceiveData}}起動コードを処理します。詳しくは{{a データの受信|#p3}}を参照して下さい。 +必要なら、レコードを表示するために{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdGoTo}}を処理します。 !!Exchange ダイアログの制御 Exchange Manager がオブジェクトを受信し、あなたのアプリケーションがそのオブジェクトの対象だと決定したなら、あなたのアプリケーションに一連の起動コードが送信されます。多くの場合、あなたのアプリケーションが最初に受信する起動コードは{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}でしょう。 ---- 注意:Palm OS 4.0以降では、Exchange Manager は Exchange ライブラリがユーザー確認ダイアログをオフにすることを許可します。この場合、あなたのアプリケーションは{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}起動コードを受信しません。 ---- Exchange Manager は、データを受信するかどうかをユーザに確認する Exchange ダイアログの表示について、この起動コードを送信します。起動コードは、確認なしにデータを受け取ること、確認なしにデータ受け取りを拒否すること、Exchange ダイアログを置き換えること、の機会をあなたに与えます。 この起動コードには、応答してもしなくても構いません。もし応答しないなら、Exchange Manager は Exchange ダイアログ表示のために{{span style='color:blue;font-family:monospace;',ExgDoDialog}}をコールします。 Palm OS 3.5 以降では、{{span style='color:blue;font-family:monospace;',ExgDoDialog}}関数によりカテゴリのポップアップリストを表示するダイアログを指定できるようになります。このポップアップリストにより、データベースのどのカテゴリにデータを受信するかをユーザが決めることができます。しかし、ポップアップリストはデフォルトでは表示されません。もし Exchange ダイアログでポップアップリストを表示したいなら、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}に応答して{{span style='color:blue;font-family:monospace;',ExgDoDialog}}をコールしなければいけません。{{span style='color:blue;font-family:monospace;',ExgDialogInfoType}}構造体にポインタを渡します。{{span style='color:blue;font-family:monospace;',ExgDialogInfoType}}構造体は以下のように定義します。 typedef struct { UInt16 version; DmOpenRef db; UInt16 categoryIndex; } ExgDialogInfoType; →'''version''' 構造体のバージョンが0であることを指定するために、このフィールドに0をセットします。 →'''db''' 表示するダイアログのカテゴリを定義するデータベース(オープン済)のポインタです。 ←'''categoryIndex''' ユーザが受信データをどのカテゴリに含めたいか、のカテゴリを示すインデックスです。 もし db が有効なら、この関数は指定されたデータベースからカテゴリ情報を取り出し、それをポップアップリストに表示します。値を返すとき、{{span style='color:blue;font-family:monospace;',categoryIndex}}フィールドにはユーザが選択したカテゴリのインデックスが格納されています。もしユーザがカテゴリを選択しなかった場面は、{{span style='color:blue;font-family:monospace;',dmUnfiledCategory}}が格納されています。 もし ExgDoDialog のコールが成功したなら、あなたのアプリケーションは{{span style='color:blue;font-family:monospace;',categoryIndex}}に返された値を保持する責任があり、そのカテゴリのレコードとして受信データをファイルするためにそれを使用します。このようにする一つの方法は、ソケットの{{span style='color:blue;font-family:monospace;',appData}} フィールド({{span style='color:blue;font-family:monospace;',ExgSocketType}}参照)に{{span style='color:blue;font-family:monospace;',categoryIndex}}を保存し、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgReceiveData}}起動コードへの応答としてソケットからそれを取り出すことです。例として、 Listing 1.5を参照して下さい。 '''Listing 1.5 Exchange ソケットからのカテゴリの取り出し''' UInt16 categoryID = (ExgSocketType *)cmdPBP->appData; /* Receive the data, and create a new record using the received data. indexNew is the index of this record. */ if (category != dmUnfiledCategory){ UInt16 attr; Err err; err = DmRecordInfo(dbP, indexNew, &attr, NULL, NULL); // Set the category to the one the user specified, and // mark the record dirty. if ((attr & dmRecAttrCategoryMask) != category) { attr &= ~dmRecAttrCategoryMask; attr |= category | dmRecAttrDirty; err = DmSetRecordInfo(dbP, indexNew, &attr, NULL); } } いくつかの Palm OS ビルトインアプリケーション(アドレス帳、メモ帳、ToDo)は、ビーム経由で受信したデータのカテゴリを設定する際にこの方法を使用しています。{{span style='color:blue;font-family:monospace;',ExgDoDialog}}の使い方に関するより完全な例は、これらのアプリケーションのサンプルコード(Palm OS SDK に含まれます)を参照して下さい。 明確に{{span style='color:blue;font-family:monospace;',ExgDoDialog}}をコールするときは、システムが2回目のダイアログを表示することを防ぐために、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}起動コードのパラメータブロックの{{span style='color:blue;font-family:monospace;',result}}フィールドに{{span style='color:blue;font-family:monospace;',exgAskOk}} (成功時) か{{span style='color:blue;font-family:monospace;', exgAskCancel}}(失敗時)のいずれかをセットしなければいけません。 !!プレビューの表示 Palm OS 4.0 以降では、Exchange ダイアログには受信するデータのプレビューが含まれています。プレビューにより、ユーザは詳細を見ることができます。プレビューの理由は、Palm OS 4.0 以降では赤外線ライブラリ以外の Exchange ライブラリもサポートしているからです。赤外線ライブラリを使って他のPalmハンドヘルドにデータをビームするとき、送信側と受信側はお互いに近くにないといけません。他の転送メカニズムではデバイス同士が近くにある必要がないので、ユーザは受信データの詳細やなぜ受信するかを知らないかもしれません。この場合、ユーザは受信データの情報を更に必要とするかもしれないので、Exchange Manager はオブジェクトについての情報を Exchange ダイアログに表示します。また、いくつかの Exchange ライブラリでは Exchange ソケットの{{span style='color:blue;font-family:monospace;',description}}フィールドのための情報を転送しないので、Exchange Manager はユーザに受信データの情報を供給する別の手段を用意するべきです。 プレビューを表示するために、Exchange Manager は受信アプリケーションを {{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgPreview}}起動コードで起動します。あなたのアプリケーションは、この起動コードに応答しなくてもかまいません。もし応答しないなら、Exchange Manager は以下の一覧に位置する最初の項目を表示します。 *Exchange ソケットの{{span style='color:blue;font-family:monospace;',description}}フィールドからの、データの説明 *ソケットの{{span style='color:blue;font-family:monospace;',name}}フィールドにあるファイル名 *Exchange レジストリに格納されている、受信アプリケーションの説明(この説明は登録時に{{span style='color:blue;font-family:monospace;',ExgRegisterDatatype}}に渡す) *ソケットの{{span style='color:blue;font-family:monospace;',type}}フィールドにある MIME 形式 *ソケットの{{span style='color:blue;font-family:monospace;',name}}フィールドにあるファイル拡張子 前出の一覧よりもきめ細かなプレビューをサポートしたいなら、{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgPreview}}起動コードを処理します。 その起動コードのパラメータブロックは、{{span style='color:blue;font-family:monospace;',ExgPreviewInfoType}}構造体です。この構造体は、{{span style='color:blue;font-family:monospace;',ExgSocketType}}構造体(Exchange Managerが期待しているプレビューデータの形式を説明する{{span style='color:blue;font-family:monospace;',op}}フィールドと、データを返すためのフィールド)を含んでいます。 その起動コードに応答するなら、以下のようにします。 +期待されるプレビューデータの形式を参照するために、パラメータブロックの{{span style='color:blue;font-family:monospace;',op}}フィールドを確認します。多くの場合、プレビューデータは文字列ですが、画像表示も要求されるかもしれません。 +Exchangeライブラリとの通信を確立するために、{{span style='color:blue;font-family:monospace;',ExgAccept}}をコールします。 +データを受信するために、{{span style='color:blue;font-family:monospace;',ExgReceive}}を1回以上コールします。この関数では受信バイト数を指定し、受信されたバイト数を返します。受信すべきデータが残っているなら、何度かコールする必要があるかもしれません。 +{{span style='color:blue;font-family:monospace;',op}}フィールドで文字列プレビューを指定された場合、パラメータブロックの{{span style='color:blue;font-family:monospace;',string}}フィールドにデータを配置します。{{span style='color:blue;font-family:monospace;',op}}フィールドで画像プレビューを指定された場合、パラメータブロックの{{span style='color:blue;font-family:monospace;',bounds}}フィールドで指定された矩形領域にデータを描画します。 +接続を終了するために{{span style='color:blue;font-family:monospace;',ExgDisconnect}}をコールします。戻り値がゼロ( 0 )の場合は、転送が成功したということです。 データのプレビュー時はデータ受信時と本質的に同じステップを踏む、ということに注意して下さい。唯一の違いは受信後にデータについて何をするかだけです。{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgPreview}}への応答時は、Exchange Manager にデータを戻し、ユーザがデータを拒否した場合はそれを破棄します。{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgReceiveData}}への応答時は、データを貯めこみます。 {{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgPreview}}起動コードを処理する例としては、 Palm OS SDK に含まれているアドレス帳(Address Book)アプリケーションを参照して下さい。{{span style='color:blue;font-family:monospace;',TransferPreview}}関数でその起動コードを処理します。 !!データの受信 Exchange Manager が Exchange ダイアログへの応答として{{span style='color:blue;font-family:monospace;',exgAskOk}}または{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgAskUser}}起動コードを受信したなら、次のステップは{{span style='color:blue;font-family:monospace;'sysAppLaunchCmdExgReceiveData}}によるアプリケーションの起動です。この起動コードはアプリケーションに対して実際にデータを受信することを知らせます。 この起動コードに応答するには、以下のようにします。 +接続を受け入れるために ExgAccept をコールします。 +データを受信するために1回以上 ExgReceive をコールします。この関数では、受信するバイト数を指定します。また、{{span style='color:blue;font-family:monospace;',ExgReceive}}は受信されたバイト数を返します。受信すべきデータが残っているなら、何度かコールする必要があるかもしれません。ソケット構造体において、{{span style='color:blue;font-family:monospace;',length}}フィールドは正確でないかもしれないので、受信ループでは{{span style='color:blue;font-family:monospace;',length}}で指定された長さより多くても少なくても処理できるよう柔軟にしておくべきである、ということに注意して下さい。 +もしあなたのアプリケーションで再び{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdGoTo}}起動コードにより起動したいなら、あなたのアプリケーションのクリエータIDをExgSocketTypeの{{span style='color:blue;font-family:monospace;',goToCreator}}フィールドに配置し、渡される起動コードの情報を{{span style='color:blue;font-family:monospace;',gotoParams}}フィールドに与えます。({{span style='color:blue;font-family:monospace;',ExgSocketType}}構造体は{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgReceiveData}}のパラメーターブロックです) +接続を終了するために ExgDisconnect をコールします。戻り値がゼロ( 0 )の場合は、転送が成功したということです。 {{span style='color:blue;font-family:monospace;',sysAppLaunchCmdExgReceiveData}}から戻った後、もし{{span style='color:blue;font-family:monospace;',goToCreator}}があなたのアプリケーションのクリエータIDを指定し、かつ Exchange ライブラリがそれをサポートするなら、あなたのアプリケーションは{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdGoto}}で起動されます。この起動コードに応答するときは、あなたのアプリケーションは起動し、そのデータベースを開き、パラメータブロックの{{span style='color:blue;font-family:monospace;',recordNum}}フィールド(または{{span style='color:blue;font-family:monospace;',matchCustom}}フィールド)で指定されるレコードを表示するべきです。Exchange Manager は常に{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdGoto}}により完全なアプリケーション起動を行うので、あなたのアプリケーションはグローバル変数へのアクセスを持ちます。しかし、もしグローバル検索機能を実装するためにこの起動コードを使用するなら、そのインスタンスではグローバル変数へのアクセスを持つことはできません。Listing 1.6のサンプルコードは、グローバル変数が利用できるかどうか確認し、もし利用できるなら、それらを初期化するために{{span style='color:blue;font-family:monospace;',StartApplication}}をコールします。 '''Listing 1.6 sysAppLaunchCmdGotoへの応答''' case sysAppLaunchCmdGoto: if (launchFlags & sysAppLaunchFlagNewGlobals) { err = StartApplication(); if (err) return err; GoTo(cmdPBP, true); EventLoop(); StopApplication(); } else { GoTo(cmdPBP, false); } Palm OS 4.0 以降では、データ受信後に{{span style='color:blue;font-family:monospace;',sysAppLaunchCmdGoto}}起動コードを使用することを全ての Exchange ライブラリがサポートしているわけではありません。 また、Palm OS 4.0 以降では複数オブジェクトの交換をサポートしているため、データ受信の最後に起動されたのがあなたのアプリケーション1つである、という保証がないことに注意してください。もし複数オブジェクトが受信されたなら、あなたのアプリケーションの後に他のアプリケーションがデータを受信するかもしれませんし、他のアプリケーションがそれ自身のクリエータIDを{{span style='color:blue;font-family:monospace;',goToCreator}}フィールドにセットするかもしれません。この場合、フィールドにセットする最後のアプリケーションが起動されます。 Listing 1.7 は、データオブジェクトを受信して{{span style='color:blue;font-family:monospace;',goToCreator}}と{{span style='color:blue;font-family:monospace;',goToParams}}をセットする関数を示しています。このコードは Palm OS SDK に含まれる Beamer サンプルアプリケーションから持ってきたものです。 '''Listing 1.7 データオブジェクトの受信''' static Err ReceiveData(ExgSocketPtr exgSocketP) { Err err; MemHandle dataH; UInt16 size; UInt8 *dataP; Int16 len; UInt16 dataLen = 0; if (exgSocketP->length) size = exgSocketP->length; else size = ChunkSize; dataH = MemHandleNew(size); if (!dataH) return -1; // // accept will open a progress dialog and wait for your receive commands err = ExgAccept(exgSocketP); if (!err){ dataP = MemHandleLock(dataH); do { len = ExgReceive(exgSocketP,&dataP[dataLen], size-dataLen,&err); if (len && !err) { dataLen+=len; // resize block when we reach the limit of this one... if (dataLen >= size) { MemHandleUnlock(dataH); err = MemHandleResize(dataH,size+ChunkSize); dataP = MemHandleLock(dataH); if (!err) size += ChunkSize; } } } while (len && !err); MemHandleUnlock(dataH); ExgDisconnect(exgSocketP,err); // closes transfer dialog if (!err) { exgSocketP->goToCreator = beamerCreator; exgSocketP->goToParams.matchCustom = (UInt32)dataH; } } // release memory if an error occured if (err) MemHandleFree(dataH); return err; } ---- [[← 4 節に戻る|Palm OS Programmer's Companion Volume II/1-4]] [[↑1 章トップへ|Palm OS Programmer's Companion Volume II/1]] [[6 節に進む →|Palm OS Programmer's Companion Volume II/1-6]]