アップダウンコントロール(スピンコントロール)

アップダウンコントロール

今回は、ダイアログボックスにアップダウンコントロール(スピンコントロール)を付けます。 アップダウンを押せば、エディットに入力した数字が1ずつ増減します。

アップダウンコントロールは、すぐ左隣のエディットコントロールとセットで使われます。

アップダウンコントロールは、スクロールバーに似た矢印の部分だけです。
その左側は、ただのエディトコントロールです。

テキストの表示 - インコのWindowsSDK で作成したソースを修正します。

ここでは、Reseditで作成する方法も説明します。

流れ

1、アップダウンコントロールを使用するため、commctrl.hをインクルード

2、_stprintf_s()を使用するため、stdio.h、tchar.hをインクルード

3、_ttoi()を使用するため、stdlib.h、tchar.hをインクルード

WM_INITDIALOG

1.InitCommonControls()でコモンコントロールの初期化

2.現在のエディットコントロールに表示する数字を、変数szBuf_edit1に格納。

3.SetDlgItemText()でエディットにデータセット。

4.UDM_SETBUDDYメッセージで、アップダウンコントロールと関連付けるコントロール(ここでは、エディットコントロール)を指定します。

lResult = SendMessage(
    (HWND) hWnd,        // アップダウンコントロールのハンドル
    (UINT) UDM_SETBUDDY,
    (WPARAM) wParam,    // 関連付けるコントロールのハンドル
    0                   // 0固定
);

WM_NOTIFY

1.アップダウンコントロールが押された時、UDN_DELTAPOSメッセージが発生します。

UDN_DELTAPOSメッセージは、WM_NOTIFYメッセージ形式です。
WM_NOTIFYメッセージは、コモンコントロールでイベントが起こった場合、およびコモンコントロールが情報を親ウィンドウに要求する場合に、コモンコントロールの親ウィンドウに送信されます。

WM_NOTIFYメッセージ発生時の wParam [コールバック関数の第3引数]の値 イベントが発生したコモンコントロールのコントロールID
このときのwParamは、アップダウンコントロールのIDになります。
WM_NOTIFYメッセージ発生時の lParam [コールバック関数の第4引数]の値 NMHDR構造体、あるいはNMHDR構造体を最初のメンバに持つ構造体のアドレス
このときのlParamは、NMUPDOWN構造体になります。
NMUPDOWN構造体の最初のメンバが、NMHDR構造体です。 NMHDR構造体のcodeメンバが「通知コード」です。通知コードは、ここでは、UDN_DELTAPOSメッセージになります。
typedef struct _NM_UPDOWN {
    NMHDR  hdr;   // NMHDR構造体
    int iPos;     // カレントポジション
    int iDelta;   // ポジションの変化量
} NMUPDOWN, FAR *LPNMUPDOWN;

hdrNMHDR構造体
iPosカレントポジション
iDelta ポジションの変化量
上矢印が押された場合は負の値が、下矢印が押された場合は正の値が入ります。 逆向きですので注意してください。

2.UDN_DELTAPOSメッセージが発生していれば、 GetDlgItemText()でエディットからデータを取得

3.取得した文字列型の変数szBuf_edit1を、_ttoi()または、_tstoi()で、整数型変数nNoに変換。

_ttoi()、_tstoi()の引数に文字列を入れてください。この関数の戻り値は整数です。

_ttoi()と_tstoi()は、unicodeでコンパイルしたときは、_wtoi()になり、マルチバイトでコンパイルしたときは、atoi()になります。

4.NMUPDOWN構造体のメンバiDeltaは、上矢印(▲)が押された場合は負の値が、下矢印(▼)が押された場合は正の値になるので、整数型変数nNoを増減させます。

UDS_HORZスタイルの指定で、上下矢印を左右矢印に変えた場合は、左矢印は下矢印と同じで、右矢印は上矢印と同じになります。

5.整数型変数nNoを、変数szBuf_edit1に格納。

6.SetDlgItemText()でエディットにデータセット。

リソースファイル

1.アップダウンコントロールを使用するため、commctrl.hをインクルード。

2.ダイアログボックスにアップダウンコントロール[UPDOWN_CLASS]を追加。

UPDOWN_CLASSの代わりに、"msctls_updown32"と記述することができます。「" "」を忘れないで下さい。
この場合は、リソースファイルで、commctrl.hをインクルードする必要はありません。
ただし、"msctls_updown32"と記述した場合でも、Cソースファイルでは、commctrl.hのインクルードが必要です。

CONTROL          "", id, UPDOWN_CLASS, style, x0, y0, width, height

idコントロールID
style スタイル
ウインドウスタイルと、 アップダウンコントロールのスタイルが指定可能。
アップダウンコントロールのスタイル
UDS_ALIGNLEFT アップダウンコントロールを関連ウィンドウの左に配置。
UDS_ALIGNRIGHT アップダウンコントロールを関連ウィンドウの右に配置。
UDS_ARROWKEYS アップダウンコントロールの▲▼キーで値を増減。
UDS_AUTOBUDDY コントロールの表示順序(Zオーダ、Z順)で直前となるウィンドウを、アップダウンコントロールの関連ウィンドウとして自動的に選択。
UDS_HORZ アップダウンコントロールの矢印が左右。
UDS_NOTHOUSANDS 関連ウィンドウの値に、桁区切り記号が挿入されないようにします。
UDS_WRAP 上限、下限を超えて増減された場合、値の位置を折り返します。
x0アップダウンコントロール左上のx座標
y0アップダウンコントロール左上のy座標
widthアップダウンコントロールの幅
heightアップダウンコントロールの高さ

ここでは、UDS_AUTOBUDDYスタイルを選択して、直前のエディットコントロールと関連付けます。

アップダウンコントロール

3.ダイアログボックスにエディトを追加

ソースコードの入力

ソースコードは下記のように入れてください。

test.cpp
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include "resource.h"

#pragma comment(lib, "comctl32.lib")

// グローバル変数:
TCHAR szBuf_edit1[1024];

// このコード モジュールに含まれる関数の宣言を転送します:
BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          PSTR lpCmdLine, int nCmdShow )
{
    DialogBox(hInstance, TEXT("DIALOG_BOX"), NULL, DialogProc);
    return 0;
}

BOOL CALLBACK DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static int nNo = 1;    // エディトに表示する数字
    LPNMUPDOWN lpnmud;     // NMUPDOWN構造体
    switch (msg)
    {
        case WM_INITDIALOG:
            InitCommonControls();
            _stprintf_s(szBuf_edit1, 10, TEXT("%d"), nNo);
            SetDlgItemText(hWnd, IDC_EDIT1, (LPCTSTR)szBuf_edit1); 
            SendMessage(GetDlgItem(hWnd, IDC_SPIN1), UDM_SETBUDDY,
                                      (WPARAM)GetDlgItem(hWnd, IDC_EDIT1), 0);
            break;
        case WM_CLOSE:
            EndDialog(hWnd, IDOK);
            break;
        case WM_NOTIFY:
            if (wParam == (WPARAM)IDC_SPIN1)
            {
                lpnmud = (LPNMUPDOWN)lParam;
                if(lpnmud->hdr.code == UDN_DELTAPOS)
                {
                    GetDlgItemText(hWnd, IDC_EDIT1,
                      (LPTSTR)szBuf_edit1, (int)sizeof(szBuf_edit1));
                    nNo = _ttoi(szBuf_edit1);
                    if((lpnmud->iDelta) < 0)
                    {
                        nNo++;
                    }
                    else if((lpnmud->iDelta) > 0)
                    {
                        nNo -= 1;
                    }
                    _stprintf_s(szBuf_edit1, 10, TEXT("%d"), nNo);
                    SetDlgItemText(hWnd, IDC_EDIT1, (LPCTSTR)szBuf_edit1); 
                }
            }
            break;
        return TRUE;
    }
    return FALSE;
}

resource.h

#define IDC_EDIT1 1001
#define IDC_SPIN1 1002
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif

Reseditで作成した場合は、これとは異なるソースコードになります。
上記の太線で示している箇所のみ追加です。

test.rc

#include <windows.h>
#include <commctrl.h>
#include "resource.h"

/////////////////////////////////////////////////////////////////////////////
//
// ダイアログ
//

DIALOG_BOX DIALOG 0, 0, 170, 62
FONT 9, "MS UI Gothic"
CAPTION "ダイアログ"
BEGIN
    CONTROL         "", IDC_SPIN1, UPDOWN_CLASS, UDS_ARROWKEYS, 63, 23, 10, 19
    EDITTEXT        IDC_EDIT1, 34, 24, 29, 17, ES_AUTOHSCROLL
END

Reseditで作成した場合は、これとは異なるソースコードになります。
上記の太線で示している箇所のみ追加です。