スマートフォン・ジン | Smartphone-Zine

引っ越し先→ https://smartphone-zine.com/

020:WindowsMobileらしい全画面ダイアログを作る

通常のパソコンで行うような、たくさんのダイアログを切り替えて作業する、といった事は小さな携帯画面では操作もしずらく、あまり現実的ではありません。
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.dwFlags = SHIDIF_SIZEDLGFULLSCREEN    
// ダイアログボックスを入力パネルの位置に関係なく、フルスクリーン表示に設定します。
                               | 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を追加します。