Spin Control(旋转按钮控件、上下微调按钮控件)

摘自:http://blog.csdn.net/zwpzym19790304/article/details/5465898

CSpinButtonCtrl

  CObject

     CCmdTarget

         CWnd

           CSpinButtonCtrl

  一个“旋转按钮控件”(也称为上下控件)是一对箭头按钮,用户点击它们来增加或减小一个值,比如一个滚动位置或显示在相应控件中的一个数字。与一个旋转按钮控件相联系的值被称为它的当前位置。一个旋转控件通常是与一个相伴的控件一起使用的,称为“伙伴窗口”。

  CSpinButtonCtrl类提供了Windows通用旋转按钮控件的功能。这个控件(也就是CSpinButtonCtrl类)只对运行在Windows95Windows NT3.51或更高版本下的程序来说是可用的。

  对用户来说,一个旋转按钮控件和它的伙伴窗口看起来通常就象一个单一的控件。你可以指定一个旋转按钮控件自动将它自己定位在它的伙伴窗口的旁边,并且它自动将它的伙伴窗口的标题设置为它的当前位置。可以将一个旋转按钮控件与一个编辑控件一起使用,以提示用户进行数字输入。

  点击向上箭头使当前位置向最大值方向移动,而点击向下箭头使当前位置向最小值的方向移动。缺省的,最小值是100,最大值是0。任何时候,最小值的设置都大于最大值(例如,当使用缺省值时),点击向上箭头减少位置值,而点击向下箭头则增加它。

  一个没有伙伴窗口的旋转按钮控件就象简化了的滚动条。例如,一个tab控件有时显示一个旋转按钮控件来使它的用户能够滚动其它的tab进入视野。

  #include <afxcmn.h>

  CSpinButtonCtrl类成员:

    1、BOOL SetAccel( int nAccel, UDACCEL* pAccel );

      此成员函数用来设置一个旋转按钮控件的加速(步长/增量)。如果成功则返回非零值;否则返回0。参数nAccel表示由pAccel指定的UDACCEL结构的数目;pAccel指向一个UDACCEL结构数组的指针,该数组包含了加速信息,其结构如下:
        typedef struct{
          UINT nSec;  //位置改变前所等待的秒数
          UINT nInc;  //位置增量。
        }UDACCEL,FAR* LPUDACCEL;

    2、UINT GetAccel( int nAccel, UDACCEL* pAccel ) const;

      获取一个旋转按钮控件的加速(步长/增量)

    3、int SetBase( int nBase );

      此成员函数用来设置一个旋转按钮控件的基数;这个基数值决定了伙伴窗口显示的数字是十进制的还是十六进制的;十六进制的数总是无符号的,十进制的数是有符号的;如果成功则返回先前的基数值,如果给出的是一个无效的基数则返回一个非零值;

    4、UINT GetBase( ) const;

      获取一个旋转按钮控件的基数

    5、CWnd* SetBuddy( CWnd* pWndBuddy );

      此成员函数用来为一个旋转控件设置伙伴窗口。返回值一个指向先前的伙伴窗口的指针。参数pWndBuddy表示指向新的伙伴窗口的指针。

    6、CWnd* GetBuddy( ) const;

      获取指向当前伙伴窗口的指针

    7、int SetPos( int nPos );

      设置一个旋转按钮控件的当前值位置;参数nPos表示控件的值位置,这个值必须在控件的上限和下限指定的范围之内;

    8、int GetPos( ) const;

      获取旋转按钮控件的当前值位置

    9、void SetRange( int nLower, int nUpper );  void SetRange32( int nLower, int nUpper );

      设置旋转按钮控件的数值范围;参数nLower和nUpper表示值的上限和下限;SetRange32为此旋转按钮控件设置32位的范围。

    10、void GetRange( int &lower, int& upper ) const;  void GetRange32( int &lower, int &upper ) const;

      获取旋转按钮控件的数值范围

     

  示例

  1)建立一个mfc对话框类工程,名称为SpinTest1

  2)在对话框窗口里加入一个Edit(ID号为IDC_EDIT_VALUE)和一个spin(ID号为IDC_SPIN01)控件,要按照先Edit后Spin的顺序添加控件,使该Spin控件的Tab顺序紧随要合作的Edit控件之后

  IDC_SPIN01控件建一个关联变量m_spin

3)修改Spin控件的属性:

  Auto Buddy 为 true
    Set Buddy Integer 为 true
    Alignment 为 Right Align

  Arrow keys 为 true

  4)CSpinTest1Dlg类的OnInitDialog()里添加下面代码

          m_spin.SetBuddy((CWnd *)GetDlgItem(IDC_EDIT_VALUE)); //将两个控件关联,若Spin控件的Tab顺序紧随Edit控件之后并设置了Auto Buddy,这句可省略

      m_spin.SetRange(1900,2000);  //设置控件的数值范围

      pSpin->SetBase(10);  //设置基数,进制或者进制显示

      //设置控件的加速(步长/增量)

      UDACCEL accel;

      accel.nSec=0;
      accel.nInc=1;
      m_spin.SetAccel(1,&accel);

  5)你可以根据需要为Edit控件设定一个初始值,这样这个spin控件就基本可以使用了

 

说明:

    有关这个控件,我在网上查了很多的资料,结果都说的很复杂,例如,在没有设定SetRange()范围之前,如何运行程序,会发现点击向上键头的按钮,数值是减少的,反之是增加的,这个问题网上有人还专门用了一个OnDeltaPos*()函数来解决,而我通过实践证明,只要设定了范围,就可以校正这个问题(当然这个只适用于数值数据的方面),网上还有有关点击了按钮之后在edit控件里显示字符的程序,如果做这样的程序可能会用到OnDeltaPos*()函数,下面我引用一下有关这个函数的添加方法:  

    旋转按钮控件的通知消息只有一个:UDN_DELTAPOS,它表示控件的位置将要改变。

    用ClassWizard可以映射此消息,在此消息的处理函数中有个NM_UPDOWN结构需要进行说明,其结构如下:

        typedef struct _NM_UPDOWN{

              NMHDR hdr; //通知代码的其他信息

              int iPos; //当前位置

              int iDelta; //位置的增减量,单击向上箭头此值为负数

         }NMUPDOWN,FAR* LPNMUPDOWN;

    应用实例:用Spin控件完成对字符的增减

      响应UDN_DELTAPOS消息

      将会多出如下函数

      void CTestDlg::OnDeltaposSpin3(NMHDR* pNMHDR, LRESULT* pResult)

      {

        NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;

        if(pNMUpDown->iDelta == 1)        // 如果此值为1 , 说明点击了Spin的往下箭头

        {

          //对字符做相关处理 , 例如将"a" 变为 "b"

        }

        else if(pNMUpDown->iDelta == -1) // 如果此值为-1 , 说明点击了Spin的往上箭头

        {

          //对字符做相关处理 , 例如将"b" 变为 "a"

        }

        *pResult = 0;

      }

    详细做法:

      1)假设你编辑框为IDC_EDIT , SPIN按钮为IDC_SPIN .

      2)Ctrl + W , 进入Class Wizard , Object IDs列选择IDC_SPIN , Messages列选择UDN_DELTAPOS , 点击"Add Function" 按钮.将弹出"OnDeltaposSpin"的对话框 ,OK 添加这个函数.然后点"Edit Code" , 进入新添加的函数里

      3)将会新添加一个函数.

        void CTestDlg::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult) . . .

      4)添加如下代码

        void CTestDlg::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult)

        {

          NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;

          CWnd* pWnd = (CWnd*)GetDlgItem(IDC_EDIT);    //得到指向编辑框的窗口指针

          CString strValue ;

          pWnd->GetWindowText(strValue);                 //得到编辑框中的内容

          if(pNMUpDown->iDelta == 1)                    //如果点击的是Spin中的往上按钮

          {

            if(!strValue.IsEmpty())

            {

              strValue.SetAt(0 , strValue[0] + 1);   //编辑框首字母加1

               pWnd->SetWindowText(strValue);         //保存修改

            }

          }

          else if(pNMUpDown->iDelta == - 1)    //如果点击的是Spin中往下按钮

          {

            if(!strValue.IsEmpty())

            {

              strValue.SetAt(0 , strValue[0] - 1);   //编辑框首字母减1

              pWnd->SetWindowText(strValue);         //保存修改

            }

          }

          *pResult = 0;

        }

      使用上述做法,后来遇到一个问题:当一直按住上或者下时,增大16个后就不再增大,后来发现,将条件改成大于0和小于0就可以了,大于0表示向上按钮。

 

  特别注意:

    若要使用响应函数 void CTestDlg::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult) 来定制Edit控件中显示的类容(如小数),则Spin控件的属性Auto Buddy必须为FALSE,且无需只用SetBuddy来绑定俩个控件,只需保证Edit控件的Tab顺序在Spin控件之前

原文地址:https://www.cnblogs.com/zhouwanqiu/p/6927710.html