一、SendMessage()函数
在Win32的消息处理机制中,分别有两种消息:一种是对于事件(如鼠标点击、移动等)发生产生的消息,被系统放入消息队列中,提交给相应程序的相应消息处理函数处理;另一种则是由程序本身发送给系统,来提交某个请求或获取信息。
例如,修改窗口标题SetWindowText()的API实际上也可以通过发送WM_SETTEXT消息来实现:
SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)"OK");
二、单选按钮
创建单选按钮,只需要在CreateWindowEx()的时候将普通按钮的BS_PUSHBUTTON风格换成BS_RADIOBUTTON或者BS_AUTORADIOBUTTON。
BS_RADIOBUTTON:
这样就创建了两个单选按钮,但初始状态均为未选中状态,所以可以向其中一个单选按钮发送BM_SETCHECK消息来更改其选择/未选择状态:CreateWindowEx(0,BUTTON,Radio1,WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON, 4,4,150,32,hWnd,(HMENU)40001,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Radio2",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON, 4,40,150,32,hWnd,(HMENU)40002,g_hInstance,NULL);
其中BST_CHECKED表示设置为选中状态,设置未选中时使用BST_UNCHECKED。SendMessage(GetDlgItem(hWnd,40001),BM_SETCHECK,BST_CHECKED,0);
为了保证两个单选按钮能够正常的进行切换,则需要在消息处理函数里作出相应处理,当单选按钮被点击时,与按钮性质一样会发出BN_CLICKED消息,而消息的wParam参数则记录了按钮ID。所以消息处理函数需要添加如下代码:
if(HIWORD(wParam)==BN_CLICKED) { if(LOWORD(wParam)==40001) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_BTN_RADIO2),BM_SETCHECK,BST_UNCHECKED,0); } else if(LOWORD(wParam)==40002) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_BTN_RADIO1),BM_SETCHECK,BST_UNCHECKED,0); } }
BS_AUTORADIOBUTTON风格则是自动属性的单选按钮:
CreateWindowEx(0,"BUTTON","AutoRadio1",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON|WS_GROUP, 4,4,150,32,hWnd,(HMENU)40001,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","AutoRadio2",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, 4,40,150,32,hWnd,(HMENU)40002,g_hInstance,NULL); SendMessage(GetDlgItem(hWnd,IDC_BTN_AUTORADIO1),BM_SETCHECK,BST_CHECKED,0);
由于是自动性质的单选按钮,故不再在消息处理函数中需要添加切换选中状态代码,由系统自动维护。但是必须在创建时将第一个单选按钮的风格上加上WS_GROUP,表示以此单选按钮起ID连续的全部单选按钮均属于组。
三、复选按钮
不带自动属性的两状态复选按钮:
//创建: CreateWindowEx(0,"BUTTON","Check Box",WS_CHILD|WS_VISIBLE|BS_CHECKBOX,4,40,150,32,hWnd,(HMENU)40001,g_hInstance,NULL);
带自动属性的两状态复选按钮://消息处理函数中: if(LOWORD(wParam)==IDC_BTN_CHECK) { if(HIWORD(wParam)==BN_CLICKED) { int res=SendMessage((HWND)lParam,BM_GETCHECK,0,0); if(res==BST_CHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); else if(res==BST_UNCHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); } }
不带自动属性的三状态复选按钮:CreateWindowEx(0,"BUTTON","Autocheck Box",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 4,40,150,32,hWnd,(HMENU)40002,g_hInstance,NULL);
//创建: CreateWindowEx(0,"BUTTON","3 State",WS_CHILD|WS_VISIBLE|BS_3STATE, 4,40,150,32,hWnd,(HMENU)40003,g_hInstance,NULL);
//消息处理函数中: if(LOWORD(wParam)==IDC_BTN_3STATE) { if(HIWORD(wParam)==BN_CLICKED) { int res=SendMessage((HWND)lParam,BM_GETCHECK,0,0); if(res==BST_CHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_INDETERMINATE,0); else if(res==BST_INDETERMINATE) SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); else if(res==BST_UNCHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); } }
带自动属性的三状态复选按钮:
CreateWindowEx(0,"BUTTON","Auto 3 State",WS_CHILD|WS_VISIBLE|BS_AUTO3STATE, 4,40,150,32,hWnd,(HMENU)40004,g_hInstance,NULL);
四、其他特殊按钮
分组框
PushLikeCreateWindowEx(0,"BUTTON","Group Box",WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 4,40,150,96,hWnd,(HMENU)40000,g_hInstance,NULL);
CreateWindowEx(0,"BUTTON","PushLike",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX|BS_PUSHLIKE, 4,40,150,32,hWnd,(HMENU)40000,g_hInstance,NULL);
五、代码实例
创建简单Win32工程(Simple Win32):
#include"stdafx.h" #include<stdio.h> #define IDC_BTN_PUSH 4001 #define IDC_BTN_DEFPUSH 4002 #define IDC_BTN_GROUP 4003 #define IDC_BTN_CHECK 4004 #define IDC_BTN_AUTOCHECK 4005 #define IDC_BTN_3STATE 4006 #define IDC_BTN_AUTO3STATE 4007 #define IDC_BTN_RADIO1 4008 #define IDC_BTN_RADIO2 4009 #define IDC_BTN_AUTORADIO1 4010 #define IDC_BTN_AUTORADIO2 4011 #define IDC_BTN_PUSHLIKE 4012 LPCSTR g_pszAppName="WinButton"; LPCSTR g_pszMainWndClass="MAIN"; HINSTANCE g_hInstance=NULL; void OnCreate(HWND hWnd,LPARAM lParam) { int x=4,y=4; CreateWindowEx(0,"BUTTON","Push",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, x,y,150,32,hWnd,(HMENU)IDC_BTN_PUSH,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Default Push",WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_DEFPUSH,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Group Box",WS_CHILD|WS_VISIBLE|BS_GROUPBOX, x,y+=36,150,96,hWnd,(HMENU)IDC_BTN_GROUP,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Check Box",WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x,y+=100,150,32,hWnd,(HMENU)IDC_BTN_CHECK,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Autocheck Box",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_AUTOCHECK,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","3 State",WS_CHILD|WS_VISIBLE|BS_3STATE, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_3STATE,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Auto 3 State",WS_CHILD|WS_VISIBLE|BS_AUTO3STATE, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_AUTO3STATE,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Radio1",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON|WS_GROUP, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_RADIO1,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","Radio2",WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_RADIO2,g_hInstance,NULL); SendMessage(GetDlgItem(hWnd,IDC_BTN_RADIO1),BM_SETCHECK,BST_CHECKED,0); CreateWindowEx(0,"BUTTON","AutoRadio1",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON|WS_GROUP, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_AUTORADIO1,g_hInstance,NULL); CreateWindowEx(0,"BUTTON","AutoRadio2",WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_AUTORADIO2,g_hInstance,NULL); SendMessage(GetDlgItem(hWnd,IDC_BTN_AUTORADIO1),BM_SETCHECK,BST_CHECKED,0); CreateWindowEx(0,"BUTTON","PushLike",WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX|BS_PUSHLIKE, x,y+=36,150,32,hWnd,(HMENU)IDC_BTN_PUSHLIKE,g_hInstance,NULL); } void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam) { if(LOWORD(wParam)==IDC_BTN_DEFPUSH||LOWORD(wParam)==IDC_BTN_PUSH) { if(HIWORD(wParam)==BN_CLICKED) { CHAR szText[256]={0}; GetWindowText((HWND)lParam,szText,sizeof(szText)/sizeof(szText[0])); MessageBox(hWnd,szText,"Push",MB_OK); } } if(LOWORD(wParam)==IDC_BTN_CHECK) { if(HIWORD(wParam)==BN_CLICKED) { int res=SendMessage((HWND)lParam,BM_GETCHECK,0,0); if(res==BST_CHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); else if(res==BST_UNCHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); } } if(LOWORD(wParam)==IDC_BTN_3STATE) { if(HIWORD(wParam)==BN_CLICKED) { int res=SendMessage((HWND)lParam,BM_GETCHECK,0,0); if(res==BST_CHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_INDETERMINATE,0); else if(res==BST_INDETERMINATE) SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); else if(res==BST_UNCHECKED) SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); } } if(LOWORD(wParam)==IDC_BTN_RADIO1) { if(HIWORD(wParam)==BN_CLICKED) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_BTN_RADIO2),BM_SETCHECK,BST_UNCHECKED,0); } } if(LOWORD(wParam)==IDC_BTN_RADIO2) { if(HIWORD(wParam)==BN_CLICKED) { SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); SendMessage(GetDlgItem(hWnd,IDC_BTN_RADIO1),BM_SETCHECK,BST_UNCHECKED,0); } } } LRESULT CALLBACK MainWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_COMMAND: OnCommand(hWnd,wParam,lParam); break; case WM_CREATE: OnCreate(hWnd,lParam); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,uMsg,wParam,lParam); } ATOM InitApplication(HINSTANCE hInstance) { WNDCLASSEX wcex={0}; wcex.cbSize=sizeof(wcex); wcex.style=CS_HREDRAW|CS_VREDRAW; wcex.lpfnWndProc=MainWndProc; wcex.cbClsExtra=0; wcex.cbWndExtra=0; wcex.hInstance=hInstance; wcex.hIcon=LoadIcon(NULL,IDI_APPLICATION); wcex.hIconSm=LoadIcon(NULL,IDI_WARNING); wcex.hCursor=LoadCursor(NULL,IDC_ARROW); wcex.hbrBackground=GetSysColorBrush(COLOR_3DFACE); wcex.lpszMenuName=NULL; wcex.lpszClassName=g_pszMainWndClass; return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance,int nCmdShow) { g_hInstance=hInstance; HWND hWnd=CreateWindowEx(WS_EX_CLIENTEDGE,g_pszMainWndClass,g_pszAppName,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,170,15*36,NULL,NULL, hInstance,NULL); if(!hWnd) return 0; ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); return 1; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if(!hPrevInstance) if(!InitApplication(hInstance)) return 0; if(!InitInstance(hInstance,nCmdShow)) return 0; MSG msg={0}; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }