第178章 日付・時刻の入力


さて、今回は「日付・時刻」の入力をやります。 と言っても新しいコモンコントロールの解説です。ユーザーに 日付とか時刻を入力させる時に便利です。



メニューの「入力」を選択すると左のようなダイアログボックスが 出てきます。これだけなら全部自前で作れそうですが、さらに 日付のところのボタンを押すと・・・



日付のコンボボックスの下に左のようなカレンダーが出現します。 これで、希望の日付を入力します。年のところをクリックすると 違う年のカレンダーを出すこともできます。月のところをクリックすると 違う月のカレンダーになります。こういったコントロールを Date and Time Picker Controlといいます。



では、作り方をみてみましょう。 WindowsにIE4.0以降がインストールされてなくてはいけません。

1.commctrl.hをインクルードする 2.Comctl32.libをプロジェクトに参加させる 3.INITCOMMONCONTROLSEX構造体に値をセットする 4.InitCommonControlsEx関数を実行 5.DATETIMEPICK_CLASSのウィンドウをCreateWindowEx関数で作る

ま、これだけのことです。新しいコモンコントロールについては すでに、第148章で出てきました。

INITCOMMONCONTROLSEX ic; ... ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_DATE_CLASSES; InitCommonControlsEx(&ic); ... CreateWindowEx(0, DATETIMEPICK_CLASS,...);

というような感じで作ります。 今回のプログラムではこのDate and Time Pickerコントロールを ダイアログボックス上に作ります。

まず、リソース・エディタで「OK」「キャンセル」ボタンだけが 存在するダイアログボックスのテンプレートを作ります。 そしてダイアログボックスのプロシージャでWM_INITDIALOG メッセージが来たら、CreateWindowExでコントロールを作ります。 この時ウィンドウスタイルにDTS_LONGDATEFORMATを指定すると 日付の、DTS_TIMEFORMATを指定すると時刻のコントロールとなります。 他にも、いろいろなウィンドウスタイルがありますが必要に応じて その都度解説します。さて、このコントロールでユーザーの入力した 日付・時刻を取得するにはGetWindowText関数 (第20章)で行えます。

また、コンボボックスに表示する日付・時刻の形式は自由に 改変することができます。これにはDTM_SETFORMATメッセージを使います。

DTM_SETFORMAT wParam = 0; lParam = (LPARAM) lpszFormat;

lpszFormatにはフォーマット文字列のアドレスを指定します。 フォーマット文字列に使用する文字には次のようなものがあります。

文字意味
d1または2桁の日付
dd2桁の日付。日付が1桁の場合は先頭に0がつく
ddd曜日(月、火、水、...)
dddd曜日(月曜日、火曜日、...)
h1または2桁の時間(12時間制)
hh2桁の時間。時間が1桁の時は先頭に0がつく
H1または2桁の時間
HH2桁の時間。時間が1桁の時は先頭に0がつく
m1または2桁の分
mm2桁の分。分が1桁の時は先頭に0がつく
M1または2桁の月
MM2桁の月。月が1桁の時は先頭に0がつく
MMM3桁の月(日本語ではMMと同じ結果になる)
MMMM完全な月(1月、2月...のように「月」がつく)
t一文字の午前午後(日本語では使えない)
tt午前・午後
y1桁の年。(日本語ではyyと同じ結果)
yy2桁の年
yyy4桁の年

また、文字をそのままあらわしたい時はシングル・クォーテーションで囲みます。

"'本日は'MM'月'dd'日です'"

というフォーマット文字列では「本日は02月03日です」と表示されます。

では、プログラムを見てみましょう。

// newctl01.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END MENUITEM "入力(&T)", IDM_INPUT END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 159, 51 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "日付・時刻入力" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,30,50,14 PUSHBUTTON "キャンセル",IDCANCEL,102,30,50,14 END

今回は、Date and Time Pickerコントロールを CreateWindowEx関数で作るのでリソース・スクリプトの ダイアログボックスにはボタンが2つあるのみです。

// newctl01.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND MakeTimeCtl(HWND); HWND MakeDateCtl(HWND); char szClassName[] = "newctl01"; //ウィンドウクラス HINSTANCE hInst; char szTime[256] = ""; char szDate[256] = "";

commctrl.hをインクルードするのを忘れないでください。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるPicker Ctrl", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 300, //幅 140, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

このへんはいつもと同じですが、WinMain関数の最初のほうで インスタンスハンドルをグローバル変数にコピーしている点に 注意して下さい。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HDC hdc; PAINTSTRUCT ps; INITCOMMONCONTROLSEX ic; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_INPUT: DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); break; } break; case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_DATE_CLASSES; InitCommonControlsEx(&ic); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 10, 10, szDate, strlen(szDate)); TextOut(hdc, 10, 50, szTime, strlen(szTime)); EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

メニューからIDM_INPUTが選択されたらダイアログボックスを表示します。

WM_CREATEメッセージが来たらコモンコントロールを初期化します。

WM_PAINTメッセージが来たらグローバル変数のszDate, szTimeを表示します。

HWND MakeTimeCtl(HWND hWnd) { HWND hTime; LPSTR lpstrTime = "tthh'時'mm'分'ss'秒'"; hTime = CreateWindowEx(0, DATETIMEPICK_CLASS, NULL, WS_BORDER | WS_VISIBLE | WS_CHILD | DTS_TIMEFORMAT, 160, 10, 120, 25, hWnd, NULL, hInst, NULL); SendMessage(hTime, DTM_SETFORMAT, 0, (LPARAM)lpstrTime); return hTime; } HWND MakeDateCtl(HWND hWnd) { HWND hDate; LPSTR lpstrDate = "yyy'年'MM'月'dd'日'dddd"; hDate = CreateWindowEx(0, DATETIMEPICK_CLASS, NULL, WS_BORDER | WS_VISIBLE | WS_CHILD | DTS_LONGDATEFORMAT, 10, 10, 150, 25, hWnd, NULL, hInst, NULL); SendMessage(hDate, DTM_SETFORMAT, 0, (LPARAM)lpstrDate); return hDate; }

Date and Time Pickerコントロールを作る関数です。初期状態で コントロールができたら、すぐにDTM_SETFORMATメッセージを送って独自の フォーマットをしています。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hDate, hTime, hParent; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: GetWindowText(hTime, szTime, sizeof(szTime)); GetWindowText(hDate, szDate, sizeof(szDate)); InvalidateRect(hParent, NULL, TRUE); EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; } break; case WM_INITDIALOG: hDate = MakeDateCtl(hDlg); hTime = MakeTimeCtl(hDlg); hParent = GetParent(hDlg); return TRUE; } return FALSE; }

ダイアログボックスの「OK」ボタンが押されたらDate and Time Pickerコントロールの 文字列をグローバル変数にコピーします。その後InvalidateRect関数を呼んで 親ウィンドウにWM_PAINTメッセージを発生させます。

WM_INITDIALOGメッセージが来たら、Date and Time Pickerコントロールを 作ります。この時親のウィンドウハンドルも取得しておくと便利です。

今回は簡単でした。メニューから表示する日付・時刻のフォーマットを 選択できるように改良してみて下さい。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 26/Feb/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。