Home

Windows Controls: The Command/Push Button

 

Introduction to the Button

 

Overview

 

A Button is a Windows control used to initiate an action. From the user's standpoint, a button is useful when clicked, in which case the user positions the mouse on it and presses one of the mouse's buttons.

There are various kinds of buttons. The most common and regularly used is a rectangular object that the user can easily recognize. In some programming environments, this classic type is called a command button. There are other controls that can serve as click controls and initiate the same behavior as if a button were clicked.

From the programmer's standpoint, a button needs a host, such as a dialog box.

Creating a Push Button

To visually add a button to a dialog box, in the Toolbox, click Button Button and click the desired location on the dialog box. By default, when you visually create a dialog box, Microsoft Visual C++ adds two buttons: OK and Cancel. If you don't need these buttons, click one and press Delete.

The most popular button used in Windows applications is a rectangular control that displays a word or a short sentence that directs the user to access, dismiss, or initiate an action or a suite of actions. In Microsoft Visual C++ applications, this control is implemented using the Button control from the Toolbox window.

In the MFC, a button is based on the CButton class, which is derived from CWnd. Therefore, to programmatically get a button, you can create a pointer to CButton and initialize it using the new operator.

Characteristics of a Command Button

 

Introduction

Like every Windows control, a button is recognized by its IDentifier. Because a button is a control, by convention, its identifier's name starts with IDC (the C stands for Control).

If you want to programmatically access the properties of a control without using an associated variable, you may have to call the CWnd::GetDlgItem() member function. It comes in two versions as follows:

CWnd* GetDlgItem(int nID) const;
void CWnd::GetDlgItem(int nID, HWND* phWnd) const;

When calling this member function, the first version allows you to assign a CWnd (or derived class) to it. The second version returns a handle to the window passed as pointer. In both cases, you must pass the identifier of the control that you want to access. When using the first version, if the control is not a CWnd object, you must cast it to its native class. Then you can manipulate the property (or properties) of your choice. Here is an example that accesses a button and changes its caption:

BOOL CDialog5Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here

    CButton *btnWhatElse = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON3));

    return TRUE; // return TRUE unless you set the focus to a control
}

The second version requires a pointer to a child window that you want to access.

Showing or Hiding a Button

After creating a control, to visually make sure that it displays when its host control comes up, set its Visible property to True. Otherwise, if you want it to be hidden for example to wait for an intermediary action from the user, you can set its Visible property to False.

To programmatically display a control such as a button, whether it is hidden or not, call the CWnd::ShowWindow() member function and pass SW_SHOW as its argument. Here is an example:

BOOL CDialog5Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here
    m_Submit.ShowWindow(SW_SHOW);
    return TRUE; // return TRUE unless you set the focus to a control
}

In the same way, to hide a button or any control, call its ShowWindow() member function and pass the SW_HIDE constant as argument.

Enabling or Disabling a Button

For the user to be able to use a control such as clicking a button, the control must allow it. This characteristic of Windows objects is controlled by the CWnd::EnableWindow() member function. Its syntax is:

BOOL EnableWindow(BOOL bEnable = TRUE);

This member function is used to enable or disable a control. The default value of the argument bEnable is set to TRUE, which would display a control. To disable a control, set the argument to FALSE. Here is an example:

void CDialog5Dlg::OnLetItBe()
{
    // TODO: Add your control notification handler code here
    m_Submit.EnableWindow(FALSE);
}

The Caption of a Command Button

From the user's point of view, the only things important about a button are the message it displays and the action it performs. The word or sentence that displays on top of a button is its caption. By default, after adding a button to a form, the Caption property has focus. Therefore, if you start typing, the caption would be changed. At design time, you can set the caption with the necessary string on the Caption field of the Properties window.

At run time, to programmatically change the caption of a button or of any control that displays a caption, call the CWnd::SetWindowText() member function and pass it the necessary string as argument. Here is an example:

BOOL CDialog5Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here
    m_Submit.SetWindowText("Submit");

    return TRUE; // return TRUE unless you set the focus to a control
}

The OK and Cancel Buttons

The most popular button captions in dialog boxes are OK and Cancel. The OK caption is set for a dialog box that informs the user of an error, an intermediary situation, or an acknowledgement of an action that was performed on the dialog that hosts the button. Microsoft Visual C++ makes it easy to add an OK button because in Windows applications, the OK object has a special meaning.

To use an OK button, add a button to a form and, from the ID combo box, select the IDOK identifier:

IDOK

What makes this constant special is that the MFC library recognizes that, when the user clicks it, if the dialog box is modal, the user is acknowledging the situation. If this dialog box was called from another window using the DoModal() member function, you can find out if the user had clicked OK and then you can take further action. Therefore, when the user clicks OK, the dialog box calls the OnOK() member function. Its syntax is:

virtual void OnOK();

Although it looks like a simple member function (and it is), the OnOK() member function carries the constant value IDOK that you can use as a return value of the DoModal() member function. Therefore, in one step, you can use the DoModal() member function to display a modal dialog box and find out whether the user clicked OK.

When a dialog box is equipped with an OK button, you should allow the user to press Enter and perform the OK clicking. This is taken care of by setting the Default Button property to True or checked.

The Cancel caption is useful on a button whose parent (the dialog box) would ask a question or request a follow-up action from the user. A Cancel button is also easy to create by simply adding a button to a dialog box and selecting IDCANCEL as its identifier in the ID combo box. Setting a button's identifier to IDCANCEL also allows the user to press Esc to dismiss the dialog box.

The scenarios described for the OK and the Cancel buttons are made possible only if the compiler is able to check or validate the changes made on a dialog box. To make this validation possible, in your class, you must overload the CWnd::DoDataExchange() member function. Its syntax is:

virtual void DoDataExchange(CDataExchange* pDX);

This member function is used internally by the application (the framework) to find out if data on a dialog box has been changed since the object was displayed. This member function does two things: It ensures the exchange of data among controls and it validates the values of those controls. In reality, it does not inherently perform data validation, meaning it would not allow or disallow value on a control. Instead, the compiler uses it to create a table of the controls on the dialog box, their variables and values, allowing other controls to refer to it for data exchange and validation. If you want to find out the data a user would have typed or selected in a control, you would have to write the necessary code.

 
 
 

Caption Alignment

By default, the caption on a button is positioned in the middle and the center of the control. At design time, you can control this position using the Horizontal and the Vertical Alignments on the Properties window:

Button Button Button
Horizontal Alignment: Left
Vertical Alignment: Top
Horizontal Alignment: Default or Center
Vertical Alignment: Top
Horizontal Alignment: Right
Vertical Alignment: Top
Button Button Button
Horizontal Alignment: Left
Vertical Alignment: Default or Center
Horizontal Alignment: Default or Center
Vertical Alignment: Default or Center
Horizontal Alignment: Right
Vertical Alignment: Default or Center
Button Button Button
Horizontal Alignment: Left
Vertical Alignment: Bottom
Horizontal Alignment: Default or Center
Vertical Alignment: Bottom
Horizontal Alignment: Right
Vertical Alignment: Bottom

A Button's Messages

The most regular action users perform on a button is to click it. When a user does this, the button sends a BN_CLICKED message. In some but rare circumstances, you may also ask the user to double-click a button. Over all, you will take care of most message handling when the user clicks a button. There are other messages that you can handle through a button.

To close a dialog box, you can use the Win32 API's PostQuitMessage() function. Its syntax is:

VOID PostQuitMessage(int nExitCode);

This function takes one argument, which is an integer. The argument could be set to almost any integer value although it should be WM_QUIT. Here is an example:

void CDialog5Dlg::OnBtnClose()
{
    // TODO: Add your control notification handler code here
    PostQuitMessage(125);
}

Although the MFC library provides enough messages associated with the various controls, in some circumstances you will need use a message that is not necessarily associated with the control. In such a case, you can call the CWnd::SendMessage() member function. Its syntax is:

LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0);

The first argument of this member function can be a Win32 message or constant. Examples would be WM_CLOSE or WM_ACTIVATE. The wParam and lParam arguments can be additional (Win32) messages.

The WinExec() function is used to run an application. Its syntax is:

UINT WinExec(LPCSTR lpCmdLine, UINT uCmdShow);

The lpCmdLine argument specifies the name or path of the application you want to display. The uCmdShow specifies how the application should be displayed. It uses the same values as the CWnd::ShowWindow() member function.

Practical LearningPractical Learning: Using Buttons

  1. To create a new application, on the main menu, click File -> New Project...
  2. Click MFC Application and set the name to AppLauncher1
  3. Click OK
  4. In the first page of the MFC Application Wizard, click Next
  5. In the second page, click Dialog Based
  6. Click Next
  7. In the third page, set the Title Name to Application Launcher
  8. Click Next
  9. Click Finish
  10. On the dialog, click the TODO line and press Delete
  11. As the OK button is selected, press Delete
  12. As the Cancel button is selected, press Delete
  13. In the Toolbox, click the Button control Button and click the lower section of the dialog box
     
    Button Design
  14.  In the Properties window, click ID and type IDC_CLOSE_BTN
  15. On the dialog box, right-click the button and click Add Variable...
  16. In the Access combo box, select private
  17. In the Variable Name, type m_BtnClose
     
    Add Member Variable
  18.  Click Finish
  19. In the Class View, expand the project. In the upper part of the Class View, click CAppLauncher1
  20. In the lower part of the Class View, double-click OnInitDialog()
  21. Set the caption of the button to "Close" as follows:
    BOOL CAppLauncher1Dlg::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        // Add "About..." menu item to system menu.
    
        // IDM_ABOUTBOX must be in the system command range.
        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
        ASSERT(IDM_ABOUTBOX < 0xF000);
    
        CMenu* pSysMenu = GetSystemMenu(FALSE);
        if (pSysMenu != NULL)
        {
    	BOOL bNameValid;
    	CString strAboutMenu;
    	bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    	ASSERT(bNameValid);
    	if (!strAboutMenu.IsEmpty())
    	{
    		pSysMenu->AppendMenu(MF_SEPARATOR);
    		pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    	}
        }
    
        // Set the icon for this dialog.  The framework does this automatically
        //  when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);			// Set big icon
        SetIcon(m_hIcon, FALSE);		// Set small icon
    
        // TODO: Add extra initialization here
        m_BtnClose.SetWindowText(L"Close");
    
        return TRUE;  // return TRUE  unless you set the focus to a control
    }
  22. To execute the application, press F5
  23.  To close the dialog box, click its System Close button , , or
  24.  Display the dialog box
  25. Right-click the button and click Add Event Handler
  26. In the Event Handler Wizard, make sure the Message Type is set to BN_CLICKED
    Make sure the Class List is set to CAppLauncher1Dlg.
    Click the Add And Edit button
  27. Implement the OnClick event as follows:
    void CAppLauncher1Dlg::OnBnClickedCloseBtn()
    {
    	// TODO: Add your control notification handler code here
    	PostQuitMessage(WM_QUIT);
    }
  28. To execute the application, press F5
  29. To close the dialog box, click the Close button and return to your programming environment

An Icon on a Button

To make a button look good, you can display an icon on it. To support this, the CButton class is equipped with the SetIcon() member function. Its syntax is:

HICON SetIcon(HICON hIcon);

Before using it, you can first import an icon file to your project and give that icon an ID. Then call this member function and pass the returned value of a LoadImage() function to it. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    m_Calculate.SetIcon(static_cast<HICON>(LoadImage(AfxGetInstanceHandle(),
	                                             MAKEINTRESOURCE(IDI_RIGHTARROW),
					             IMAGE_ICON,
					      	     16,
					      	     16,
					      	     LR_DEFAULTSIZE)));
	
    return TRUE;  // return TRUE  unless you set the focus to a control

 

 
 
   
 

Home Copyright © 2010-2011 FunctionX, Inc.