Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/9-4
9-4 フォームのリサイズ
ペン入力マネージャが入力エリアやコントロールバーの開閉、あるいはディスプレイの表示方向の変更をした場合、sysNotifyDisplayResizedEvent ノティフィケーションが受信登録をしたアプリケーション全てに対してブロードキャストされます。
sysNotifyDisplayResizedEvent を受信したアプリケーションは、(EvtAddUniqueEventToQueue を使って)winDisplayChangedEvent をポストしなければなりません。このイベントにより、フォームがリサイズ処理を自身で処理できます。
リスト 9.3 winDisplayChangedEvent のポスト
case sysAppLaunchCmdNotify: if(((SysNotifyParamType*)cmdPBP)->notifyType == sysNotifyDisplayResizedEvent) { EventType resizedEvent; MemSet(&resizedEvent, sizeof(EventType), 0); //add winDisplayChangedEvent to the event queue resizedEvent.eType = winDisplayChangedEvent; EvtAddUniqueEventToQueue(&resizedEvent, 0, true); } break;
入力エリアはメニューがオープンしていても状態を変更できます。そのような状況では、winEnterEvent を受信した場合にも( リスト 9.3 と同じようなコードで )winDisplayChangedEvent をキューに追加すべきです。
ノティフィケーションには現在のフォームの新しい領域を示す矩形情報が含まれています。一般的に、フォームは入力エリアのクローズに応答してボタンを新しい矩形領域の下部に移動したり、データ領域をリサイズする必要があります。
リスト 9.4 に winDisplayChangedEvent の処理例を示します。
リスト 9.4 winDisplayChangedEvent の処理
// Input area was opened or was closed. Must resize form. case winDisplayChangedEvent: // get the current bounds for the form frmP = FrmGetActiveForm(); WinGetBounds (FrmGetWindowHandle(frmP), &curBounds); // get the new display window bounds WinGetBounds(WinGetDisplayWindow(), &displayBounds); EditFormResizeForm(frmP, &curBounds, &displayBounds); WinSetBounds(FrmGetWindowHandle(frmP), &displayBounds); FrmDrawForm(frmP); handled = true; break;
この例では、フォームには複数行のテキストフィールド、スクロールバー、および最下部にいくつかのボタンがあります。このフォームは winDisplayChangedEvent に応答して EditFormResizeForm という関数にフォームの現在の領域と新しい領域を渡します。この関数をリスト 9.5 に示します。この関数は新旧の幅と高さの違いを調べ、フォーム内のオブジェクトにその違いを適用します。コマンドボタンについては、常に画面の下部に配置されるように位置を変更します。テキストフィールドとスクロールバーについては、より多くのテキスト行がスクリーン上に表示されるようにリサイズを行ないます。
テキストフィールドのあるフォームをリサイズしたら、FldRecalculateField をコールしてフィールドの新しいサイズでワードラップを更新した方が良いでしょう。
リスト 9.5 フォームのリサイズ
void EditFormResizeForm(FormType *frmP, RectangleType* fromBoundsP, RectangleType* toBoundsP) { Int16 heightDelta, widthDelta; UInt16 numObjects, i; Coord x, y; RectangleType objBounds; heightDelta = widthDelta = 0; numObjects = 0; x = y = 0; FieldType* fldP; // Determine the amount of the change heightDelta=(toBoundsP->extent.y - toBoundsP->topLeft.y) - (fromBoundsP->extent.y - fromBoundsP->topLeft.y); widthDelta=(toBoundsP->extent.x - toBoundsP->topLeft.x) - (fromBoundsP->extent.x - fromBoundsP->topLeft.x); // Iterate through objects and re-position them. // This form consists of a big text field and // command buttons. We move the command buttons to the // bottom and resize the text field to display more data. numObjects = FrmGetNumberOfObjects(frmP); for (i = 0; i < numObjects; i++) { switch (FrmGetObjectType(frmP, i)) { case frmControlObj: FrmGetObjectPosition(frmP, i, &x, &y); FrmSetObjectPosition(frmP, i, x + widthDelta, y + heightDelta); break; case frmFieldObj: case frmScrollBarObj: FrmGetObjectBounds(frmP, i, &objBounds); objBounds.extent.x += widthDelta; objBounds.extent.y += heightDelta; FrmSetObjectBounds(frmP, i, &objBounds); fldP = (FieldType*) FrmGetObjectPtr(frmP, i); FldRecalculateField(fldP, false); break; } } }