9控件按钮
通过WIN32 绘图,画出各种控件,如下:
注意:按钮的本质是窗口。换句话说,以上说显示的都是窗口,button,radio,checked box等都是一个窗口。
窗口函数原型:
CreateWindowExA(0, lpClassName, lpWindowName, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
全部控件都可以利用CreateWindowExA()实现,以下几点请注意:
1.lpClassName:”BUTTON”,使用系统内部的类
2.dwStyle:要定义主窗口的风格、按钮的风格,WS_CHILD|WS_VISIBLE这两个必要的
3.hMenu:菜单句柄,如果要通过按钮实现其他操作,因此必须一个消息队列,可以通过hMenu进入消息循环。
可以看出,在例子中使用了许多控件ID,那么如何使ID不重复并有意义?
步骤:打开资源视图-》找到.rc(如下图)-》右击-》资源符号。
利用资源符号可以各种控件的ID,并其值由系统分配。
Checked box 与 AutoChecked box的区别:
Checked box必须要自己书写消息循环,由hMenu为入口。
AutoChecked box 创建后可以直接使用,不需要书写消息循环。
同理,AutoRadio与Radio也是如此。
关于checked box详解:
case IDM_CHECKEDBOX:
if(HIWORD(wParam)==BN_CLICKED)
{
switch(SendMessage((HWND)lParam,BM_GETCHECK,0,0))
{
case BST_CHECKED:
SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0);
break;
case BST_UNCHECKED:
SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0);
break;
}
}
break;
注意点:
1.HIWORD(wParam) 存放该控件是否被点击了。
2.因为每一个控件都是一个窗口,所以SendMessage()的窗口句柄是(HWND)lParam,不是hWnd,而hWnd是我们的主窗口,不是控件。
3.通过SendMessage((HWND)lParam,BM_GETCHECK,0,0),BM_GETCHECK返回控件的点击情况,
再进一步选择,若是不选中,则变成选中状态。
关于checked box详解:
CreateWindowEx(0,"button","RADIOBUTTON1",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON|WS_GROUP,point.x,point.y+dwSize*5,dwWidth,dwHeight,hWnd,(HMENU)IDC_RADIO1,hInst,0);
CreateWindowEx(0,"button","RADIOBUTTON2",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON,point.x,point.y+dwSize*6,dwWidth,dwHeight,hWnd,(HMENU)IDC_RADIO2,hInst,0);
case IDC_RADIO1:
if(HIWORD(wParam)==BN_CLICKED)
{
SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0);
SendMessage(GetDlgItem(hWnd,IDC_RADIO2),BM_SETCHECK,BST_UNCHECKED,0);
}
break;
case IDC_RADIO2:
if(HIWORD(wParam)==BN_CLICKED)
{
SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0);
SendMessage(GetDlgItem(hWnd,IDC_RADIO1),BM_SETCHECK,BST_UNCHECKED,0);
}
break;
创建radio button时,要注意第一radio的风格必须加上WS_GROUP,意思为与以下的radio都是都是一组的。
消息循环函数与checked box类似,若选择了radio1,则将radio1变成选中状态,radio2变成不选中状态。
比较 :
SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0);
SendMessage(GetDlgItem(hWnd,IDC_RADIO1),BM_SETCHECK,BST_UNCHECKED,0);
因为点击了radio1,lParam里面携带了当前radio1的窗口句柄,但是没有radio2的窗口句柄,所以要通过windows API 函数GetDlgItem()来获取。(参数解析,获取某一窗口的某一控件id的句柄。)
3 state的详解:
CreateWindowEx(0,"button","3state",WS_CHILD|WS_VISIBLE|BS_3STATE,point.x+dwWidth+dwSize,point.y,dwWidth,dwHeight,hWnd,(HMENU)IDC_3STATE,hInst,0);
case IDC_3STATE:
if(HIWORD(wParam)==BN_CLICKED)
{
switch(SendMessage(HWND(lParam),BM_GETCHECK,0,0))
{
case BST_CHECKED:
SendMessage((HWND)lParam,BM_SETCHECK,BST_INDETERMINATE,0);
break;
case BST_INDETERMINATE:
SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0);
break;
case BST_UNCHECKED:
SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0);
break;
}
}
break;
该控件有三种状态,选中、没选中、虚选中。实现原理与以上解析的控件类似。也是有auto3state。
同样通过SendMessage(HWND(lParam),BM_GETCHECK,0,0),来获取当前控件的状态,再经过选择,进入下一级状态。
源代码: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static POINT point; int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; point.x=4,point.y=4; DWORD dwSize=50; static DWORD dwWidth=150,dwHeight=40; switch (message) { case WM_CREATE: //普通按钮 CreateWindowEx(0,"BUTTON","Push Button",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,point.x,point.y,dwWidth,dwHeight,hWnd,(HMENU)IDM_PUSHBUTTON,hInst,0); CreateWindowEx(0,"button","DEFAULT BUTTON",WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,point.x,point.y+dwSize*1,dwWidth,dwHeight,hWnd,0,hInst,0); //组合框 CreateWindowEx(0,"button","GROUP BOX",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,point.x,point.y+dwSize*2,dwWidth+50,dwHeight,hWnd,0,hInst,0); //选择框 CreateWindowEx(0,"button","CHECKED BOX",WS_CHILD|WS_VISIBLE|BS_CHECKBOX,point.x,point.y+dwSize*3,dwWidth,dwHeight,hWnd,(HMENU)IDM_CHECKEDBOX,hInst,0); //自动选择框,不需要写菜单消息循环 CreateWindowEx(0,"button","AUTOCHECKED BOX",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,point.x,point.y+dwSize*4,dwWidth,dwHeight,hWnd,0,hInst,0); //选择按钮 CreateWindowEx(0,"button","RADIOBUTTON1",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON|WS_GROUP,point.x,point.y+dwSize*5,dwWidth,dwHeight,hWnd,(HMENU)IDC_RADIO1,hInst,0); CreateWindowEx(0,"button","RADIOBUTTON2",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON,point.x,point.y+dwSize*6,dwWidth,dwHeight,hWnd,(HMENU)IDC_RADIO2,hInst,0); //自动选择按钮 CreateWindowEx(0,"button","AUTORADIO1",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON|WS_GROUP,point.x,point.y+dwSize*7,dwWidth,dwHeight,hWnd,NULL,hInst,0); CreateWindowEx(0,"button","AUTORADIO2",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON,point.x,point.y+dwSize*8,dwWidth,dwHeight,hWnd,NULL,hInst,0); //3 state CreateWindowEx(0,"button","3state",WS_CHILD|WS_VISIBLE|BS_3STATE,point.x+dwWidth+dwSize,point.y,dwWidth,dwHeight,hWnd,(HMENU)IDC_3STATE,hInst,0); CreateWindowEx(0,"button","auto3state",WS_CHILD|WS_VISIBLE|BS_AUTO3STATE,point.x+dwWidth+dwSize,point.y+dwSize,dwWidth,dwHeight,hWnd,NULL,hInst,0); //push like CreateWindowEx(0,"button","push like",WS_CHILD|WS_VISIBLE|BS_PUSHLIKE,point.x+dwWidth+dwSize,point.y+dwSize*3,dwWidth,dwHeight,hWnd,NULL,hInst,0); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_PUSHBUTTON: MessageBox(hWnd,"测试 ","提醒",MB_OK); break; case IDM_CHECKEDBOX: if(HIWORD(wParam)==BN_CLICKED) { switch(SendMessage((HWND)lParam,BM_GETCHECK,0,0)) { case BST_CHECKED: SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); break; case BST_UNCHECKED: SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); break; } } break; case IDC_RADIO1: if(HIWORD(wParam)==BN_CLICKED) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_RADIO2),BM_SETCHECK,BST_UNCHECKED,0); } break; case IDC_RADIO2: if(HIWORD(wParam)==BN_CLICKED) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_RADIO1),BM_SETCHECK,BST_UNCHECKED,0); } break; case IDC_3STATE: if(HIWORD(wParam)==BN_CLICKED) { switch(SendMessage(HWND(lParam),BM_GETCHECK,0,0)) { case BST_CHECKED: SendMessage((HWND)lParam,BM_SETCHECK,BST_INDETERMINATE,0); break; case BST_INDETERMINATE: SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); break; case BST_UNCHECKED: SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); break; } } break; case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }