第345章 時計を作る オプションの改良


今回は、文字盤などの色の設定オプションを少し改良してみます。



右クリックして、メニューの「色のオプション」を選択すると・・・



左の図のようなダイアログボックスが出てきます。



ツリービューを展開して、変更したい色をクリックすると 猫の画像が消えてスライダーが出てきます。

この時スライダーのつまみ位置は、そのときの色を表しています。

このスライダーのつまみを 動かして色を変更します。

スライダーを動かすと中央の矩形にその色が表示されます。

好みの色が決まったら、「設定」ボタンを押します。

「色の設定」を選択するか、ツリービューを折りたたむと また、猫の画像が表示されます。



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

// clock09.rcの一部

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

MYMENU MENU 
BEGIN
    POPUP "ダミーです"
    BEGIN
        POPUP "ファイル(&F)"
        BEGIN
            MENUITEM "終了(&X)...",                 IDM_END
        END
        POPUP "アラーム(&L)"
        BEGIN
            MENUITEM "時刻設定(&S)...",             IDM_ALARMSET
        END
        POPUP "タイマー(&T)"
        BEGIN
            MENUITEM "タイマーセット(&T)...",       IDM_TIMER
            MENUITEM "ストップウォッチ(&S)...",     IDM_STOPWATCH
        END
        POPUP "ストップウォッチ(&S)"
        BEGIN
            MENUITEM "ストップウォッチ(&S)...",     IDM_STOPWATCH
        END
        MENUITEM "色のオプション(&C)...",       IDM_OPTION
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

CAT                     BITMAP                  "bitmap1.bmp"
MASK                    BITMAP                  "bmp00001.bmp"
CAT2                    BITMAP                  "bitmap2.bmp"

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

MYALARM DIALOGEX 0, 0, 115, 73
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | 
    WS_SYSMENU
CAPTION "アラーム設定"
FONT 10, "MS ゴシック", 400, 0, 0x80
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,7,52,50,14
    PUSHBUTTON      "キャンセル",IDCANCEL,58,52,50,14
    CONTROL         "アラームをセットする",IDC_CHECK1,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,7,7,101,15
    CONTROL         "",IDC_DATETIMEPICKER1,"SysDateTimePick32",
                    DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP,30,25,54,17
END

MYTIMER DIALOGEX 0, 0, 123, 54
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | 
    WS_SYSMENU
CAPTION "タイマー設定"
FONT 10, "MS ゴシック", 400, 0, 0x80
BEGIN
    DEFPUSHBUTTON   "スタート",IDOK,7,33,50,14
    PUSHBUTTON      "ストップ",IDCANCEL,65,33,50,14
    CONTROL         "",IDC_DATETIMEPICKER1,"SysDateTimePick32",
                    DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP,35,7,53,19
END

MYSTOPWATCH DIALOGEX 0, 0, 131, 54
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | 
    WS_SYSMENU
CAPTION "ストップウォッチ"
FONT 10, "MS ゴシック", 400, 0, 0x80
BEGIN
    DEFPUSHBUTTON   "スタート",IDOK,7,7,50,14
    PUSHBUTTON      "閉じる",IDCANCEL,71,31,50,14
    PUSHBUTTON      "ストップ",IDC_STOP,71,7,50,14
    PUSHBUTTON      "リセット",IDC_RESET,7,31,50,14
END

MYOPTION DIALOGEX 0, 0, 244, 129
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "色の設定"
FONT 10, "MS ゴシック", 400, 0, 0x80
BEGIN
    DEFPUSHBUTTON   "設定",IDOK,35,108,50,14
    PUSHBUTTON      "閉じる",IDCANCEL,147,108,50,14
    CONTROL         "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | 
                    TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | 
                    WS_BORDER | WS_TABSTOP,7,7,100,93
    CONTROL         "",IDC_SLIDER1,"msctls_trackbar32",TBS_VERT | TBS_BOTH | 
                    TBS_NOTICKS | WS_TABSTOP,157,7,14,70
    CONTROL         "",IDC_SLIDER2,"msctls_trackbar32",TBS_VERT | TBS_BOTH | 
                    TBS_NOTICKS | WS_TABSTOP,180,7,14,70
    CONTROL         "",IDC_SLIDER3,"msctls_trackbar32",TBS_VERT | TBS_BOTH | 
                    TBS_NOTICKS | WS_TABSTOP,201,7,14,70
    LTEXT           "スタティック",IDC_STATIC1,157,77,17,11
    LTEXT           "スタティック",IDC_STATIC2,181,77,16,11
    LTEXT           "スタティック",IDC_STATIC3,203,77,18,11
    LTEXT           "R",IDC_STATIC,159,92,8,8
    LTEXT           "G",IDC_STATIC,182,92,8,8
    LTEXT           "B",IDC_STATIC,205,92,8,8
    CONTROL         "",IDC_FRAME,"Static",SS_BLACKFRAME,112,7,30,25
    CONTROL         "CAT2",IDC_PIC,"Static",SS_BITMAP,110,7,13,13
END

/////////////////////////////////////////////////////////////////////////////
//
// WAVE
//

BELL                    WAVE                    "ringin.wav"

メニューの「オプション」項目が無くなり、替わって「色のオプション」項目が増えました。

「色の設定」ダイアログのリソース・スクリプトが増えました。

// clock09.cpp

#define hParentKey HKEY_CURRENT_USER
#define lpszSubKey "Software\\Kumei\\Clock"
#define PAI 3.14159

#define CLOCK_WIDTH 250        //時計全体のウィンドウ幅
#define CLOCK_HEIGHT 60        //高さ
#define MYTIMER 1            //タイマーID
#define MYSTOP 2
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <commctrl.h>
#include <Mmsystem.h>
#include "resource.h"

typedef struct MYDATA {
    COLORREF cr_bg;        //背景色
    COLORREF cr_txt;    //文字色
    COLORREF cr_plate;    //文字盤の色
    COLORREF cr_short;    //短針の色
    COLORREF cr_long;    //長針の色
    COLORREF cr_second;    //秒針の色
    int x;
    int y;
    char szAlarmSet[8];
    char szAlarmTime[16];
    char szTimerTime[16];
    char szStopWatch[8]; //ストップウォッチモードかどうか
    char szStopTime[16]; //ストップウォッチモードの時の時間
} INIDATA;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyAlarmProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyTimerProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyStopWatchProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyColorOptionProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
HFONT SetMyFont(LPCTSTR, int);
void GetInitialSettings(INIDATA *);
BOOL GetDataDWORD(char *, DWORD *);
BOOL GetDataString(char *, char *);
BOOL SetInitialSettings(INIDATA);
BOOL SetDataDWORD(char *, DWORD);
BOOL SetDataString(char *, char *);
BOOL ShowClock(HDC, char *, INIDATA);
BOOL GetHMS(char *, int *, int *, int *);
BOOL ShowBitmap(HDC, INIDATA);
BOOL MyTimerShow(HDC, int, int, INIDATA, DWORD);
BOOL SetHMS(char *, DWORD);
BOOL SetStopHMS(char *, DWORD);

char szClassName[] = "clock09";    //ウィンドウクラス
char szAppName[] = "猫クロック"; //アプリケーション名
HINSTANCE hInst;
色の設定ダイアログのプロシージャ(MyColorOptionProc)が増えました。

GetMyColor関数は無くなりました。

WinMain, InitApp, InitInstanceの各関数に変更はありません。
//ウィンドウプロシージャ

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    int id, x, y;
    SYSTEMTIME st;
    PAINTSTRUCT ps;
    HDC hdc;
    HFONT hFont;
    SIZE s;
    HRGN hRgn, hRgn1, hRgn2, hRound1Rgn, hRound2Rgn, hRectRgn;
    HBRUSH hBrush;
    HMENU hMenu, hSubMenu;
    POINT pt;
    static INIDATA inidata;
    RECT rc;
    char szYobi[8];
    static char szBuf[64], szBuf2[64]; //時刻表示用
    INITCOMMONCONTROLSEX ic;
    static BOOL bTimer; //タイマ表示かどうか
    static DWORD dwStartMs;
    MMTIME mm;

    switch (msg) {
        case WM_CREATE:
            ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
            ic.dwICC = ICC_DATE_CLASSES |
                ICC_TREEVIEW_CLASSES | ICC_BAR_CLASSES;
            InitCommonControlsEx(&ic);
            GetInitialSettings(&inidata);
            MoveWindow(hWnd,
                inidata.x, 
                inidata.y, 
                CLOCK_WIDTH, 
                CLOCK_HEIGHT, 
                TRUE);
            SetTimer(hWnd, MYTIMER, 1000, NULL);

            hRgn = CreateRectRgn(0, 0, 1, 1);
            hRgn1 = CreateRectRgn(0, 0, 1, 1);
            hRgn2 = CreateRectRgn(0, 0,1, 1);

            hRound1Rgn = CreateEllipticRgn(0, 0, CLOCK_HEIGHT, CLOCK_HEIGHT);
            hRectRgn = CreateRectRgn(CLOCK_HEIGHT / 2,
                0, 
                CLOCK_WIDTH - CLOCK_HEIGHT / 2,
                CLOCK_HEIGHT);
            CombineRgn(hRgn1, hRound1Rgn, hRectRgn, RGN_OR);
            hRound2Rgn = CreateEllipticRgn(CLOCK_WIDTH - CLOCK_HEIGHT,
                0,
                CLOCK_WIDTH,
                CLOCK_HEIGHT);
            CombineRgn(hRgn2, hRound2Rgn, hRectRgn, RGN_OR);
            CombineRgn(hRgn, hRgn1, hRgn2, RGN_OR);
            SetWindowRgn(hWnd, hRgn, TRUE);

            DeleteObject(hRound1Rgn);
            DeleteObject(hRound2Rgn);
            DeleteObject(hRectRgn);
            DeleteObject(hRgn1);
            DeleteObject(hRgn2);
            
            break;
        case WM_RBUTTONDOWN:
            pt.x = LOWORD(lp);
            pt.y = HIWORD(lp);
            hMenu = LoadMenu(hInst, "MYMENU");
            hSubMenu = GetSubMenu(hMenu, 0);
            ClientToScreen(hWnd, &pt);
            TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL);
            DestroyMenu(hMenu);
            break;
        case WM_LBUTTONDOWN:
            PostMessage(hWnd, WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lp);
            break;
        case WM_TIMER:
            if (wp != MYTIMER)
                return DefWindowProc(hWnd, msg, wp, lp);
            GetLocalTime(&st);
            wsprintf(szBuf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
            switch (st.wDayOfWeek) {
                case 0:
                    strcpy(szYobi, "Sun");
                    break;
                case 1:
                    strcpy(szYobi, "Mon");
                    break;
                case 2:
                    strcpy(szYobi, "Tue");
                    break;
                case 3:
                    strcpy(szYobi, "Wed");
                    break;
                case 4:
                    strcpy(szYobi, "Thu");
                    break;
                case 5:
                    strcpy(szYobi, "Fri");
                    break;
                case 6:
                    strcpy(szYobi, "Sat");
                    break;
            }

            wsprintf(szBuf2, "%d/%02d/%02d(%s)", st.wYear, st.wMonth, st.wDay, szYobi);
                        
            if (strcmp(inidata.szAlarmSet, "Yes") == 0 && strcmp(szBuf, inidata.szAlarmTime) == 0) {
                PlaySound("BELL", hInst, SND_RESOURCE | SND_ASYNC | SND_LOOP);
                MessageBox(hWnd, "時間ですよ", szAppName, MB_OK);
                PlaySound(NULL, hInst, SND_PURGE);
            }
            InvalidateRect(hWnd, NULL, TRUE);
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            hBrush = CreateSolidBrush(inidata.cr_bg);
            SelectObject(hdc, hBrush);
            PatBlt(hdc, 0, 0, CLOCK_WIDTH, CLOCK_HEIGHT, PATCOPY);
            ShowBitmap(hdc, inidata);

            hFont = SetMyFont("MS ゴシック", 30);
            SelectObject(hdc, hFont);
            GetTextExtentPoint32(hdc, szBuf, (int)strlen(szBuf), &s);
            
            x = (CLOCK_WIDTH - s.cx) / 2 + 4;
            y = (CLOCK_HEIGHT - s.cy) / 2 + 10;
            
            SetBkMode(hdc, TRANSPARENT);
            SetTextColor(hdc, inidata.cr_txt);
            if (strcmp(inidata.szStopWatch, "Yes") == 0) {
                hFont = SetMyFont("MS ゴシック", 24);
                SelectObject(hdc, hFont);
                GetTextExtentPoint32(hdc, szBuf, (int)strlen(inidata.szStopTime), &s);
            
                x = (CLOCK_WIDTH - s.cx) / 2 + 4;
                y = (CLOCK_HEIGHT - s.cy) / 2 + 10;
                TextOut(hdc, x, y, inidata.szStopTime, (int)strlen(inidata.szStopTime));
                DeleteObject(hFont);
            } else {
                hFont = SetMyFont("MS ゴシック", 30);
                SelectObject(hdc, hFont);
                GetTextExtentPoint32(hdc, szBuf, (int)strlen(szBuf), &s);
            
                x = (CLOCK_WIDTH - s.cx) / 2 + 4;
                y = (CLOCK_HEIGHT - s.cy) / 2 + 10;
                TextOut(hdc, x, y, szBuf, (int)strlen(szBuf));
                DeleteObject(hFont);
            }
            

            hFont = SetMyFont("MS ゴシック", 16);
            SelectObject(hdc, hFont);
            GetTextExtentPoint32(hdc, szBuf2, (int)strlen(szBuf2), &s);
            x = (CLOCK_WIDTH - s.cx) / 2 + 4;
            if (!bTimer) {
                TextOut(hdc, x, 4, szBuf2, (int)strlen(szBuf2));
            } else {
                if (MyTimerShow(hdc, x, 4, inidata, dwStartMs)) {
                    bTimer = FALSE;
                    PlaySound("BELL", hInst, SND_RESOURCE | SND_ASYNC | SND_LOOP);
                    MessageBox(hWnd, "時間ですよ", szAppName, MB_OK);
                    PlaySound(NULL, hInst, SND_PURGE);
                }
            }
            DeleteObject(hFont);
            DeleteObject(hBrush);

            ShowClock(hdc, szBuf, inidata);
            
            EndPaint(hWnd, &ps);
            break;
        case WM_COMMAND:
            switch (LOWORD(wp)) {
                case IDM_END:
                    SendMessage(hWnd, WM_CLOSE, 0, 0);
                    break;
                case IDM_ALARMSET:
                    DialogBoxParam(hInst, "MYALARM", hWnd, (DLGPROC)MyAlarmProc, (LPARAM)&inidata);
                    break;
                case IDM_TIMER:
                    if (DialogBoxParam(hInst,
                        "MYTIMER", 
                        hWnd, 
                        (DLGPROC)MyTimerProc, 
                        (LPARAM)&inidata) == IDOK) {
                            bTimer = TRUE;
                            memset(&mm, 0, sizeof(MMTIME));
                            mm.wType = TIME_MS;
                            timeGetSystemTime(&mm, sizeof(MMTIME));
                            dwStartMs = mm.u.ms;
                        } else {
                            bTimer = FALSE;
                        }
                    break;
                case IDM_STOPWATCH:
                    DialogBoxParam(hInst, "MYSTOPWATCH", hWnd, (DLGPROC)MyStopWatchProc, (LPARAM)&inidata);
                    break;
                case IDM_OPTION:
                    DialogBoxParam(hInst, "MYOPTION", hWnd, (DLGPROC)MyColorOptionProc, (LPARAM)&inidata);
                    break;
            }
            break;
        case WM_CLOSE:
            id = MessageBox(hWnd,
                "終了してもよろしいですか",
                szAppName,
                MB_YESNO | MB_ICONQUESTION);
            if (id == IDYES) {
                GetWindowRect(hWnd, &rc);
                inidata.x = rc.left;
                inidata.y = rc.top;
                DestroyWindow(hWnd);
            }
            break;
        case WM_DESTROY:
            SetInitialSettings(inidata);
            KillTimer(hWnd, MYTIMER);
            PostQuitMessage(0);
            break;
        default:
            return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}
メインウィンドウのプロシージャです。

WM_CREATEメッセージが来たときの、コモンコントロールの初期化が少し変更となりました。 (ツリービューを扱うため)

メニュー項目が削減されたため、これに対応していた部分が削除されました。 (IDM_BACKGROUNDからIDM_SECONDまで)

メニュー項目の「色のオプション」(IDM_OPTION)が選択されたときの処理が増えました。 「色の設定」ダイアログを出しますが、例によってDialogBoxParam関数を使って ダイアログのプロシージャにinidata構造体のアドレスを渡しています。

GetMyColor関数は無くなりました。
SetMyFont, GetInitialSettings, GetDataDWORD, GetDataString, SetInitialSettings,
SetDataDWORD, SetDataString, ShowClock, GetHMS, ShowBitmap, MyAlarmProc, MyTimerProc,
MyTimerShow, SetHMS, MyStopWatchProc, SetStopHMSの各関数に変更はありません。
BOOL CALLBACK MyColorOptionProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    static INIDATA *lpini;
    static HWND hTree, hSlider1, hSlider2, hSlider3, 
        hR, hG, hB, hFrame, hPic;
    TVINSERTSTRUCT tv;
    static HTREEITEM hParent;
    HTREEITEM hti;
    static int nPos1, nPos2, nPos3;
    char szBuf[32];
    HBRUSH hBrush;
    HDC hdc_frame;
    RECT rc;
    NMHDR *lpnmhdr;
    TVITEM ti;
    static HTREEITEM hHaikei, hMoji, hMojiBan, hChoshin, hTanshin, hByoshin;
    char szText[256];
    int nR, nG, nB;
    COLORREF crColor;

    switch (msg) {
        case WM_INITDIALOG:
            lpini = (INIDATA *)lp;
            hTree = GetDlgItem(hDlg, IDC_TREE1);
            memset(&tv, 0, sizeof(TVINSERTSTRUCT));
            tv.hInsertAfter = TVI_LAST;
            tv.item.mask = TVIF_TEXT;
            tv.hParent = TVI_ROOT;
            tv.item.pszText = "色の指定";
            hParent = TreeView_InsertItem(hTree, &tv);
            tv.hParent = hParent;
            tv.item.pszText = "背景色";
            hHaikei = TreeView_InsertItem(hTree, &tv);
            tv.item.pszText = "文字色";
            hMoji = TreeView_InsertItem(hTree, &tv);
            tv.item.pszText = "文字盤の色";
            hMojiBan = TreeView_InsertItem(hTree, &tv);
            tv.item.pszText = "長針の色";
            hChoshin = TreeView_InsertItem(hTree, &tv);
            tv.item.pszText = "短針の色";
            hTanshin = TreeView_InsertItem(hTree, &tv);
            tv.item.pszText = "秒針の色";
            hByoshin = TreeView_InsertItem(hTree, &tv);
            hSlider1 = GetDlgItem(hDlg, IDC_SLIDER1);
            hSlider2 = GetDlgItem(hDlg, IDC_SLIDER2);
            hSlider3 = GetDlgItem(hDlg, IDC_SLIDER3);
            hR = GetDlgItem(hDlg, IDC_STATIC1);
            hG = GetDlgItem(hDlg, IDC_STATIC2);
            hB = GetDlgItem(hDlg, IDC_STATIC3);
            hFrame = GetDlgItem(hDlg, IDC_FRAME);
            hPic = GetDlgItem(hDlg, IDC_PIC);
            SendMessage(hSlider1, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELPARAM(0, 255));
            SendMessage(hSlider2, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELPARAM(0, 255));
            SendMessage(hSlider3, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELPARAM(0, 255));
            return TRUE;
        case WM_COMMAND:
            switch (LOWORD(wp)) {
                case IDOK:
                    hti = TreeView_GetSelection(hTree);
                    nPos1 = (int)SendMessage(hSlider1, TBM_GETPOS, 0, 0);
                    nPos2 = (int)SendMessage(hSlider2, TBM_GETPOS, 0, 0);
                    nPos3 = (int)SendMessage(hSlider3, TBM_GETPOS, 0, 0);
                    crColor = RGB(nPos1, nPos2, nPos3);
                    if (hti == hHaikei) {
                        SetDataDWORD("background-color", crColor);
                        lpini->cr_bg = crColor;
                    } else if (hti == hMoji) {
                        SetDataDWORD("text-color", crColor);
                        lpini->cr_txt = crColor;
                    } else if (hti == hMojiBan) {
                        SetDataDWORD("plate-color", crColor);
                        lpini->cr_plate = crColor;
                    } else if (hti == hChoshin){
                        SetDataDWORD("long-color", crColor);
                        lpini->cr_long = crColor;
                    } else if (hti == hTanshin) {
                        SetDataDWORD("short-color", crColor);
                        lpini->cr_short = crColor;
                    } else if (hti == hByoshin) {
                        SetDataDWORD("second-color", crColor);
                        lpini->cr_second = crColor;
                    } else {
                        return FALSE;
                    }
                    return TRUE;
                case IDCANCEL:
                    EndDialog(hDlg, IDCANCEL);
                    return TRUE;
            }
            return FALSE;
        case WM_NOTIFY:
            if (wp != (WPARAM)IDC_TREE1)
                return FALSE;
            lpnmhdr = (NMHDR *)lp;
            if (lpnmhdr->code == TVN_SELCHANGED) {
                memset(&ti, 0, sizeof(TVITEM));
                hti = TreeView_GetSelection(hTree);
                ti.cchTextMax = 255;
                ti.hItem = hti;
                ti.mask = TVIF_TEXT | TVIF_HANDLE;
                ti.pszText = szText;
                TreeView_GetItem(hTree, &ti);
                SetWindowText(hDlg, szText);
                if (hti != hParent) {
                    ShowWindow(hPic, SW_HIDE);
                } else {
                    ShowWindow(hPic, SW_SHOW);
                    return FALSE;
                }
                if (hti == hHaikei) {
                    GetDataDWORD("background-color", &crColor);
                } else if (hti == hMoji) {
                    GetDataDWORD("text-color", &crColor);
                } else if (hti == hMojiBan) {
                    GetDataDWORD("plate-color", &crColor);
                } else if (hti == hChoshin){
                    GetDataDWORD("long-color", &crColor);
                } else if (hti == hTanshin) {
                    GetDataDWORD("short-color", &crColor);
                } else if (hti == hByoshin) {
                    GetDataDWORD("second-color", &crColor);
                } else {
                    return FALSE;
                }
                nR = (int)GetRValue(crColor);
                nG = (int)GetGValue(crColor);
                nB = (int)GetBValue(crColor);
                wsprintf(szBuf, "%03d", nR);
                SetWindowText(hR, szBuf);
                wsprintf(szBuf, "%03d", nG);
                SetWindowText(hG, szBuf);
                wsprintf(szBuf, "%03d", nB);
                SetWindowText(hB, szBuf);
                SendMessage(hSlider1, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)nR);
                SendMessage(hSlider2, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)nG);
                SendMessage(hSlider3, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)nB);

                GetClientRect(hFrame, &rc);
                hBrush = CreateSolidBrush(RGB(nR, nG, nB));
                hdc_frame = GetDC(hFrame);
                SelectObject(hdc_frame, hBrush);
                PatBlt(hdc_frame, 0, 0, rc.right, rc.bottom, PATCOPY); 
                ReleaseDC(hFrame, hdc_frame);
                DeleteObject(hBrush);
            }
            return TRUE;
        case WM_VSCROLL:
            hti = TreeView_GetSelection(hTree);
            nPos1 = (int)SendMessage(hSlider1, TBM_GETPOS, 0, 0);
            wsprintf(szBuf, "%03d", nPos1);
            SetWindowText(hR, szBuf);
            nPos2 = (int)SendMessage(hSlider2, TBM_GETPOS, 0, 0);
            wsprintf(szBuf, "%03d", nPos2);
            SetWindowText(hG, szBuf);
            nPos3 = (int)SendMessage(hSlider3, TBM_GETPOS, 0, 0);
            wsprintf(szBuf, "%03d", nPos3);
            SetWindowText(hB, szBuf);

            GetClientRect(hFrame, &rc);
            hBrush = CreateSolidBrush(RGB(nPos1, nPos2, nPos3));
            hdc_frame = GetDC(hFrame);
            SelectObject(hdc_frame, hBrush);
            PatBlt(hdc_frame, 0, 0, rc.right, rc.bottom, PATCOPY); 
            ReleaseDC(hFrame, hdc_frame);
            DeleteObject(hBrush);
            return TRUE;
    }
    return FALSE;
}
「色の設定」ダイアログのプロシージャです。

WM_INITDIALOGメッセージが来たら、INIDATA構造体のアドレスをstaticな変数にコピーしておきます。

ダイアログボックス上のいろいろなコントロールのウィンドウハンドルを取得しておきます。

トラックバーコントロールの範囲を0から255までに設定しておきます。

「設定」(IDOK)ボタンが押されたら、各トラックバーのつまみ位置を取得します。 この位置がRGB成分の値となります。これらの値からRGBマクロでCOLORREF値を取得します。

次に「OK」ボタンが押されたとき、ツリービューのどのアイテムが選択されていたかを 知る必要があります。

TreeView_GetSelectionマクロの返す値によってINIDATA構造体のどのメンバの値を 変更するかを決めます。この時ついでにレジストリにも書き込んでいます。

WM_NOTIFYメッセージが来たとき、これがツリービュー以外から来たのであれば何もしません。

選択アイテムが変更されたのであれば、そのアイテムの文字列を取得してダイアログボックスの タイトルバーに表示します。ツリービューのアイテムから文字列を取得する方法は忘れやすいので 復習しておいてください(筆者は特に忘れやすい)。

また、選択アイテムが変更されたら、選択されているアイテムに相当するレジストリから 値を読み出して、トラックバーのつまみ位置をこれに合わせます。

また、中央の矩形をその時の色で塗りつぶします。

WM_VSCROLLメッセージが来たら(つまみが動かされたら)すべてのつまみ位置を読み取って これに相当する色で中央の矩形を塗りつぶします。

簡単そうなプログラムですが、作っていくうちにいろいろ問題点が見えてきます。

今回のプログラムでは、猫のビットマップが表示されているとき、このビットマップ上を 適当にクリックすると、クリックした場所にトラックバーなどが存在すると、これが見えてしまい 大変みっともないことになります。この点を改良するにはどうしたらよいでしょうか。 いろいろ工夫してみてください。


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

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