Win32 处理多个按钮共用一个事件消息
今天在学习制作计算器小程序中,碰到要多个按钮共用一个事件的问题,
现记录下来.
在窗体上按钮排列
排列的时候要按顺序排放,也就是说,0-9的ID号要连着的.
#define IDD_DIALOG1 101 #define IDC_BTN_1 1001 #define IDC_BTN_2 1002 #define IDC_BTN_3 1003 #define IDC_BTN_4 1004 #define IDC_BTN_5 1005 #define IDC_BTN_6 1006 #define IDC_BTN_7 1007 #define IDC_BTN_8 1008 #define IDC_BTN_9 1009 #define IDC_BTN_10 1010 #define IDC_BTN_11 1011 #define IDC_BTN_12 1012 #define IDC_BTN_13 1013 #define IDC_BTN_14 1014 #define IDC_BTN_15 1015 #define IDC_BTN_16 1016 #define IDC_BTN_17 1017 #define IDC_BTN_18 1018 #define IDC_BTN_19 1019 #define IDC_EDIT1 1020
在WM_COMMAND消息中去捕获
CString str; void OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { UINT btnId = LOWORD(wParam); HWND hBtn = (HWND)lParam; HWND hEdit = GetDlgItem(hWnd, IDC_EDIT1); //数字0-9,小数点按钮消息 if (btnId >= IDC_BTN_1 && btnId <= IDC_BTN_11) { CString tem; GetWindowText(hBtn, tem.GetBuffer(), 4);//根据按下的数字按钮获得相应的数字字符 str.Format(TEXT("%s%s"), str, tem); SetWindowText(hEdit, str); } //处理+-*/运算符按钮 if (btnId >= IDC_BTN_12 && btnId <= IDC_BTN_15) { } }
原来用swith语句的,但是出现了case 不能判断>=格式,所以只能用if语句了,
其他的同样的道理,要操作哪几个按钮,只要把它们的ID号连着,用if语句判断是否在指定的范围内的ID号就行了.
上面的程序只有点0-9和小数点有效,其它的没有反应.
//补充
今天去查看了下MFC中是如何弄的多个按键共有一个消息的,原来MFC中定义的消息结构中多了个控件ID的最后范围:
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT_PTR nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
所以我在原来的甚础上也添加了这个
//定义消息结构体 struct MSGMAP_STRUCT { UINT uMsg; //消息id号 UINT uCod; //控件反射的事件id号 UINT uCtrID; //控件id号 UINT uLastID; //控件ID结束范围 AFX_PMSG pfn; //函数指针 };
最后在WM_COMMAND消息中判断下消息中的uLastID是否为零,不为零就继续判断传来的控件ID是不是指定的范围内,
如果是就返回找到的消息和对应的消息响应函数,下面这要结合我写的https://www.cnblogs.com/greenleaf1976/p/14780317.html就能明白
if(uMsg==WM_COMMAND)\ {\ if(pMsg->uLastID!=0)\ {\ if (LOWORD(wParam)>=pMsg->uCtrID && LOWORD(wParam) <= pMsg->uLastID)\ {\ return pMsg;\ }\ }\ else if (pMsg->uCtrID == LOWORD(wParam) && pMsg->uCod == HIWORD(wParam))\ return pMsg;\
消息宏的定义
//定义添加消息结构宏 #define ON_WM_MESSAGE(msg,pfn) {msg,0,0,0,(AFX_PMSG)pfn}, #define ON_COMMAND(ctrlID,pfn) {WM_COMMAND,0,ctrlID,0,(AFX_PMSG)pfn}, #define ON_COMMAND_CTRL(ctrlEvent,ctrlID,pfn) {WM_COMMAND,ctrlEvent,ctrlID,0,(AFX_PMSG)pfn}, #define ON_NOTIFY(ctrlEvent,ctrlID,pfn) {WM_NOTIFY,ctrlEvent,ctrlID,0,(AFX_PMSG)pfn}, #define ON_COMMAND_RANGE(ctrlID,ctrLastID,pfn) {WM_COMMAND,0,ctrlID,ctrLastID,(AFX_PMSG)pfn},
在静态消息数组中添加
BEGIN_MESSAGE_MAP(MyTestDialog, QDialog) ON_WM_MESSAGE(WM_CLOSE, &MyTestDialog::OnClose) ON_NOTIFY(LVN_ITEMCHANGED, 1001, &MyTestDialog::OnListCtrlItemChanged) ON_WM_MESSAGE(WM_SIZE,&MyTestDialog::OnSize) ON_NOTIFY(NM_CLICK,1002,&MyTestDialog::OnStatusClick) ON_COMMAND_RANGE(10001,10004,&MyTestDialog::OnBtnArrClick)//这个就是多个控件共用一个消息响应函数,(控件ID必须是连续的) ON_COMMAND(10001,&MyTestDialog::OnBtn1Click) END_MESSAGE_MAP()
最后来个效果:
LRESULT MyTestDialog::OnBtnArrClick(WPARAM wParam, LPARAM lParam) { UINT ctrlID = LOWORD(wParam);//控件ID UINT code = HIWORD(wParam); HWND hbtn = (HWND)lParam; //控件句柄 CString str; GetWindowText(hbtn, str.GetBuffer(), 10);//获得控件ID上对应的文本 str.Format(TEXT("%s,id=%d,code=%d"), str, ctrlID, code);//格式化显示控件文本,控件ID,控件事件ID MessageBox(str); return 0; }
这是按下btn1;
这是按下btn2;
这是按下btn3;
这是btn4;