Are you having trouble using the CSpinButtonCtrl in MFC?
Then what kind of trouble are you going through?

In my case, I was having trouble with setting the range of the spin button control. I needed to set the range from 0 to 0xFFFF. The default range of CSpinButtonCtrl is from 0 to 100. And the range can be modified by using the SetRange method. However, the range must be defined within the range -0x8000~0x7FFF inclusive.  Moreover, if I remember correctly, the difference between the max and min of the range must not exceed 0x7FFF. I am pretty sure that not many people would have been happy with this limitation. To overcome this limitation, I guess Microsoft added a method called SetRange32 for the CSpinButtonCtrl. The SetRange32 method has no limits on setting the range within the 32 bit integer range. But does this mean that there absolutely no limitations on using the CSpinButtonCtrl within the 32 bit integer range?
No !!!
I believe another method frequently used in CSpinButtonCtrl among with SetRange is SetPos and GetPos method. Now comes the funny part. Even though you set the range for the CSpinButtonCtrl with SetRange32 method, SetPos and GetPos operates properly within the 12 bit interger range, which is -0x8000~0x7FFF.

After some research I found out that you can get and set the position of the CSpinButtonCtrl by sending UDM_SETPOS32 and UDM_GETPOS32 message to the CSpinButtonCtrl object. So the code will become something like the following...

// Assume that the control ID of the CSpinButtonCtrl is IDC_SPIN
CSpinButtonCtrl spinButtonCtrl;
// set range
spinButtonCtrl.SetRange32(0, 0xFFFF);

// 1. how to set position
// nPos is the new position
// (valid position within the range specified above)
GetDlgItem(IDC_SPIN)->SendMessage(UDM_SETPOS32, 0, nPos);
//2. how to get position
int pos = GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETPOS32, 0, NULL);

The requirements for being able to do this is having comctl.dll version 5.8 or later and commctrl.h. I figured out that the version of my comctl.dll is 5.82. But I had some problems with commctrl.h. At the moment, I have two versions of Visual Studio. Version 6.0 and 2005. The commctrl.h that Visual Studio 2005 refers to has the following lines.

#define UDM_SETPOS32 (WM_USER+113)
#define UDM_GETPOS32 (WM_USER+114)

On the otherhand, the commctrl.h that Visual Studio 6.0 refers to does not define the messages UDM_SETPOS32 and UDM_GETPOS32.

Knowing that the value defined for UDM_GETRANGE32 is WM_USER+112, here is what I did...

// 1. how to set position
// nPos is the new position
// (valid position within the range specified above)
GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETRANGE32+1, 0, nPos);
//2. how to get position
int pos = GetDlgItem(IDC_SPIN)->SendMessage(UDM_GETRANGE32+2, 0, NULL);


On second thought I decided to define my two messages on my own. So I added the two lines that were absent in my commctrl.h in my source code and used UDM_SETPOS32 and UDM_GETPOS32 where I actually send the message to the CSpinButtonCtrl in the code.

On the third thought, I had a better idea. I created my own class derived from CSpinButtonCtrl called CSpinButtonCtrl32. I defined SetPos and GetPos method in the following manner.

#define UDM_SETPOS32 (WM_USER+113)
#define UDM_GETPOS32 (WM_USER+114)

int CSpinButtonCtrl32::SetPos(int nPos)
{
    int prevPos = this->SendMessage(UDM_GETPOS32, 0, NULL);
    this->SendMessage(UDM_SETPOS32, 0, nPos);
    return prevPos;
}

int CSpinButtonCtrl32::GetPos()
{
    return this->SendMessage(UDM_GETPOS32, 0, NULL);
}

And everthing worked just as I wanted. Spin Button Control without much limitations on setting the range and setting/getting the position.


Posted by Dansoonie