Topic : Common Controls
Author : Unknown
Page : << Previous 2  Next >>
Go to page :

the proposed change on spin's position. We can calculate the new position of the spin control by adding up these two members.

The following function shows how the buddy's text is set after receiving the message:

(Code omitted)

The buddy's text is set by calling function CWnd::SetWindowText(...). Here variable szNumber is a two- dimensional character array which stores strings "Zero", "One", "Two"..."Nine". First we calculate the current position of the spin control and store the result in an integer type variable nNewPos. Then we use it as an index to table szNumber, find the appropriate string, and use it to set the text of the edit control.

In dialog box's initialization stage, we need to set the range and position of the spin control. Since the edit box will display nothing by default, we also need to set its initial text:

(Code omitted)

With the above implementation, the spin's buddy control will display text instead of numbers.

4 Bitmap Button Buddy

String text is not the only appearance a buddy control can have. We can also implement a buddy that displays bitmaps. Because bitmap button can be easily implemented to display images, we can use it to implement spin's buddy control rather than using edit box.

Sample 4\CCtl demonstrates how to implement bitmap button buddy. It is based on sample 3\CCtl, with a new spin control IDC_SPIN_BMP and a new bitmap button IDC_BUTTON_BMP added to the application.

The procedure of creating a bitmap button buddy is almost the same with creating an edit box buddy. The only difference here is that instead of creating an edit box resource, we need to add a button resource, and set its "Owner draw" style.

In the sample, four bitmaps are prepared to implement the bitmap button. All of them have integer resource IDs, which are listed as follows: IDB_BITMAP_SMILE_1, IDB_BITMAP_SMILE_2, IDB_BITMAP_SMILE_3, IDB_BITMAP_SMILE_4.

A CBitmapButton type variable is declared in class CCCtlDlg. In the dialog box's initialization stage, functions CWnd::SubclassDlgItem(...), CBitmapButton::LoadBitmaps(...) and CBitmapButton:: SizeToContent() are called to initialize the bitmap button. Also, the range of the spin control is set from 0 to 3, and its initial position is set to 0:

(Code omitted)

The initially selected bitmap is IDC_BITMAP_SMILE_1. We should not load bitmaps for other states ("down", "focused" and "disabled") because the purpose of this button is to display images rather than executing commands. We need to change the currently loaded image upon receiving UDN_DELTAPOS notification. To change button's associated bitmap, in the sample application, a UDN_DELTAPOS message handler is added for IDC_SPIN_BMP, which is implemented as follows:

(Code omitted)

Although we say that the bitmap button is the buddy of the spin control, in the above implementation we see that they do not have special relationship. A spin control needs a buddy only in the case when we want the text in the buddy window to be updated automatically. If we implement this in UDN_DELTAPOS message handler, the buddy loses its meaning because we can actually set text for any control. Although this is true, here we still treat the bitmap button as the buddy of spin control because the bitmap button is under the control of the spin.

5 Slider

A slider is a control that allows the user to select a value from pre-defined range using mouse or keyboard. A slider can be customized to have many different styles: we can put tick marks on it, set its starting and ending ranges, make the tick marks distributed linearly or non-linearly. Besides these attributes, we can also set the line size and page size of a slider, which decide the minimum distance the slider moves when the user clicks mouse on slider's rail or hit arrow keys of the keyboard.

Including Slider Control in the Application

Sample 5\CCtl demonstrates how to use the slider control. It is a standard dialog based application generated by the Application Wizard. In the dialog box, three different sliders are implemented, they are used to show how to set tick marks, page size, line size, and implement other customizations.

The tick marks can be added to the slider automatically. When we add a slider resource to the dialog template, we can find two check boxes, "Tick mark" and "Auto ticks", in the property page that lets us customize slider's properties (Figure 4). If we check the former check box, the slider will be able to have tick marks, if we check the latter, tick marks will be added automatically.

(Figure 4 omitted)

In MFC, slider can be implemented through using class CSliderCtrl. We need to call its member functions in order to customize the slider.

To let the tick marks be set automatically, besides setting "Tick mark" and "Auto ticks" styles, we must also specify slider's range. A slider's range can be set by calling either function CSliderCtrl:: SetRange(...) alone or CSliderCtrl::SetRangeMin(...) together with CSliderCtrl::SetRangeMax(...)in the dialog box's initialization stage. The format of the above three functions are listed as follows:

void CSliderCtrl::SetRange(int nMin, int nMax, BOOL bRedraw = FALSE);

void CSliderCtrl::SetRangeMax (int nMax, BOOL bRedraw = FALSE);

void CSliderCtrl::SetRangeMin(int nMin, BOOL bRedraw = FALSE);

By default, the distance between two neighboring tick marks is 1. To change this, we may call function CSliderCtrl::SetTicFreq(...) to set the frequency of the tic marks. If the slider does not have "Auto ticks" style, we must call function CSliderCtrl::SetTic(...) to set tick marks for the slider. Because this function allows us to specify the position of a tic mark, we can use it to set non-linearly distributed tic marks.

Two other properties that can be modified are slider's page size and line size. Here, page size represents the distance the slider will move after the user clicks mouse on its rail. The line size represents the distance the slider will move if the user hits left arrow or right arrow key when the slider has the current focus (Figure 5). Two member functions of class CSliderCtrl can be used to set the above two sizes: CSliderCtrl::SetPageSize(...) and CSliderCtrl::SetLineSize(...). The default page size is 1/5 of the total slider range and the default line size is 1.

In sample 5\CCtl, there are three sliders, whose IDs are IDC_SLIDER_AUTOTICK, IDC_SLIDER_TICK and IDC_SLIDER_SEL respectively. Here, slider IDC_SLIDER_AUTOTICK has "Tick marks" and "Auto ticks" styles, slider IDC_SLIDER_TICK has only one "Tick marks" style, and slider IDC_SLIDER_SEL has "Tick marks", "Auto ticks", and "Enable selection" styles.

Three sliders are initialized in function CCCtlDlg::OnInitDialog(). The following portion of this function sets the range, tick marks, page size and line size for each slider:

(Code omitted)

Since slider IDC_SLIDER_AUTOTICK has "Auto ticks" style, we don't need to set the tick marks. In the sample, the range of this slider is set from 0 to 10, and the tick mark frequency is set to 2. The tick marks will appear at 0, 2, 4, 6... 10. Also, since no page size and line size are specified here, they will be set to the default values (2 and 1). For IDC_SLIDER_TICK, its range is set from 0 to 50, and function CSliderCtrl::SetTic(...) is called to set non-linearly distributed tick marks. Here, a loop is used to set all the tick marks, which will appear at 0, 4, 8, 16.... Slider IDC_SLIDER_SEL also has "Auto ticks" style, its range is set from 50 to 100, page size set to 40 and line size set to 10. This slider also has "Enable selection" style, and function CSliderCtrl::SetSelection(...) is called to draw a selection on the slider's rail. The range of the selection is from 60 to 90.

Handling Slider Related Messages

Another feature we want to add to the application is trapping events generated by the sliders. When a slider moves, we may want to know its current position and make changes to other settings. For example, in a multimedia application, we can use slider to control the volume of speakers.

In Windows( system, there is no special message defined for the slider. Instead, a slider shares same messages with scroll bar. For horizontal sliders, we need to trap WM_HSCROLL message; for vertical sliders, we need to trap WM_VSCROLL message.

Similar to UDN_DELTAPOS message, in a dialog box, message WM_HSCROLL or WM_VSCROLL can be added through using Class Wizard. The default message handler for WM_HSCROLL will look like this:

void CCCtlDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)


CDialog::OnHScroll(nSBCode, nPos, pScrollBar);


There are three parameters in this function. The first parameter nSBCode indicates user's scrolling request, which includes left-scroll, right-scroll, left-page-scroll, right-page-scroll, etc. If we want to customize the behavior of a slider, we need to check this parameter. Parameter nPos is used to specify the current slider's position under some situations (it is not valid all the time). The third parameter pScrollBar is a window pointer to slider or scroll bar control. We can use it to check which slider is being changed, then make the corresponding response. The slider's current position can be obtained by calling function CSliderCtrl::GetPos(). In the sample application, since all sliders are horizontal, only WM_HSCROLL message is handled:

(Code omitted)

Function CWnd::GetDlgCtrlID() is called to retrieve the control ID of the slider. We use this ID to call function CWnd::GetDlgItem(...) and get the address of slider control. If the control happens to

Page : << Previous 2  Next >>