たまにはVC++ネタ。
コモンコントロールのカラーダイアログは、テンプレートとフックプロシージャでその振る舞いをカスタマイズできますが、そのテンプレートの使い方のサンプルです。というのも、ファイル選択ダイアログのようにカスタマイズ部分のテンプレートを作ればよいのかと思ったら、全部作らなければいけないのを知らなかったので…。
上図のように、標準のカラーダイアログにWEBでよく使われるカラーコード(ただの16進表記ですね)を表示・編集するエディットボックスを追加するサンプルをWTLで作ってみました。
まずダイアログリソースはWindows SDKのインクルードフォルダにあるColor.Dlgファイルからコピーします。ソリューションエクスプローラーからプロジェクトのリソースファイルを右クリックして、「コードの編集」で開いたら「Dialog」のところに貼り付けてカラーコード用のエディットボックスを追加します。
こんな感じです。
DLG_COLOR DIALOGEX 2, 0, 331, 184 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "色の設定" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN LTEXT "基本色(&B):",IDC_STATIC,4,4,140,9 CONTROL "",COLOR_BOX1,"Static",SS_SIMPLE | WS_GROUP | WS_TABSTOP,4,14,140,86 LTEXT "作成した色(&C):",IDC_STATIC,4,106,140,9 CONTROL "",COLOR_CUSTOM1,"Static",SS_SIMPLE | WS_GROUP | WS_TABSTOP,4,116,140,28 PUSHBUTTON "色の作成(&D) >>",COLOR_MIX,4,150,140,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,4,166,44,14,WS_GROUP PUSHBUTTON "キャンセル",IDCANCEL,52,166,44,14,WS_GROUP PUSHBUTTON "ヘルプ(&H)",1038,100,166,44,14,WS_GROUP CONTROL "",COLOR_RAINBOW,"Static",SS_SIMPLE | SS_SUNKEN,152,4,150,116 CONTROL "",COLOR_LUMSCROLL,"Static",SS_SIMPLE | SS_SUNKEN,310,4,8,116 CONTROL "",COLOR_CURRENT,"Static",SS_SIMPLE | SS_SUNKEN,152,124,52,15 PUSHBUTTON "&o",COLOR_SOLID,300,200,6,14,WS_GROUP RTEXT "色",COLOR_SOLID_LEFT,153,141,13,9 LTEXT "| 純色(&O)",COLOR_SOLID_RIGHT,169,141,35,9 RTEXT "色合い(&E):",COLOR_HUEACCEL,204,126,49,9 EDITTEXT COLOR_HUE,257,124,18,12,WS_GROUP RTEXT "鮮やかさ(&S):",COLOR_SATACCEL,204,140,49,9 EDITTEXT COLOR_SAT,257,138,18,12,WS_GROUP RTEXT "明るさ(&L):",COLOR_LUMACCEL,204,154,49,9 EDITTEXT COLOR_LUM,257,152,18,12,WS_GROUP RTEXT "赤(&R):",COLOR_REDACCEL,279,126,24,9 EDITTEXT COLOR_RED,306,124,18,12,WS_GROUP RTEXT "緑(&G):",COLOR_GREENACCEL,279,140,24,9 EDITTEXT COLOR_GREEN,306,138,18,12,WS_GROUP RTEXT "青(&U):",COLOR_BLUEACCEL,279,154,24,9 EDITTEXT COLOR_BLUE,306,152,18,12,WS_GROUP PUSHBUTTON "色の追加(&A)",COLOR_ADD,152,166,172,14,WS_GROUP EDITTEXT COLOR_HEX,164,152,40,12,ES_AUTOHSCROLL RTEXT "#",IDC_STATIC,152,154,9,8 END
これだけだとColor.DlgからコピーしたリソースIDが定義されていないので、リソースファイル内とメインのcppファイルでSDKにあるColorDlg.hをインクルードします。
WTLにはCColorDialogがありますが、これと同じようにCColorDialogImplから派生してCCustomColorDialogを作成することにしましょう。EN_CHANGEでHSLまたはRGBのエディットボックスの内容が変化したことを検知して、カラーコード用のエディットボックスの内容を更新します。またカラーコード用のエディットボックスが更新されて6桁入力された時には、_GetSetRGBMessage() によって取得した SETRGBSTRING メッセージを送信することで選択色を更新します。
#pragma once #include <atldlgs.h> class CCustomColorDialog : public CColorDialogImpl<CCustomColorDialog> { public: CCustomColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL) : CColorDialogImpl<CCustomColorDialog>(clrInit, dwFlags, hWndParent) { m_cc.Flags |= CC_ENABLETEMPLATE; m_cc.lpTemplateName = MAKEINTRESOURCE(DLG_COLOR); m_cc.hInstance = (HWND)_Module.m_hInst; } // override base class map and references to handlers BEGIN_MSG_MAP(CCustomColorDialog) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) COMMAND_CODE_HANDLER(EN_CHANGE, OnEnChange) CHAIN_MSG_MAP(CColorDialogImpl<CCustomColorDialog>) END_MSG_MAP() // Handler prototypes (uncomment arguments if needed): // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CenterWindow(GetParent()); // HexEditに初期値を設定 SendMessage(_GetSetRGBMessage(), 0, (LPARAM)m_cc.rgbResult); return TRUE; } LRESULT OnEnChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/) { CString strR, strG, strB, strHex; static bool bIgnoreHexUpdate=false; switch (wID) { case COLOR_HUE: case COLOR_SAT: case COLOR_LUM: case COLOR_RED: case COLOR_GREEN: case COLOR_BLUE: if (!bIgnoreHexUpdate) { GetDlgItemText(COLOR_RED, strR); GetDlgItemText(COLOR_GREEN, strG); GetDlgItemText(COLOR_BLUE, strB); strHex.Format(_T("%02x%02x%02x"), _ttol(strR), _ttol(strG), _ttol(strB)); bIgnoreHexUpdate = true; SetDlgItemText(COLOR_HEX, strHex); bIgnoreHexUpdate = false; } break; case COLOR_HEX: if (!bIgnoreHexUpdate) { GetDlgItemText(COLOR_HEX, strHex); if (strHex.GetLength() != 6) break; strR = strHex.Mid(0, 2); strG = strHex.Mid(2, 2); strB = strHex.Mid(4, 2); strHex = _T("0x") + strB + strG + strR; LPTSTR lpszEnd=NULL; errno = 0; int lValue = _tcstol(strHex, &lpszEnd, 0); if (errno == ERANGE) return false; bIgnoreHexUpdate = true; SendMessage(_GetSetRGBMessage(), 0, (LPARAM)lValue); bIgnoreHexUpdate = false; } else { bIgnoreHexUpdate = false; } break; } return DefWindowProc(); } };
あとはサンプルプロジェクトを見れば分かると思います。