Windows窗口程序设计中,按钮、文本编辑框等控件都作为一个子窗口在WM_CREATE事件中创建的。其中按钮类button有多种类型和风格,常见的单选钮、复选钮、分组框也在此类中,见下表:
子窗口控件:按钮类button
按钮类型,可以是按钮风格与窗口风格的组合
窗口风格:
WS_CHILD 子窗口,必须有
WS_VISIBLE 窗口可见,一般都有
WS_DISABLED 禁用窗口,创建初始状态为灰色不可用的按钮时使用
WS_TABSTOP 可用Tab键选择
WS_GROUP 成组,用于成组的单选按钮中的第一个按钮
按钮风格:
BS_PUSHBUTTON 下压式按钮,也即普通按钮
BS_CHECKBOX 复选按钮,不常用
BS_AUTOCHECKBOX 含自动选中状态的复选按钮
BS_RADIOBUTTON 单选按钮,不常用
BS_AUTORADIOBUTTON 含自动选中状态的单选按钮
BS_3STATE 三态复选按钮,不常用
BS_AUTO3STATE 含自动选中状态的三态复选按钮
BS_GROUPBOX 分组框,用来放置单选或复选按钮的
BS_OWNERDRAW 用于自定义形状的类型,比如画个圆形的按钮
以上风格指定了创建的按钮类型,不能同时使用,但必须有其一
其中非自动类型的按钮需要自己编程来实现选中与否的状态切换
BS_BITMAP 按钮上将显示位图
BS_DEFPUSHBUTTON 设置为默认按钮,只用于下压式按钮,一个对话框中只能指定一个默认按钮
创建方法:
HWND hwndButton;
hwndButton = CreateWindow ( TEXT("button"), /*子窗口类名称*/
TEXT("Command Button"), /*按钮上的文字*/
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, /*按钮类型*/
left, top, width, height, /*位置*/
hwnd, /*父窗口句柄*/
(HMENU)IDcmdButton, /*按钮ID,一个自定义整型常量*/
((LPCREATESTRUCT) lParam)->hInstance, NULL);
if (!hwndButton) MessageBox(NULL,"创建按钮失败","Message",MB_OK|MB_ICONERROR);
ShowWindow(hwndButton,SW_SHOW);
UpdateWindow(hwndButton);
再来用DEV-C++的windows application示例代码,创建这十种button类按钮。(代码获得方法见上一篇博文《C++ 用DEV-C++建一个Windows窗口程序带文本框和命令按钮》)
先建一个结构数组,存放这些按钮类型常数:
struct button {
int swStyle;
const char *szText;
}
Buttons[] = {
BS_PUSHBUTTON, TEXT("普通按钮"),
BS_DEFPUSHBUTTON, TEXT("默认按钮"),
BS_RADIOBUTTON, TEXT("单选按钮"),
BS_CHECKBOX, TEXT("复选按钮"),
BS_3STATE, TEXT("三态按钮"),
BS_AUTORADIOBUTTON, TEXT("自动单选按钮"),
BS_AUTOCHECKBOX, TEXT("自动复选按钮"),
BS_AUTO3STATE, TEXT("自动三态按钮"),
BS_GROUPBOX, TEXT("按钮分组框"),
BS_OWNERDRAW, TEXT("自画类型按钮")
};
然后在WM_CREATE事件中遍历数组创建全部按钮,在WM_COMMAND事件中写入鼠标单击响应代码就完成了:
#include <windows.h>
struct button {
int swStyle;
const char *szText;
}
Buttons[] = {
BS_PUSHBUTTON, TEXT("普通按钮"),
BS_DEFPUSHBUTTON, TEXT("默认按钮"),
BS_RADIOBUTTON, TEXT("单选按钮"),
BS_CHECKBOX, TEXT("复选按钮"),
BS_3STATE, TEXT("三态按钮"),
BS_AUTORADIOBUTTON, TEXT("自动单选按钮"),
BS_AUTOCHECKBOX, TEXT("自动复选按钮"),
BS_AUTO3STATE, TEXT("自动三态按钮"),
BS_GROUPBOX, TEXT("按钮分组框"),
BS_OWNERDRAW, TEXT("自画类型按钮")
};
/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
int num = sizeof Buttons / sizeof Buttons[0];
switch(Message) {
//在 WM_CREATE 事件中创建所有按钮类型
case WM_CREATE: {
for (int i = 0; i < num; i++) {
CreateWindow( TEXT("button"),
Buttons[i].szText,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | Buttons[i].swStyle,
80 + (i >= num / 2 ? 240 : 0),
60 + i * 50 - (i >= num / 2 ? 250 : 0),
160, 40,
hwnd,
(HMENU)i,
((LPCREATESTRUCT) lParam)->hInstance,
NULL);
}
break;
}
//在 WM_COMMAND 事件中会响应button类的鼠标单击,但其中GROUPBOX不响应操作
case WM_COMMAND: {
MessageBox(NULL, Buttons[LOWORD(wParam)].szText, "Button_Click()", MB_OK);
break;
}
/* Upon destruction, tell the main thread to stop */
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
/* All other messages (a lot of them) are processed using default procedures */
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc; /* A properties struct of our window */
HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
MSG msg; /* A temporary location for all messages */
/* zero out the struct and set the stuff we want to modify */
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc; /* This is where we will send messages to */
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "WindowClass";
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Button Style",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, /* x */
CW_USEDEFAULT, /* y */
640, /* width */
480, /* height */
NULL,NULL,hInstance,NULL);
if(hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
/*
This is the heart of our program where all input is processed and
sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
this loop will not produce unreasonably high CPU usage
*/
while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
TranslateMessage(&msg); /* Translate key codes to chars if present */
DispatchMessage(&msg); /* Send it to WndProc */
}
return msg.wParam;
}
运行效果图: