WindowsMobile特有のウィンドウ作成
今まで、通常のWindowsと同じようにメインウィンドウを作成してきました。単純にウィンドウを表示すると、下のメニューバーの部分が切れているのがわかると思います。
そこでSIP(Software Input Panel)の高さを考慮したウィンドウサイズを作成し、メニューバーを作成したいと思います。
SIPを考慮したウィンドウサイズの設定
SIPの情報を得るにはSHSipInfo関数を使用します。SIP領域を除いた有効なウィンドウサイズを取得し、MoveWindow関数でウィンドウサイズを変更しています。
SHSipInfo関数 SIPの状態を取得・設定します。
BOOL WINAPI SHSipInfo(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni
);
MoveWindow関数 指定されたウィンドウの位置とサイズを変更します。
BOOL MoveWindow(
HWND hWnd, // ウィンドウのハンドル
int X, // 横方向の位置
int Y, // 縦方向の位置
int nWidth, // 幅
int nHeight, // 高さ
BOOL bRepaint // 再描画オプション
);
SHSipInfo関数はaygshell.hに含まれています。
#include <aygshell.h>
これだけだとビルド時にエラーとなってしまいます。そこで必要であればaygshell.libをリンクするようにリンカに指示を行います。
#pragma comment( lib, "aygshell.lib" )
SHSipInfo関数のほかに、SipGetInfo関数を使用することで同じようにSIPの情報を得ることが出来ますが、今回は使用しません。
BOOL SipGetInfo(
SIPINFO* pSipInfo
);
SIPの状態が変化したときは、トップレベルウィンドウに対してWM_SETTINGCHANGEイベントが通知され、ウィンドウプロシージャの第3引数 WPARAM に、SPI_SETSIPINFOがセットされます。
このイベントが通知されたら、ShShipInfo関数でSIP領域を除いた有効なウィンドウサイズを取得し、MoveWindow関数でウィンドウサイズを変更しています。
case WM_SETTINGCHANGE:
switch( wp )
{
case SPI_SETSIPINFO:
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof( si );
if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) )
{
MoveWindow(
hWnd,
si.rcVisibleDesktop.left,
si.rcVisibleDesktop.top,
si.rcVisibleDesktop.right –
si
si.rcVisibleDesktop.bottom –
si.rcVisibleDesktop.top,
TRUE );
}
break;
}
break;
メニューバーの作成
次にメニューバーを作成します。作成にはSHCreateMenuBar関数を使用します。
BOOL SHCreateMenuBar(
SHMENUBARINFO * pmb
);
SHMENUBARINFO構造体に、メニューの情報を格納してSHCreateMenuBar関数に渡します。サンプルの例ではSHCMBF_EMPTYBARを指定することで、空のメニューバーを作成しています。
SHMENUBARINFO smi = {sizeof(SHMENUBARINFO),hWnd,SHCMBF_EMPTYBAR};
SHCreateMenuBar(&smi);
メニューの作成については、また別の機会に説明しますが、ここでは単純に見た目を整えるための空のメニューを作成して表示しています。
では、ソースファイルです。
// SampleWindow001.cpp
#include <aygshell.h>
#pragma comment( lib, "aygshell.lib" ) // 必要であれば aygshell.lib をリンクするよう、リンカに指示をする。
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
WCHAR szClassName[] = L"SampleWindow001"; // ウィンドウクラス。UNICODEとしての文字列定数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine,int nShowCmd)
{
MSG msg;
BOOL bRet;
if (!InitApp(hInstance))
return FALSE;
if (!InitInstance(hInstance,nShowCmd))
return FALSE;
while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1){
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
// ウィンドウクラスの登録
ATOM InitApp(HINSTANCE hInst)
{
WNDCLASSW 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=(LPCWSTR) szClassName;
return (RegisterClassW(&wc));
}
// ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nShowCmd)
{
HWND hWnd;
hWnd = CreateWindowW(szClassName,L"SampleWindow",
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 TRUE;
}
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
SIPINFO si;
SHMENUBARINFO smi = {sizeof(SHMENUBARINFO),hWnd,SHCMBF_EMPTYBAR};// 空のメニューバー
switch (msg){
case WM_CR
EATE:
// メニューバーを作成する。
SHCreateMenuBar(&smi);
break;
case WM_SETTINGCHANGE:
switch( wp )
{
case SPI_SETSIPINFO:
// SIP領域を除いた有効なウィンドウサイズを取得し、
// MoveWindow関数でウィンドウサイズを変更する。
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof( si );
if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) )
{
MoveWindow(
hWnd,
si.rcVisibleDesktop.left,
si.rcVisibleDesktop.top,
si.rcVisibleDesktop.right -
si.rcVisibleDesktop.left,
si.rcVisibleDesktop.bottom -
si.rcVisibleDesktop.top,
TRUE );
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
今日はここまでです。