印刷用ページ      送信     
クリックして評価とフィードバックをお寄せください
MSDN
MSDN ライブラリ
テクニカルドキュメント
 画面方向の切替えに対応したアプリケーションの開発
画面方向の切替えに対応したアプリケーションの開発

Jan, 2004

日本語版最終更新日 2004 年 4 月 2 日

Microsoft Corporation

適用対象

Windows Mobile 2003 for Pocket PC

Windows Mobile 2003 for Smartphone

Microsoft® Windows CE .NET

要約 : この資料には、縦画面と横画面に対応したモバイルアプリケーションの開発に必要な情報を記載しています。また、提案およびサンプルを備えており、開発者向けの新しいガイドラインとして参照していただけます。

トピック

はじめに はじめに
画面方向を意識したアプリケーション開発 画面方向を意識したアプリケーション開発
コンテンツの再描画 コンテンツの再描画
付録 : RelayoutDialog() コード RelayoutDialog()

はじめに

現 在、Microsoft® Windows MobileTM 搭載のすべてのデバイスでは、縦画面モードで表示しています。今後、横画面表示を既定の表示モードに設定したデバイスが発売される可能性があります。ま た、デバイスをリセットせず使用したまま、画面方向を切り替えられるようになるかもしれません。
 この資料には、縦画面と横画面に対応したモバイル アプリケーションの開発に必要な情報を記載しています。また、提案およびサンプルを備えており、開発者向けの新しいガイドラインとして参照していただけます。

画面方向を意識したアプリケーション開発

画面方向を切り替える、または [入力] パネルが表示されると、全画面表示および最上位のアプリケーション ウィンドウはすべて、新しい方向に合わせて自動的にサイズ変更されます。
: ウィンドウの上、左、および右の座標が、作業領域の境界線の上または外にあるときに、このウィンドウを全画面表示と見なします。作業領域は、タイトル バーの下の画面領域全体を指します。最上位ウィンドウとは、親ウィンドウを持っていない、つまり親が NULLであるウィンドウです。

ウィンドウのサイズが変更すると、アプリケーションは WM_SIZE通知を受け取ります。WM_SIZE メッセージの lParamパ ラメータの下位の語がクライアント領域の新しい幅を、上位の語が新しい高さを指定します。アプリケーションは、ウィンドウ サイズが変更した時点に注意し、それに応じてレイアウトを更新する必要があります。さらに、ウィンドウに含まれるすべての子ウィンドウをレイアウトし直す 必要があります。
アプリケーションに全画面表示ウィンドウがない場合は WM_SIZE 通知を受け取りません。代わりに wParam パラメータを SETTINGCHANGE_RESET に設定した WM_SETTINGCHANGE メッセージを受け取ります。
: アプリケーションが、最上位ウィンドウを持つ場合、または SHHandleWMSettingChange SHInitDialog、および SHFullScreenメソッドを利用するウィンドウを作成する場合は、WM_SIZEWM_SETTINGCHANGE の両方のメッセージを受け取ります。

次のサンプル コードは WM_SIZEWM_SETTINGCHANGE の両方のメッセージを利用する WindowProc テンプレートです。

switch (uMessage)
{
case
WM_SIZE:
          //
Recompute the layout of any child windows; resize
          //
list views and edit boxes, and reposition buttons, 
          //
statics, and other controls.
          break;
case
WM_SETTINGCHANGE:
          if
(SETTINGCHANGE_RESET== wParam) {
          //
An orientation change occurred. This is where you
          //
perform processing that you do not want to perform in
          //
WM_SIZE, such as positioning toolbar windows,
          //
sibling controls, and so on. If there is no need to
          //
perform such control repositioning, just ignore
          //
the WM_SETTINGCHANGE message.
 
          }

コンテンツの再描画

縦画面モードでの表示には適合しても横画面モードには適合しないメニューは一般的な問題です。この問題が該当する場合、メニュー間のアイテムを再調整する必要があります。

 アプリケーションのコンテンツを再描画する場合、プログラミングのオプションとして次の 4 つがあります。

•ウィンドウへのコンテンツの適合

•コンテンツの変更

•レイアウトの変更

•すべてのレイアウトで共通して表示される 240x240 の正方形に合わせた設計

次の表では、Windows Mobile 搭載の Pocket PC アプリケーションでコンテンツを再描画する、それぞれのアプローチの例を示しています (ウィンドウへのコンテンツの適合オプションは 2 例)。

再描画オプション

縦画面

横画面

ウィンドウへのコンテンツの適合 :

カレンダーでは、作業領域に適合するように、格子のサイズを変更します。

 

screen_orientation_awareness_image001.gif

 

screen_orientation_awareness_image003.jpg

ウィンドウへのコンテンツの適合 :

[メモリ設定] コントロール パネルでは、そのリストボックスを、最大サイズに変更し、その周りの他のユーザー インターフェイス要素すべてを再配置します。

 

screen_orientation_awareness_image005.jpg

 

screen_orientation_awareness_image007.jpg

コンテンツ変更 :

横画面モードのカレンダー では、一度に 8 か月しか表示されません。

 

screen_orientation_awareness_image009.jpg

 

screen_orientation_awareness_image011.jpg

レイアウト変更 :

Windows Media Player のボタンは、横画面モードでは、ビデオ クリップの下ではなく、横に表示されます。

 

screen_orientation_awareness_image013.jpg

 

screen_orientation_awareness_image015.jpg

正方形に合わせた設計 :

カレンダーの [オプション] ダイアログは、どちらの方向でも表示される 240 x 240 の正方形に、全コンテンツを適合させています。

 

screen_orientation_awareness_image017.gif

 

screen_orientation_awareness_image019.gif

ア プリケーションが、任意のサイズおよび縦横比の表示で動作するように、レイアウトをできるだけ汎用にしておくとよいでしょう。つまり、可能ならば、横画面 モードと縦画面モードを別々にしないということです。横画面モードと縦画面モードを別々に用意する必要がある場合は、単に画面幅が画面高より大きいからと いって、アプリケーションは横画面モードで表示するべきだと考えないでください。たとえば、321 ピクセルの画面幅、320 ピクセルの画面高のデバイスがあるとします。このようなデバイスでは、アプリケーションを横画面モードでも縦画面モードでも表示できますが、アプリケー ションはその最適なまたは優先的なレイアウトとして、縦画面モードを選択できます。

ダイアログのレイアウト

横画面用と縦画面用の 2 つのダイアログ テンプレートが用意されているとします。これらのテンプレートに、同じコントロール ID の付いた同一のコントロールがある場合、WM_SIZE ハンドラとして次のコードを使用できます。

case WM_SIZE:
 
      RelayoutDialog(g_hInst, hDlg,
InWideMode() ?
            MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_1_WIDE) :
      MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_1));

: IDC_STATICとして定義されたすべてのコントロールには、同じコントロール ID が付けられています。したがって複数の IDC_STATIC がある場合は、それらの名前を IDC_STATIC_1IDC_STATIC_2 のように変更する必要があります。

付録 : RelayoutDialog() コード

この RelayoutDialog() を単独で実装する場合、eVC 4.0 では、これだけでコンパイルします。

#include <windows.h>
static void FixupDialogItem(
      HINSTANCE hInst,
          HWND hDlg,
          LPDLGITEMTEMPLATE lpDlgItem,
          LPWORD lpClass,
          LPWORD lpData);
static LPBYTE WalkDialogData(LPBYTE lpData);
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: RelayoutDialog
//
// PURPOSE: Re-lays out a dialog based on a dialog template.      This function
//          iterates through all the child window controls and does a SetWindowPos
//          for each.      It also does a SetWindowText for each static text control
//          and updates the selected bitmap or icon in a static image control.
//          This assumes that the current dialog and the new template have all the
//          same controls, with the same IDCs.
//
// ON ENTRY:
//           HINSTANCE hInst: the hInstance of the current module.
//           HWND hDlg: the dialog to layout.
//                LPCWSTR iddTemplate: the new template for the dialog (can use
//                the MAKEINTRESOURCE macro).
//
// ON EXIT: TRUE if success; FALSE if failure (either the iddTemplate is
//                invalid, or there are two or more IDC_STATICs in the template).
//
BOOL RelayoutDialog(HINSTANCE hInst, HWND hDlg, LPCWSTR iddTemplate)
{
      HRSRC hRsrc = FindResource((HMODULE)hInst, iddTemplate, RT_DIALOG);
      if (hRsrc == NULL)
          {
                return FALSE;
      }
      HGLOBAL hGlobal = LoadResource((HMODULE)hInst, hRsrc);
      if (hGlobal == NULL)
      {
                return FALSE;
      }
      INT nStatics = 0;
      LPBYTE lpData = (LPBYTE)LockResource(hGlobal);
      LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lpData;
      HDWP hDWP = BeginDeferWindowPos(lpTemplate->cdit);
      //
      // See documentation on the DLGTEMPLATE and DLGITEMTEMPLATE structs
      // for more information on the data structures we are walking.
      //
      lpData += sizeof(DLGTEMPLATE);
      lpData = WalkDialogData(lpData);           // menu
      lpData = WalkDialogData(lpData);           // class
      lpData = WalkDialogData(lpData);           // title
          if (lpTemplate->style & DS_SETFONT)<
      {
                lpData += sizeof(WORD);                // font size.
                lpData = WalkDialogData(lpData); // font face.
      }
      for (int i = 0; i < lpTemplate->cdit; i++)
      {
                lpData = (LPBYTE) (((INT)lpData + 3) & ~3);      // force to DWORD boundary.
                LPDLGITEMTEMPLATE lpDlgItem = (LPDLGITEMTEMPLATE)lpData;
                HWND hwndCtl = GetDlgItem(hDlg, lpDlgItem->id);
          if (lpDlgItem->id == 0xFFFF)
                {
          nStatics++;
                }
                //
                // Move the item around.
                //
               {
          RECT r;
          r.left       = lpDlgItem->x;
          r.top      = lpDlgItem->y;
          r.right      = lpDlgItem->x + lpDlgItem->cx;
          r.bottom = lpDlgItem->y + lpDlgItem->cy;
          MapDialogRect(hDlg, &r);
          DeferWindowPos(hDWP, hwndCtl, NULL,
          r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER);
                }
                lpData += sizeof(DLGITEMTEMPLATE);
                LPWORD lpClass = (LPWORD)lpData;
                lpData = WalkDialogData(lpData);      // class
                //
                // Do some special handling for each dialog item (changing text,
                // bitmaps, ensuring visible, etc.
                //
                FixupDialogItem(hInst, hDlg, lpDlgItem, lpClass, (LPWORD)lpData);
                lpData = WalkDialogData(lpData);      // title
                WORD cbExtra = *((LPWORD)lpData); // extra class data.
                lpData += (cbExtra ? cbExtra : sizeof(WORD));
      }
      EndDeferWindowPos(hDWP);
      return nStatics < 2 ? TRUE : FALSE;
}
//
// Called by RelayoutDialog to advance to the next item in the dialog template.
//
static LPBYTE WalkDialogData(LPBYTE lpData)
{
      LPWORD lpWord = (LPWORD)lpData;
      if (*lpWord == 0xFFFF)
      {
                return (LPBYTE)(lpWord + 2);
      }
      while (*lpWord != 0x0000)
      {
                lpWord++;
      }
      return (LPBYTE)(lpWord + 1);
}
//
// Post-processing step for each dialog item.
//      Static controls and buttons: change text and bitmaps.
//      Listboxes and combo boxes: ensures that the selected item is visible.
//
static void FixupDialogItem(
     HINSTANCE hInst,
          HWND hDlg,
          LPDLGITEMTEMPLATE lpDlgItem,
          LPWORD lpClass,
          LPWORD lpData)
{
      if (lpClass[0] == 0xFFFF)
      {
                switch (lpClass[1])
                {
          case 0x0080: // button
          case 0x0082: // static
          {
                   if (lpData[0] == 0xFFFF)
                    {
                    if (lpDlgItem->style & SS_ICON)
                    {
                              HICON hOld = (HICON)SendDlgItemMessage(hDlg, 
 
lpDlgItem->id, STM_GETIMAGE, IMAGE_ICON, 0);
                              HICON hNew = LoadIcon(hInst, MAKEINTRESOURCE(lpData[1]));
                              SendDlgItemMessage(hDlg, lpDlgItem->id,
 
STM_SETIMAGE, IMAGE_ICON, (LPARAM)hNew);
                              DestroyIcon(hOld);
                    }
                    else if (lpDlgItem->style & SS_BITMAP)
                    {
                               HBITMAP hOld = (HBITMAP)SendDlgItemMessage(hDlg,
lpDlgItem->id, STM_GETIMAGE, IMAGE_BITMAP, 0);
                              HBITMAP hNew = LoadBitmap(hInst, MAKEINTRESOURCE(lpData[1]));
                          SendDlgItemMessage(hDlg, lpDlgItem->id,
STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hNew);
                              DeleteObject(hOld);
                    }
                   }
                    else // lpData[0] is not 0xFFFF (it's text).
                              {
                    SetDlgItemText(hDlg, lpDlgItem->id, (LPCTSTR)lpData);
                    }
          }
          break;
          case 0x0083: // list box
          {
                    INT nSel = SendDlgItemMessage(hDlg, lpDlgItem->id, LB_GETCURSEL, 0, 0);
                    if (nSel != LB_ERR) 
          {
                    SendDlgItemMessage(hDlg, lpDlgItem->id, LB_SETCURSEL, nSel, 0);
                    }
          }
          break;
          case 0x0085: // combo box
                  {
                    INT nSel = SendDlgItemMessage(hDlg, lpDlgItem->id, CB_GETCURSEL, 0, 0);
                    if (nSel != CB_ERR)
          {
                    SendDlgItemMessage(hDlg, lpDlgItem->id, CB_SETCURSEL, nSel, 0);
                    }
                          }
         break;
                }
      }
}
 
© 2008 Microsoft Corporation.All rights reserved. 使用条件  |  商標  |  プライバシー
Page view tracker