Jan, 2004
Microsoft Corporation
適用対象
Windows Mobile 2003 for Pocket PC
Windows Mobile 2003 for Smartphone
Microsoft® Windows CE .NET
要約 : この資料には、縦画面と横画面に対応したモバイルアプリケーションの開発に必要な情報を記載しています。また、提案およびサンプルを備えており、開発者向けの新しいガイドラインとして参照していただけます。
トピック
はじめに
画面方向を意識したアプリケーション開発
コンテンツの再描画
RelayoutDialog()
はじめに
現 在、Microsoft® Windows MobileTM 搭載のすべてのデバイスでは、縦画面モードで表示しています。今後、横画面表示を既定の表示モードに設定したデバイスが発売される可能性があります。ま た、デバイスをリセットせず使用したまま、画面方向を切り替えられるようになるかもしれません。
この資料には、縦画面と横画面に対応したモバイル アプリケーションの開発に必要な情報を記載しています。また、提案およびサンプルを備えており、開発者向けの新しいガイドラインとして参照していただけます。
画面方向を意識したアプリケーション開発
画面方向を切り替える、または [入力] パネルが表示されると、全画面表示および最上位のアプリケーション ウィンドウはすべて、新しい方向に合わせて自動的にサイズ変更されます。
注 : ウィンドウの上、左、および右の座標が、作業領域の境界線の上または外にあるときに、このウィンドウを全画面表示と見なします。作業領域は、タイトル バーの下の画面領域全体を指します。最上位ウィンドウとは、親ウィンドウを持っていない、つまり親が NULLであるウィンドウです。
ウィンドウのサイズが変更すると、アプリケーションは WM_SIZE通知を受け取ります。WM_SIZE メッセージの lParamパ ラメータの下位の語がクライアント領域の新しい幅を、上位の語が新しい高さを指定します。アプリケーションは、ウィンドウ サイズが変更した時点に注意し、それに応じてレイアウトを更新する必要があります。さらに、ウィンドウに含まれるすべての子ウィンドウをレイアウトし直す 必要があります。
アプリケーションに全画面表示ウィンドウがない場合は WM_SIZE 通知を受け取りません。代わりに wParam パラメータを SETTINGCHANGE_RESET に設定した WM_SETTINGCHANGE メッセージを受け取ります。
注 : アプリケーションが、最上位ウィンドウを持つ場合、または SHHandleWMSettingChange 、 SHInitDialog、および SHFullScreenメソッドを利用するウィンドウを作成する場合は、WM_SIZE と WM_SETTINGCHANGE の両方のメッセージを受け取ります。
次のサンプル コードは WM_SIZE と WM_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 例)。
再描画オプション |
縦画面 |
横画面 |
ウィンドウへのコンテンツの適合 : カレンダーでは、作業領域に適合するように、格子のサイズを変更します。 |
|
|
ウィンドウへのコンテンツの適合 : [メモリ設定] コントロール パネルでは、そのリストボックスを、最大サイズに変更し、その周りの他のユーザー インターフェイス要素すべてを再配置します。 |
|
|
コンテンツ変更 : 横画面モードのカレンダー では、一度に 8 か月しか表示されません。 |
|
|
レイアウト変更 : Windows Media Player のボタンは、横画面モードでは、ビデオ クリップの下ではなく、横に表示されます。 |
|
|
正方形に合わせた設計 : カレンダーの [オプション] ダイアログは、どちらの方向でも表示される 240 x 240 の正方形に、全コンテンツを適合させています。 |
|
|
ア プリケーションが、任意のサイズおよび縦横比の表示で動作するように、レイアウトをできるだけ汎用にしておくとよいでしょう。つまり、可能ならば、横画面 モードと縦画面モードを別々にしないということです。横画面モードと縦画面モードを別々に用意する必要がある場合は、単に画面幅が画面高より大きいからと いって、アプリケーションは横画面モードで表示するべきだと考えないでください。たとえば、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_1、IDC_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;
}
}
}
.gif)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.gif)
.gif)