10.2 按钮控件的应用

特殊说明:版权归个人所有,请勿转载,谢谢合作。

按钮控件是一种接受用户命令的控件,通常可以响应鼠标单击或双击事件的矩形窗口。按钮命令是通过鼠标或键盘的操作来响应相应的事件,按钮中可以显示文本或位图。根据按钮实现功能的不同分为:命令按钮(Push Button)、复选框(Check Box)、单选按钮(Radio Button)、分组框(Group Box)以及自绘按钮(Owner-draw Button)。

按钮控件是不能接受用户的输入,只能响应相应的消息,如表10.1所示,描述了按钮控件的通知消息。

 

  • 表10.1 按钮控件的通知消息
消息 描述
BN_CLICKED 按钮单击消息
BN_DOUBLECLICKED 按钮双击消息

 

按钮控件通过CreateWindow或CreateWindowEx函数创建,下面以CreateWindow函数为列,创建一个通用命令按钮控件。

// 创建按钮
g_hButtonWnd =  CreateWindow("BUTTON", "MyButton", 
  WS_CHILD | WS_VISIBLE, 50+80+10, 50, 100, 20, 
  hWnd, NULL, g_hIns, NULL);

 

除了标准按钮,可以通过CreateWindow函数来创建不同风格的按钮(如:单选、多选按钮等),通过第三个参数dwStyle来指定,具体可指定的风格(可以是风格的组合)如表10.2所示。

 

  • 表10.2 按钮控件风格
风格 描述
BS_AUTOCHECKBOX 同BS_CHECKBOX,创建一个自动选中的复选按钮,只有在复选框里设置值才起作用
BS_AUTORADIOBUTTON 同BS_RADIOBUTTON,创建一个自动选中的单选按钮
BS_AUTO3STATE 同BS_3STATE,创建自动的三态按钮
BS_CHECKBOX 创建一个复选按钮
BS_DEFPUSHBUTTON 创建默认选中的按键按钮,当用户按下Enter键时,则表示选择该按键按钮
BS_GROUPBOX 创建按钮组合框,当创建一组单选按钮或者复选按钮时,首先需要创建该按钮组合框
BS_LEFTTEXT 创建单选按钮或复选按钮时,指定按钮名称的文本出现在左边
BS_OWNERDRAW 指定一个自绘按钮
BS_PUSHBUTTON 指定一个命令按钮
BS_RADIOBUTTON 指定一个单选按钮,在右边显示标题
BS_3STATE 创建三态按钮

 

创建复选框按钮与创建命令按钮相同,只是在使用CreateWindow函数创建时,需要修改dwStyle的风格值,指定为“BS_AUTOCHECKBOX”风格即可,代码如下所示。

g_hButtonWnd11 = CreateWindow("BUTTON", "Check Box1", 
  WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 
  50, 80, 100, 20, hWnd, NULL, g_hIns, NULL);

 

创建多选框按钮与创建命令按钮相同,只是在使用CreateWindow函数创建时,需要修改dwStyle的风格值,指定为“BS_AUTOCHECKBOX”风格即可,代码如下所示。

g_hButtonWnd11 = CreateWindow("BUTTON", "Check Box1", 
  WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 
  50, 80, 100, 20, hWnd, NULL, g_hIns, NULL);

 

其它按钮创建类同。按钮有自己的消息类型,当点击了按钮时,它向窗口发送一个WM_COMMAND消息,这些通知消息包含在wParam的高位字节中,也就是说,如果响应按钮的消息,就需要捕获WM_COMMAND消息,并根据wParam的参数内容来判断消息的内容。

前面的代码只是将按钮创建出来,并不能响应任何消息。因为无法识别是哪个按钮,所以在按钮创建之前,需要给第个按钮定义一个唯一的标识,可以通过如下的宏来进行定义。

// 宏定义,分别定义按钮的ID
#define ID_BUTTON_PUSH 0x01
#define ID_BUTTON_RADIO1 0x02
#define ID_BUTTON_RADIO2 0x03
#define ID_BUTTON_CHECK1 0x04
#define ID_BUTTON_CHECK2 0x05

 

其中0x01~0x05是十六进制的数值,当然也可以直接使用十进制数值,但这个数值必须是唯一的。此时需要修改CreateWindow函数的第九个参数hMenu,即使用与菜单响应一样的模式,以命令按钮为例,代码修改如下所示。

// 创建按钮
g_hButtonWnd =  CreateWindow("BUTTON", "MyButton", 
  WS_CHILD | WS_VISIBLE, 50+80+10, 50, 100, 20, 
  hWnd, (HMENU) ID_BUTTON_PUSH, g_hIns, NULL);

 

最后,就可以对按钮的消息进行捕获了,代码如下所示。

  // 菜单响应事件
case WM_COMMAND:
  wmId    = LOWORD(wParam); 
  wmEvent = HIWORD(wParam); 
  // Parse the menu selections:
  switch (wmId)
  {
  case ID_BUTTON_PUSH:
    MessageBox(hWnd, "按钮被按下了...", "提示", MB_OK);
    break;

  default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }//end switch

  break;

 

【例10-2】实现了对命令、单选及多选按钮的创建,并对按钮的消息进行了捕获处理。

//**************************************************************
// NAME 	: Demo_10
//**************************************************************
// POWER 	: Copyright (c) 2012 for lixinghua.
// AUTHOR 	: 2012-7-26 16:51 Create by lixinghua for functions.
// VERSION	: V1.0.0.1
// NOTE 	: 手工整理的创建窗口的代码,本程序只创建一个名称为MyWin的窗口。
//**************************************************************
//

#include <windows.h>
#include <stdio.h>

// 宏定义,分别定义按钮的ID
#define ID_BUTTON_PUSH 0x01
#define ID_BUTTON_RADIO1 0x02
#define ID_BUTTON_RADIO2 0x03
#define ID_BUTTON_CHECK1 0x04
#define ID_BUTTON_CHECK2 0x05

// 回调函数,用于系统消息的处理。
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hIns = NULL;
HWND g_hStaticWnd = NULL;		// 静态文本框句柄
HWND g_hButtonWnd = NULL;		// 按钮句柄
HWND g_hButtonWnd11 = NULL;		// 按钮句柄
HWND g_hButtonWnd12 = NULL;		// 按钮句柄
HWND g_hButtonWnd21 = NULL;		// 按钮句柄
HWND g_hButtonWnd22 = NULL;		// 按钮句柄

//-----------------------------------------------------------------------------
//	FUNC	:	入口函数
//-----------------------------------------------------------------------------
//	IN	:	hInstance,进程的实例句柄;
//			hPrevInstance,前一个进程实例句柄,默认为NULL即可;
//			lpCmdLine,命令行参数;
//			nCmdShow,当前窗口显示状态。
//	OUT	:	void
//	RETURN	:	返回为整型,代表窗口的状态,其中APIENTRY描述了
//               	压栈的顺序。
//	AUTHOR	:	2012-2-6 11:18 Create by lixinghua for functions.
//	NOTE	:	此函数为Win32入口函数。
//-----------------------------------------------------------------------------
//
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  // 定义所用到的参数
  //
  char szWindowClass[] = { "WinClsName" };
                // 窗口类的名称
  HWND hWnd = NULL;					// 用于存放窗口句柄
  char szTitle[] = { "MyWin" };				// 窗口标题名称
  MSG  msg;						// 存放消息的结构体,
// 由系统提供

  // 保存进程实例句柄
  g_hIns = hInstance;

  // 1. 设计一个窗口类
  WNDCLASSEX wcex;
  
  wcex.cbSize = sizeof(WNDCLASSEX); 
  
  wcex.style		= CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc	= (WNDPROC)WndProc;
  wcex.cbClsExtra		= 0;
  wcex.cbWndExtra		= 0;
  wcex.hInstance		= hInstance;
  wcex.hIcon		= NULL;
  wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName	= NULL;
  wcex.lpszClassName	= szWindowClass;
  wcex.hIconSm		= NULL;

  // 2. 注册窗口
  RegisterClassEx(&wcex);

  // 3. 创建窗口
  HMENU hMenu = NULL;
  hWnd = CreateWindow(szWindowClass, szTitle, 
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 
0, CW_USEDEFAULT, 0, NULL, hMenu, hInstance, NULL);

  // 判断创建是否成功
  if (!hWnd)
  {
     return FALSE;
  }//end if

  // 4. 显示并更新窗口
  ShowWindow(hWnd, nCmdShow);		// 请注意 nCmdShow 参数
  UpdateWindow(hWnd);

  // 5. 进入消息循环
  while (GetMessage(&msg, NULL, 0, 0)) 
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }//end while
  
  return 0;
}

//-----------------------------------------------------------------------------
//	FUNC	:	回调函数
//-----------------------------------------------------------------------------
//	IN	:	hWnd,窗口句柄;
//			message,要处理的消息ID,以此来区分消息;
//			wParam,消息参数,根据消息的不同内容也有所不同;
//			lParam,消息参数,根据消息的不同内容也有所不同。
//	OUT	:	void
//	RETURN	:	void
//	AUTHOR	:	2012-2-6 11:36 Create by lixinghua for functions.
//	NOTE	:	此函数用于系统消息的处理。
//-----------------------------------------------------------------------------
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

  PAINTSTRUCT ps;						// 结构体包含了用于绘
                // 制窗口客户区的信息
  HDC  hdc;						// 设备环境句柄
  int wmId, wmEvent;
  char szContext[512] = { 0 };

  // 消息处理
  //
  switch (message) 
  {
    // 创建窗口时响应的事件
  case WM_CREATE:
    // 创建静态文本控件
    g_hStaticWnd = CreateWindow("STATIC", "MyStatic", 
      WS_CHILD | WS_VISIBLE, 50, 50, 80, 20, hWnd,
NULL, g_hIns, NULL);

    // 创建按钮
    g_hButtonWnd =  CreateWindow("BUTTON", "MyButton", 
      WS_CHILD | WS_VISIBLE, 50+80+10, 50, 100, 20, 
      hWnd, (HMENU)ID_BUTTON_PUSH, g_hIns, NULL);

    // 创建多选按钮
    g_hButtonWnd11 = CreateWindow("BUTTON", "Check Box1", 
      WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 
      50, 80, 100, 20, hWnd, (HMENU)ID_BUTTON_RADIO1,g_hIns, NULL);

    g_hButtonWnd12 = CreateWindow("BUTTON", "Check Box2", 
      WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 
      160, 80, 100, 20, hWnd, (HMENU)ID_BUTTON_RADIO2,g_hIns, NULL);

    // 创建单选按钮
    g_hButtonWnd21 = CreateWindow("BUTTON", "Radio 1", 
      WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 
      50, 120, 100, 20, hWnd, (HMENU)ID_BUTTON_CHECK1,g_hIns, NULL);

    g_hButtonWnd22 = CreateWindow("BUTTON", "Radio 2", 
      WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 
      160, 120, 100, 20, hWnd, (HMENU)ID_BUTTON_CHECK2,g_hIns, NULL);

    break;

    // 菜单响应事件
  case WM_COMMAND:
    wmId    = LOWORD(wParam); 
    wmEvent = HIWORD(wParam); 
    // Parse the menu selections:
    switch (wmId)
    {
    case ID_BUTTON_PUSH:
      // 判断Check Box 1是否被按下
      if(IsDlgButtonChecked(hWnd, ID_BUTTON_RADIO1))
      {
        strcat(szContext, "Check Box1 被按下。\r\n");
      }//end if

      // 判断Check Box 2是否被按下
      if(IsDlgButtonChecked(hWnd, ID_BUTTON_RADIO2))
      {
        strcat(szContext, "Check Box2 被按下。\r\n");
      }//end if

      // 判断Radio 1与Radio 2哪个被按下
      if(IsDlgButtonChecked(hWnd, ID_BUTTON_CHECK1))
      {
        strcat(szContext, "Radio 1 被按下。\r\n");
      }
      else if(IsDlgButtonChecked(hWnd, ID_BUTTON_CHECK2))
      {
        strcat(szContext, "Radio 2 被按下。\r\n");
      }//end if

      // 显示提示信息
      MessageBox(hWnd, szContext, "提示", MB_OK);
      
      break;

    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
    }//end switch

    break;

    // 图形绘制事件
  case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);

    EndPaint(hWnd, &ps);
    break;
  
    // 窗口销毁消息,关闭窗口时响应。
  case WM_DESTROY:
    PostQuitMessage(0);
    break;

  default:
    // 调用系统默认消息处理,即交给系统处理。
    return DefWindowProc(hWnd, message, wParam, lParam);
  }//end switch

  return 0;
}

 

程序执行结果如图10.2所示。

  • 图10.2 程序执行结果

 

程序中IsDlgButtonChecked函数的功能是查看单选按钮或多选按钮是否被选中,函数的返回值可能是BST_CHECKED(选中状态)、BST_INDETERMINATE(多选按钮灰化状态)或BST_UNCHECKED(未选中状态)。当然也可以像程序那样,通过值的真假来判断。如果想设计单选或多选按钮的状态,可以使用CheckDlgButton函数,通过参数来对按钮进行设置,设置的值同样是BST_CHECKED(选中状态)、BST_INDETERMINATE(多选按钮灰化状态)或BST_UNCHECKED(未选中状态)三种。

按钮控件的内容同样可以使用SetWindowText函数来设置显示的内容,使用GetWindowText函数来获得显示的内容(按钮上的文本内容)。如果对于按钮没有做其它控制性操作,按钮的句柄可以省略。

 

 

转载请附上原文出处链接及本声明
李老师的博客 » 10.2 按钮控件的应用

发表评论

提供最优质的文章集合

立即查看 了解详情