通常のパソコンで行うような、たくさんのダイアログを切り替えて作業する、といった事は小さな携帯画面では操作もしずらく、あまり現実的ではありません。
WindowsMobileアプリケーションでは、ウインドウであれダイアログであれ、全画面表示にするのが一般的です。その方が使い勝手もよく、他のソフトウェアともインターフェースを統一できるのでお勧めです。
Windows Mobile6 Standardでは、主にナビゲーションバーにOKボタンを表示したフルスクリーンダイアログボックスが使用されます。完了ボタンは視覚的にフルスクリーンのダイアログボックスで隠されてOKボタンに置き換わるため、「ダイアログのOKボタンである」ということが理解しやすいからです。ダイアログのボタンを完了ボタン([×]ボタン)にしていると、親画面の完了ボタン([×]ボタン)なのか、ダイアログの完了ボタンなのか区別がつかず、ユーザの誤動作を招くことになります。
ではダイアログも全画面表示にしてみましょう。
前回のダイアログ「SampleDialog002」を全画面ダイアログになるように変更します。
全画面ダイアログを表示するには、WM_INITDIALOG:でSHInitDialog()を使用します。
SH~()関数と頭にSHのつく関数は、WindowsMobile特有の関数で主にUIの部分に関連する関数です。
このSHInitDialog()関数はSHINITDLGINFO構造体にパラーメータを指定することで、ダイアログボックスのサイズをSIPに合わせて変更します。
SHInitDialog()関数を使用するにはaygshell.hをインクルードします。
■SHInitDialog()
ダイアログの状態を指定するSHINITDLGINFO構造体に値をセットしてSHInitDialog()関数に渡します。
SHINITDLGINFO構造体
typedef struct tagSHINITDLGINFO
{
DWORD dwMask;
HWND hDlg;
DWORD dwFlags;
} SHINITDLGINFO, *PSHINITDLGINFO;
dwMask
SHINITDLGINFO構造でどのメンバーが有効であるかを示すビットフィールドで、SHIDIM_FLAGSを指定します。
hDlg
ダイアログへのハンドルです。必須項目です。
dwFlags
ダイアログの動作を決定するフラグです。SHIDIM_FLAGSフラグが設定されてなければ無視されます。
SHIDIF_DONEBUTTON
ナビゲーションバーにOKボタンを表示します。
SHIDIF_EMPTYMENU
下部に空のメニューを作成します。
SHIDIF_FULLSCREENNOMENUBAR
ダイアログボックスを入力パネルの位置に関係なく、フルスクリーン表示に設定します。
SHIDIF_SIPDOWN
ダイアログ初期化時に入力パネルが開いていたら閉じます。
SHIDIF_SIZEDLG
ダイアログボックスはSIPの邪魔にならないサイズで最大化されます。
SHIDIF_SIZEDLGFULLSCREEN
ダイアログボックスを入力パネルの位置に関係なく、フルスクリーン表示に設定します。
SHIDIF_CANCELBUTTON
[×]ボタン表示しダイアログを閉じると同時にキャンセル(IDCANCEL)を発行します。
SHIDIF_WANTSCROLLBAR
ダイアログが画面に収まらない場合にスクロールバーを表示します。
ソースコードは次のとおりです。
// SampleDialog003.cpp
//
// ダイアログを全画面表示にする
#include <windows.h>
#include <aygshell.h>
#include "resource1.h"
#define ID_BUTTON1 (0) // ボタンのID
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
HWND InitInstance(HINSTANCE, int);
HWND hDlg; // モードレスダイアログボックスのハンドル
HINSTANCE hInst; // アプリケーションインスタンスハンドル
TCHAR szClassName[] = _T("SampleDialog003");
// ウィンドウクラス。UNICODEとしての文字列定数
TCHAR szStr[4]; // ダイアログとのデータ受け渡し用。4文字確保(うち1つはNULLポインタ用)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
MSG msg;
BOOL bRet;
HWND hWnd;
hInst = hInstance; // アプリケーションインスタンスハンドルをグローバル変数へ格納
if (!InitApp(hInstance))
return FALSE;
if (!(hWnd = InitInstance(hInstance,nShowCmd)))
return FALSE;
while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1){
break;
} else {
//ダイアログからのメッセージを処理する。
if(!IsDialogMessage(hDlg,&msg)){
// ダイアログで処理されなかったメッセージは
// ウィンドウプロシージャで処理する。
TranslateMessage(&msg); // 仮想キーメッセージを文字メッセージに変換
DispatchMessage(&msg); // メッセージをウィンドウプロシージャに送る
}
}
}
return (int)msg.wParam;
}
// ウィンドウクラスの登録
ATOM InitApp(HINSTANCE hInst)
{
WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc; // プロシージャ名
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL; // 未サポート
wc.hCursor = NULL; // 未サポート
wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
wc.lpszMenuName = NULL; // 未サポート
wc.lpszClassName=(LPCTSTR) szClassName;
return (RegisterClass(&wc));
}
// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd)
{
HWND hWnd;
hWnd = CreateWindow(szClassName,_T("モードレス"),
WS_CLIPCHILDREN, // ウィンドウの種類
CW_USEDEFAULT, // x座標
CW_USEDEFAULT, // y座標
CW_USEDEFAULT, // 幅
CW_USEDEFAULT, // 高さ
NULL, // 親ウィンドウのハンドル。親を作るのでNULL
NULL, // メニューハンドルまたは子ウィンドウID
hInst, // インスタンスハンドル
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
return hWnd;
}
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
PAINTSTRUCT ps;
HDC hdc;
size_t size; // 文字列のサイズを格納する
HWND hButton;
HWND hDlg;
switch (msg){
case WM_CREATE: // 初期化処理開始
// モードレスダイアログを開くボタン
hButton = CreateWindow(
_T("BUTTON"), // ウィンドウクラス名
_T("DIALOG"), &nb
sp; // キャプション
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // スタイル指定
50, 50, // 座標
60, 40, // サイズ
hWnd, // 親ウィンドウのハンドル
HMENU(ID_BUTTON1), // メニューハンドル
hInst, // インスタンスハンドル
NULL // その他の作成データ
);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd,&ps); // 描画処理を開始
StringCchLength(szStr,STRSAFE_MAX_CCH,&size); // 安全な文字列長取得
ExtTextOut(
hdc, // デバイスコンテキストのハンドル
0, // 開始位置(基準点)の x 座標
20, // 開始位置(基準点)の y 座標
NULL, // 長方形領域の使い方のオプション
NULL, // 長方形領域の入った構造体へのポインタ
szStr, // 文字列
size, // 文字数
NULL // 文字間隔の入った配列
);
EndPaint(hWnd,&ps);
break;
case WM_COMMAND:
switch (LOWORD(wp)){
case ID_BUTTON1
:
// モードレスダイアログウィンドウを開く
hDlg = CreateDialog(
hInst, // アプリケーションのインスタンスのハンドル
MAKEINTRESOURCE(IDD_DIALOG1),
// ダイアログボックステンプレートを指定
hWnd, // 親ウィンドウのハンドル
DlgProc // ダイアログボックスプロシージャへのポインタ
);
ShowWindow(hDlg,SW_SHOW);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
// ダイアログプロシージャ
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
static HWND hParent; // 親ウィンドウのハンドル
int copyCount;
switch(msg){
case WM_INITDIALOG: // ダイアログの初期化処理
{
SHINITDLGINFO shidi;
hParent = GetParent(hDlg); // 親ウィンドウハンドル
// Create a Done button and size it.
shidi.dwMask = SHIDIM_FLAGS; // SHINITDLGINFO構造でどのメンバーが有効であるかを示すビットフィールドです。
// SHIDIM_FLAGSを指定します。
shidi
| SHIDIF_EMPTYMENU // 下部に空のメニューを作成します
| SHIDIF_WANTSCROLLBAR // ダイアログが画面に収まらない場合にスクロールバーを表示します
| SHIDIF_DONEBUTTON // ナビゲーションバーにOKボタンを表示します。
;
shidi.hDlg = hDlg; // ダイアログのハンドル。必須です。
SHInitDialog(&shidi);
return TRUE;
}
case WM_COMMAND: // ダイアログのボタンが押されたときの処理
switch (LOWORD(wp)){
case IDOK:
// エディットコントロールの値を取得
copyCount = GetDlgItemText(hDlg,IDC_EDIT1,szStr,4);
// デバッグプリント
NKDbgPrintfW(_T("szStr :バイト数: %d 文字数:%d コピーした文字数:%d")
,sizeof(szStr),lstrlen(szStr),copyCount);
DestroyWindow(hDlg); // ダイアログを破棄
return TRUE;
case IDCANCEL:
DestroyWindow(hDlg); // ダイアログを破棄
return TRUE;
}
return FALSE;
<
font color="#037e06">}
return FALSE;
}
コンパイル時に
error LNK2019: 未解決の外部シンボル
といったエラーが出る場合、前回はpragmaを使用し、#pragma comment( lib, "aygshell.lib" ) としていたと思います。
これは.dllをリンクする必要があればリンクしなさいという命令です。今回はaygshell.libファイルをリンカ入力として追加します。
プロジェクトを右クリックし[プロパティ]からプロジェクトのプロパティウィンドウを開きます。
[構成]プルダウンリストより[すべての構成]を選択します。
[プラットフォーム]プルダウンリストより[すべてのプラットフォーム]を選択します。
[構成プロパティ]-[リンカ]-[入力]を選択します。
[追加の依存ファイル]プロパティにaygshell.libを追加します。