第179章 DTPの色をカスタマイズする


DTPとは前章で解説したDate and Time Pickerの略です。 この色をカスタマイズするメッセージとかマクロが用意されています。

また、前章ではCreateWindowEx関数を用いてコントロールを作成しましたが 今回はVC++のリソースエジタを利用してコントロールを作成します。 また、ダイアログボックスに簡単なメニューを付けます。



ダイアログボックスのメニューで「文字色」を選択すると 左のようなサブメニューが出現します。 ここから、「青」を選択すると・・



1日から月末までの日付の色が青色に変わります。 このほかに、タイトルバーの色などいろいろな個所の色を 変える事ができます。



まず、リソース・エディタで左の図のようなダイアログ・テンプレートを 作ります。この時「OK」「キャンセル」ボタンが少し上のほうに寄っている ことに注意して下さい。これは、あとからメニューが挿入されて コントロール全体が下方に移動されるからです。DTPCは、ツールバーの 「コントロール」の中の「日時指定」を選択します。 そして、「ボタン」を作るのと同じ要領で矩形の位置・大きさを 決めます。このコントロールのプロパティの「書式」の中から 「長い形式の日付」「短い形式の日付」「時間」などを選択します。

左の図では日付のコントロールのIDはIDC_DATETIMEPICKER1、右の時間の コントロールのIDはIDC_DATETIMEPICKER2にしてあります。



次に青、赤、緑のメニューアイテムのビットマップを用意します。 これは、"BLUE", "RED", "GREEN"という名前にしておきます。

さて、これだけの準備ができればあとは、前章とほとんど同じ 要領でプログラムを作ることができます。

ビットマップを持つメニューの作り方はすでに 第42章でやりました。 さて、第42章ではCreateMenuやCreatePopupMenu関数で 空のメニューを作っておいてAppendMenuでメニュー項目を追加していきました。 ところが、AppendMenu関数で追加していきました。ところが、このAppendMenu 関数は現在ではInsertMenuItem関数に取って代わられました。 互換性のため、まだ、AppendMenu関数は使えますが将来も使える保証はありません。

BOOL WINAPI InsertMenuItem( HMENU hMenu, UINT uItem, BOOL fByPosition, LPMENUITEMINFO lpmii );

hMenuはメニュー項目を挿入するメニューのハンドルを指定します。

uItemはメニュー項目または位置を指定します。この項目の前に新しい項目が挿入されます。

fByPositionにFALSEを指定するとuItemはメニュー項目のID、 FALSE意外を指定すると位置になります。

lpmiiには、MENUITEMINFO構造体へのポインタを指定します。 これは、次のように定義されています。

typedef struct tagMENUITEMINFO { UINT cbSize; UINT fMask; UINT fType; UINT fState; UINT wID; HMENU hSubMenu; HBITMAP hbmpChecked; HBITMAP hbmpUnchecked; DWORD dwItemData; LPTSTR dwTypeData; UINT cch; } MENUITEMINFO, FAR *LPMENUITEMINFO;

cbSizeには、この構造体の大きさを指定します。

fMaskには、セットするメンバーを指定します。これは次のうちの 1つまたはそれ以上の組み合わせとなります。
意味
MIIM_CHECKMARKShbmpCheckedとhbmpUncheckedメンバをセットします。
MIIM_DATAdwItemDataメンバをセットします。
MIIM_IDwIDメンバをセットします。
MIIM_STATEfStateメンバをセットします。
MIIM_SUBMENUhSubMenuメンバをセットします。
MIIM_TYPEfTypeおよびdwTypeDataをセットします。

fTypeにはメニュー項目のタイプを指定します。次の1つまたはそれ以上の組み合わせです。
意味
MFT_BITMAPビットマップを使ってメニュー項目を表示します。
dwTypeDataメンバの下位ワード値がビットマップハンドルになります。
cchメンバは無視されます。
MFT_MENUBARBREAKメニュー項目を新しい列に置きます。
ドロップダウンメニュー、サブメニュー、ショートカットメニューの
時は区切り線が入ります。
MFT_MENUBREAKメニュー項目を新しい列に置きます。
区切り線は入りません。
MFT_OWNERDRAWオーナードローをする時指定します。
dwTypeDataメンバにはアプリケーション定義の32ビット値が入ります。
MFT_RADIOCHECKhbmpCheckedメンバがNULLの時
ラジオボタンを使ってチェックされます。
MFT_RIGHTJUSTIFYメニュー項目が右揃えになります。
MFT_RIGHTORDERアラビア語とかヘブライ語の時指定。
MFT_SEPARATOR区切り線。
dwTypeDataとcchメンバは無視されます。
MFT_STRINGメニュー項目に文字列を使います。
dwTypeDataに文字列へのポインタを指定します。
cchには文字列の長さを指定します。


The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING は互いに組み合わせることは できません。

fStateには、メニュー項目の状態を指定します。
意味
MFS_CHECKEDメニュー項目にチェックをつけます。
MFS_DEFAULTそのメニュー項目がデフォルトであることを指定します。
MFS_DISABLEDメニュー項目を選択不能にします。
MFS_ENABLEDメニュー項目を選択可能にします。
MFS_GRAYEDメニュー項目を灰色にして選択不能にします。
MFS_HILITEメニュー項目をハイライトします。
MFS_UNCHECKEDメニュー項目からチェックをはずします。
MFS_UNHILITEメニュー項目のハイライトをやめます。

wID はメニューアイテムのIDを指定します。

hSubMenuは、メニュー項目に関連付けられたサブメニューのハンドルを指定します。 メニュー項目がサブメニューを持たない時はNULLを指定します。

hbmpChecked には、チェックマークのビットマップハンドルを指定します。 NULLの時はデフォルトのマークが使われます。

hbmpUncheckedはチェックがはずされた時のビットマップのハンドルを 指定します。NULLの時はビットマップは使われません。

dwItemDataはメニュー項目に関連したアプリケーション定義の値です。

dwTypeDataはメニュー項目の内容です。fMaskにMIIM_TYPEが指定された時のみ有効です。

cchはMFT_STRINGタイプのメニュー項目についての情報を受け取る時の メニュー項目のテキストの長さです。このメンバはMIIM_TYPEフラグがセットされている時のみ 使われます。他の場合は0です。

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

// newctl02.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, 65 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "日付・時刻入力" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,25,50,14 PUSHBUTTON "キャンセル",IDCANCEL,102,25,50,14 CONTROL "DateTimePicker1",IDC_DATETIMEPICKER1,"SysDateTimePick32", DTS_RIGHTALIGN | DTS_LONGDATEFORMAT | WS_TABSTOP,7,7,67, 14 CONTROL "DateTimePicker2",IDC_DATETIMEPICKER2,"SysDateTimePick32", DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP | 0x8,77,7,75, 14 END ///////////////////////////////////////////////////////////////////////////// // // Bitmap // BLUE BITMAP DISCARDABLE "blue.bmp" RED BITMAP DISCARDABLE "red.bmp" GREEN BITMAP DISCARDABLE "green.bmp"

今回はDialogのリソース・スクリプトにDTPが組み込まれていることに注意して下さい。

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

ダイアログボックスに付けるメニューは、アプリケーション側で 作る為reource.hにIDが反映されません。それで、自分でdefineしています。

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; }

このへんは、いつもと変わりません。

//ウィンドウプロシージャ 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; }

プロシージャ部分も前回と同じです。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hDate, hTime, hParent; static COLORREF crTextClr; LPSTR lpstrDateFormat = "yy'年'MM'月'dd'日('ddd')'"; LPSTR lpstrTimeFormat = "tthh'時'mm'分'ss'秒'"; 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; case IDM_BLUE: crTextClr = RGB(0, 0, 255); DateTime_SetMonthCalColor(hDate, MCSC_TEXT, crTextClr); break; case IDM_RED: crTextClr = RGB(255, 0, 0); DateTime_SetMonthCalColor(hDate, MCSC_TEXT, crTextClr); break; case IDM_GREEN: crTextClr = RGB(0, 255, 0); DateTime_SetMonthCalColor(hDate, MCSC_TEXT, crTextClr); break; } break; case WM_INITDIALOG: SetMenuBMP(hDlg); hDate = GetDlgItem(hDlg, IDC_DATETIMEPICKER1); hTime = GetDlgItem(hDlg, IDC_DATETIMEPICKER2); SendMessage(hDate, DTM_SETFORMAT, 0, (LPARAM)lpstrDateFormat); SendMessage(hTime, DTM_SETFORMAT, 0, (LPARAM)lpstrTimeFormat); hParent = GetParent(hDlg); DateTime_SetMonthCalColor(hDate, MCSC_TEXT, crTextClr); return TRUE; } return FALSE; }

ダイアログのプローシージャです。メニューからIDM_RED, IDM_GREEN, IDM_BLUEが 選択されたらそれぞれの色をcrTextClrにコピーしておきます。 そして、DateTime_SetMonthCalColorマクロで色を設定します。さて、ここで注意すべこことは まだ色の設定が行われていない時crTextClrはstaticな変数なので0(黒)になっています。 これがデフォルトの色となります。一度設定した色はダイアログを閉じても次回 ダイアログを開いた時有効になります。

COLORREF DateTime_SetMonthCalColor( HWND hwndDP, int iColor, COLORREF clr );

DTPコントロールのカレンダーの色を変えるマクロです。 DTM_SETMCCOLOR メッセージを送っても同様のことが行えます。

hwndDPはDTPコントロールのハンドルです。

iColorは色をセットする部分を指定します。次の中から1つを指定します。
意味
MCSC_BACKGROUND月の間の背景色とあるが意味不明
MCSC_MONTHBKカレンダー部分の背景色
MCSC_TEXTその月のテキスト(1日から月末まで)
MCSC_TITLEBKタイトルの背景色、および曜日の色
MCSC_TITLETEXTタイトルのテキストの色
MCSC_TRAILINGTEXT前月およびよく月の日にちの色

clrには色を指定します。

WM_INITDIALOGが来たら、GetDlgItem関数でDTPコントロールのハンドルを 取得します。

void SetMenuBMP(HWND hDlg) { HMENU hMenu, hSubMenu; HBITMAP hBMPG, hBMPR, hBMPB; MENUITEMINFO mi; hBMPG = LoadBitmap(hInst, "GREEN"); hBMPR = LoadBitmap(hInst, "RED"); hBMPB = LoadBitmap(hInst, "BLUE"); hMenu = CreateMenu(); hSubMenu = CreatePopupMenu(); memset(&mi, 0, sizeof(MENUITEMINFO)); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask = MIIM_TYPE | MIIM_SUBMENU; mi.fType = MFT_STRING; mi.fState = MFS_ENABLED; mi.wID = 0; mi.hSubMenu = hSubMenu; mi.dwTypeData = "文字色(&C)"; InsertMenuItem(hMenu, 0, TRUE, &mi); mi.fMask = MIIM_TYPE | MIIM_ID; mi.fType = MFT_BITMAP; mi.wID = IDM_GREEN; mi.dwTypeData = (LPTSTR)hBMPG; InsertMenuItem(hSubMenu, 0, TRUE, &mi); mi.wID = IDM_RED; mi.dwTypeData = (LPSTR)hBMPR; InsertMenuItem(hSubMenu, 1, TRUE, &mi); mi.wID = IDM_BLUE; mi.dwTypeData = (LPSTR)hBMPB; InsertMenuItem(hSubMenu, 2, TRUE, &mi); SetMenu(hDlg, hMenu); return; }

ダイアログボックスにビットマップのメニュー項目を持つメニューを 付ける関数です。InsertMenuItem関数とMENUITEMINFO構造体の使い方に注意して下さい。
[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

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