windows第十二章 MFC控件常用消息

embedded/2025/3/14 13:32:04/

文章目录

  • 控件反射消息机制
  • 文本框控件
    • EN_CHANGE消息
    • EN_UPDATE消息
    • EN_SETFOCUS消息
    • EN_KILLFOCUS消息
    • EN_MAXTEXT消息
    • EN_ERRSPACE消息
    • EN_HSCROLL消息
  • 按钮控件
    • BN_CLICKED消息
    • BN_DOUBLECLICKED消息
    • BN_SETFOCUS消息
    • BN_KILLFOCUS消息
  • 单选按钮
    • BN_CLICKED 消息
  • 复选框
    • BN_CLICKED
    • BN_DOUBLECLICKED消息
  • 组合框
    • CBN_SELCHANGE 消息
    • CBN_EDITCHANGE 消息
    • CBN_DROPDOWN消息
    • CBN_CLOSEUP消息
    • CBN_SELENDOK消息
    • CBN_SELENDCANCEL消息
  • WM_NOTIFY消息
    • 1.当控件向父窗口发送消息
    • 2.标准的解决方案
    • 还可以对NMHDR这个结构体进行拓展
  • 微调控件
    • UDN_DELTAPOS消息
  • 滑动控件
    • TRBN_THUBPOSCHANGING
  • 进度条
  • 列表
    • LBN_SELCHANGE 消息
    • LBN_DBLCLK 消息
    • LBN_SELCANCEL 消息
    • LBN_SETFOCUS 消息
    • LVN_ITEMCHANGED 消息
    • LVN_COLUMCLICK 消息
      • 实现简单的列表排序
  • 树控件
    • TVNSELCHANGED 消息
    • TVN_ITEMEXPANDING消息
    • TVN_KEYDOWN 消息
  • Tab控件
    • TCN_SELCHANGED 消息
    • TCN_KEYDOWN 消息

控件反射消息机制

在这里插入图片描述
当控件产生一个消息时,MFC首先会尝试将该消息反射回控件自身进行处理,这就是控件反射消息机制。这种机制允许控件类自己处理与自身相关的特定消息,而不需要父窗口介入。

如果控件没有处理反射消息,或者没有设置反射消息处理机制,那么消息会传递给父窗口进行处理。父窗口可以使用ON_BN_CLICKED等宏来处理控件的消息。

如果父窗口也没有处理该消息,消息会继续向上传递到更高级别的窗口(如主框架窗口),直到消息被处理或者到达消息链的末端。

创建消息步骤如下

  1. 对话框里创建一个控件,这里是edit control
  2. 点开类视图,点击类向导
    在这里插入图片描述
  3. 搜索对象ID,右边就会弹出很多消息供选择,选择需要使用的消息
    在这里插入图片描述

文本框控件

EN_CHANGE消息

文本改变消息

void C控件消息Dlg::OnChangeEdit1()
{CString str;GetDlgItemText(IDC_EDIT1, str);//获取文本框内容SetWindowText(str);//设置窗口标题
}

在这里插入图片描述

EN_UPDATE消息

跟上面的差不多,只不过在未完成绘制更新时触发

void C控件消息Dlg::OnUpdateEdit1()
{CString str;GetDlgItemText(IDC_EDIT1, str);//获取文本框内容SetWindowText(str);//设置窗口标题
}

EN_SETFOCUS消息

获取焦点时的消息

void C控件消息Dlg::OnSetfocusEdit1()
{static int i = 0;CString str;str.Format(_T("第%d次获得焦点"), ++i);SetWindowText(str);//设置窗口标题
}

在这里插入图片描述

EN_KILLFOCUS消息

与上面相反,失去焦点时获得消息

EN_MAXTEXT消息

这里要先设置一下最大值,才能获取这个消息

BOOL C控件消息Dlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码auto pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);//获取文本框控件pEdit->SetLimitText(10);//设置文本框最大字符数return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
void C控件消息Dlg::OnMaxtextEdit1()
{MessageBox(_T("文本框已达到最大字符数"));
}

在这里插入图片描述

EN_ERRSPACE消息

当 Edit 控件在执行某些操作时,由于系统内存不足,无法完成分配所需内存空间的任务,就会触发 EN_ERRSPACE 消息。这是一个系统发出的警示信号,告知程序当前 Edit 控件遇到了内存分配困境,可能影响正常功能的运行,例如无法存储新输入的文本、无法动态扩展以显示完整内容等。比如在文本文档里输入的内容超过限制数量,弹出一个提示

EN_HSCROLL消息

要接收到消息,先要设置一下滚动条
在这里插入图片描述
这里水平和竖直滚动条都开了

void C控件消息Dlg::OnHscrollEdit1()
{//MessageBox(_T("水平滚动条被拖动"));auto pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);//获取文本框控件int pos = pEdit->GetScrollPos(SB_HORZ);//获取水平滚动条位置CString str;str.Format(_T("水平滚动条位置:%d"), pos);SetWindowText(str);//设置窗口标题
}

在这里插入图片描述

按钮控件

BN_CLICKED消息

和以前的双击一样,都是关联到OnBnClickedButton()

BN_DOUBLECLICKED消息

要获取双击事件,要开启notify
在这里插入图片描述

void C控件消息Dlg::OnDoubleclickedButton1()
{MessageBox(_T("按钮被双击"));
}

后面很多消息需要开启notify

BN_SETFOCUS消息

获得焦点

BN_KILLFOCUS消息

失去焦点

单选按钮

BN_CLICKED 消息

需要的消息可以在类向导里一起选中双击,后确定
在这里插入图片描述
这里双击同样要开启notify

void C控件消息Dlg::OnClickedRadio1()
{SetWindowText(_T("radio1被点击"));
}void C控件消息Dlg::OnKillfocusRadio1()
{SetWindowText(_T("radio1失去焦点"));
}void C控件消息Dlg::OnSetfocusRadio1()
{SetWindowText(_T("radio1获得焦点"));
}void C控件消息Dlg::OnDoubleclickedRadio1()
{MessageBox(_T("radio1被双击"));
}

在这里插入图片描述

复选框

BN_CLICKED

BN_DOUBLECLICKED消息

组合框

创建了一个combobox,给它设置了一个控件变量m_combobox

CBN_SELCHANGE 消息

CBN_EDITCHANGE 消息

CBN_DROPDOWN消息

下拉箭头点击时发出的消息

void C控件消息Dlg::OnDropdownCombo1()
{MessageBeep(0xFFFFFFFF);//发出声音
}

CBN_CLOSEUP消息

CBN_SELENDOK消息

CBN_SELENDCANCEL消息

void C控件消息Dlg::OnSelendcancelCombo1()
{MessageBox(_T("下拉框选项被取消"));
}

在这里插入图片描述

WM_NOTIFY消息

1.当控件向父窗口发送消息

当自定义控件中发生了特殊的事件需要通知父窗口时,可以向父窗口发送消息,最简单的方法就是直接向父窗口直接发送自定义消息:
在pch.h定义一下全局的宏

#define UM_TEST WM_USER + 1//自定义消息

创建一个自定义类CMyButton,继承自CButton,下面是cpp文件

#include "pch.h"
#include "CMyButton.h"BEGIN_MESSAGE_MAP(CMyButton, CButton)ON_CONTROL_REFLECT(BN_CLICKED, &CMyButton::OnBnClicked)
END_MESSAGE_MAP()void CMyButton::OnBnClicked()
{// TODO: 在此添加控件通知处理程序代码this->GetParent()->SendMessage(UM_TEST, 1, 2);//发送自定义消息
}

然后就可以在主窗口截取消息
Dlg.cpp里添加消息映射

ON_MESSAGE(UM_TEST, &C控件消息Dlg::OnTestBtnMsg)//添加在消息映射那块

添加接收函数


LRESULT C控件消息Dlg::OnTestBtnMsg(WPARAM wParam, LPARAM lParam)
{CString str;str.Format(_T("收到自定义消息,参数1:%d,参数2:%d"), wParam, lParam);MessageBox(str);return wParam + lParam;
}

在这里插入图片描述

缺点:需要用到唯一ID的时候,父窗口中的控件会有很多,并不能保证所有消息ID都是唯一的。父窗口可能有一个控件和子窗口的控件同名

2.标准的解决方案

WM_NOTIFY 消息它主要用于控件向其父窗口发送详细的通知信息。
这个消息与其它的消息不同,用户可以自定义通知的内容,但传递消息的方式是统一的。
上述CMyButton.cpp中的函数改成


void CMyButton::OnBnClicked()
{// TODO: 在此添加控件通知处理程序代码NMHDR nmhdr;//一个NMHDR结构体,用于存储按钮的消息nmhdr.hwndFrom = GetSafeHwnd();//获取按钮的句柄nmhdr.idFrom = GetDlgCtrlID();//获取按钮的IDnmhdr.code = UM_TEST;//自定义消息this->GetParent()->SendMessage(WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);//发送消息//注意,这里如果用PostMessage,则按钮点击后不会立即响应,而是等到消息队列中的其他消息处理完毕后才会响应,后面如果用WM_NOTIFY接收,会接收不到,需要再添加一行代码,才能收到
}

Dlg里的消息改成

ON_NOTIFY(UM_TEST, IDC_TEST_BUTTON, &C控件消息Dlg::OnTestBtnMsg2)

Dlg的消息接收函数改成

void C控件消息Dlg::OnTestBtnMsg2(NMHDR* pNMHDR, LRESULT* pResult)
{CString str;str.Format(_T("收到自定义消息,参数1:%d,参数2:%d"), pNMHDR->idFrom, pNMHDR->code);MessageBox(str);*pResult = 0;//表示消息处理完毕
}

还可以对NMHDR这个结构体进行拓展

在pc.h里添加结构体

typedef struct MyNMHDR
{NMHDR nmhdr;int data1;int data2;
} MyNMHDR, * PMyNMHDR;

CMyButton.cpp修改

void CMyButton::OnBnClicked()
{// TODO: 在此添加控件通知处理程序代码NMHDR nmhdr;//一个NMHDR结构体,用于存储按钮的消息nmhdr.hwndFrom = GetSafeHwnd();//获取按钮的句柄nmhdr.idFrom = GetDlgCtrlID();//获取按钮的IDnmhdr.code = UM_TEST;//自定义消息MyNMHDR mynmhdr;mynmhdr.nmhdr = nmhdr;mynmhdr.data1 = 100;mynmhdr.data2 = 200;this->GetParent()->SendMessage(WM_NOTIFY, nmhdr.idFrom, (LPARAM)&mynmhdr);//发送消息
}

Dlg.cpp修改

void C控件消息Dlg::OnTestBtnMsg2(NMHDR* pNMHDR, LRESULT* pResult)
{MyNMHDR* pnmhdr = (MyNMHDR*)pNMHDR;CString str;str.Format(_T("收到自定义消息,参数1:%d,参数2:%d ,参数3:%d,参数4:%d"), pNMHDR->idFrom, pNMHDR->code, pnmhdr->data1, pnmhdr->data2);MessageBox(str);*pResult = 0;//表示消息处理完毕
}

微调控件

控件事件也可以点属性框那个闪电符号设置
在这里插入图片描述
选中需要添加的事件,点下拉按钮,点add
在这里插入图片描述

UDN_DELTAPOS消息

步长位置消息
在这里插入图片描述
可以看出,该结构体和我们上例自定义的MyNMHDR类似,那么用法也是类似的

void C控件消息Dlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);// TODO: 在此添加控件通知处理程序代码CString str;str.Format(_T("当前值:%d, 步长:%d"), pNMUpDown->iPos, pNMUpDown->iDelta);SetWindowText(str);//设置窗口标题CSpinButtonCtrl* pSpin = (CSpinButtonCtrl*)GetDlgItem(IDC_SPIN1);//获取控件UDACCEL uda[1];//定义一个加速器数组uda[0].nInc = 10;//每次增加的值uda[0].nSec = 1;//加速时间间隔pSpin->SetAccel(1, uda);//设置加速器*pResult = 0;
}

在这里插入图片描述

滑动控件

TRBN_THUBPOSCHANGING

滑块位置改变消息
该消息需要开启notify

void C控件消息Dlg::OnTRBNThumbPosChangingSlider1(NMHDR* pNMHDR, LRESULT* pResult)
{// 此功能要求 Windows Vista 或更高版本。// _WIN32_WINNT 符号必须 >= 0x0600。NMTRBTHUMBPOSCHANGING* pNMTPC = reinterpret_cast<NMTRBTHUMBPOSCHANGING*>(pNMHDR);// TODO: 在此添加控件通知处理程序代码CString str;str.Format(_T("当前值:%d,移动原因:%d"), pNMTPC->dwPos, pNMTPC->nReason);//移动原因,有点滑之类的SetWindowText(str);//设置窗口标题*pResult = 0;
}

进度条

都是通用消息,略

列表

LBN_SELCHANGE 消息

选择改变消息

LBN_DBLCLK 消息

LBN_SELCANCEL 消息

选择取消消息
这个消息要结合combobox才能触发,下面会介绍

LBN_SETFOCUS 消息

LVN_ITEMCHANGED 消息

列表选择发生改变的消息,如果是HDN_ITEMCHANGED消息,就是表头选择发生改变

void C控件消息Dlg::OnLvnItemchangedList2(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码if (pNMLV->uNewState & LVIS_SELECTED)//如果被选中{CString str;str.Format(_T("item:%d\r\niSubitem:%d\r\n状态:%d\r\nold状态:%d\r\n"), pNMLV->iItem, pNMLV->iSubItem, pNMLV->uNewState, pNMLV->uOldState);//把字符串放到m_edit中m_edit.SetWindowText(str);}*pResult = 0;
}

LVN_COLUMCLICK 消息

列的点击,一般可以用来排序之类的

实现简单的列表排序

.h文件定义一个排序函数

static int CALLBACK CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//排序函数

.cpp实现

DWORD dwSelColID;	// 选择的列
bool bSortAsc = true;	// 是否升序
void C控件消息Dlg::OnLvnColumnclickList2(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码int nCol = pNMLV->iSubItem;//获取列for (int i = 0; i < m_list.GetHeaderCtrl()->GetItemCount(); i++)m_list.SetItemData(i, i);//设置列的排序数据dwSelColID = nCol;//保存列	bSortAsc = !bSortAsc;//改变排序方式m_list.SortItems(CompareProc, (DWORD_PTR)&m_list);//排序*pResult = 0;
}int C控件消息Dlg::CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{CListCtrl* pList = (CListCtrl*)lParamSort;CString str1 = pList->GetItemText(lParam1, dwSelColID);CString str2 = pList->GetItemText(lParam2, dwSelColID);if (bSortAsc)return str1.Compare(str2);elsereturn str2.Compare(str1);
}

树控件

TVNSELCHANGED 消息

选择发生改变消息

void C控件消息Dlg::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码HTREEITEM hItem = pNMTreeView->itemNew.hItem;CString str;str.Format(_T("选中项:%s"), m_tree.GetItemText(hItem));SetWindowText(str);*pResult = 0;
}

在这里插入图片描述

TVN_ITEMEXPANDING消息

展开消息

TVN_KEYDOWN 消息

按键消息

void C控件消息Dlg::OnTvnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult)
{LPNMTVKEYDOWN pTVKeyDown = reinterpret_cast<LPNMTVKEYDOWN>(pNMHDR);// TODO: 在此添加控件通知处理程序代码if (pTVKeyDown->wVKey == 0x46 && (GetKeyState(VK_CONTROL) & 0x8000))//按下了回车键和Ctrl{MessageBox(_T("按下了F和Ctrl"));}*pResult = 0;
}

Tab控件

TCN_SELCHANGED 消息

选择改变消息

void C控件消息Dlg::OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
{// TODO: 在此添加控件通知处理程序代码int nTab = ((CTabCtrl*)GetDlgItem(IDC_TAB1))->GetCurSel();//获取当前选项卡CString str;str.Format(_T("当前选项卡:%d"), nTab);SetWindowText(str);*pResult = 0;
}

TCN_KEYDOWN 消息

按键消息

void C控件消息Dlg::OnTcnKeydownTab1(NMHDR* pNMHDR, LRESULT* pResult)
{NMTCKEYDOWN* pTCKeyDown = reinterpret_cast<NMTCKEYDOWN*>(pNMHDR);// TODO: 在此添加控件通知处理程序代码if (pTCKeyDown->wVKey == 0x30 && (GetKeyState(VK_CONTROL) & 0x8000))//按下了0和CtrlMessageBox(_T("按下了0和Alt"));if (pTCKeyDown->wVKey == 0x10)//按下了回车键MessageBox(_T("按下了shift"));*pResult = 0;
}

http://www.ppmy.cn/embedded/172499.html

相关文章

《Transformer如何进行图像分类:从新手到入门》

引言 如果你对人工智能&#xff08;AI&#xff09;或深度学习&#xff08;Deep Learning&#xff09;感兴趣&#xff0c;可能听说过“Transformer”这个词。它最初在自然语言处理&#xff08;NLP&#xff09;领域大放异彩&#xff0c;比如在翻译、聊天机器人和文本生成中表现出…

大语言模型(一) 初识大模型

课程讲解视频&#xff1a;《大语言模型》1.1 语言模型发展历程 开源学习网站&#xff1a;https://www.datawhale.cn/learn/content/107/3267 语言模型的发展历程 大模型技术基础 GPT和DeepSeek模型介绍

完美解决ElementUI中树形结构table勾选问题

完美解决ElementUI中树形结构table勾选问题 实现功能效果图全选取消全选取消父节点取消某个子节点 关键代码 实现功能 1. 全选/取消全选&#xff0c;更新所有节点勾选状态 2. 勾选父/子节点&#xff0c;子/父节点状态和全选框状态更新 效果图 全选 取消全选 取消父节点 取消某…

通义万相 2.1 × 蓝耘智算:AIGC 界的「黄金搭档」如何重塑创作未来?

我的个人主页 我的专栏&#xff1a; 人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01; 点赞&#x1f44d;收藏❤ 引言 在当今数字化浪潮席卷的时代&#xff0c;AIGC&#xff08;生成式人工智能&#xff09;领域正…

医院本地化DeepSeek R1对接混合数据库技术实战方案研讨

1. 引言 Deep SEEK R1是一个医疗智能化平台,通过本地化部署实现数据的安全性和可控性,同时提供高效的计算能力。随着医疗信息化的迅速发展,各种数据源的增加使得医院面临更多复杂的挑战,包括如何处理实时监测数据、如何进行大数据环境下的复杂查询以及如何整合多模态数据等…

Python+DeepSeek:开启AI编程新次元——从自动化到智能创造的实战指南

文章核心价值 技术热点:结合全球最流行的编程语言与国产顶尖AI模型实用场景:覆盖代码开发/数据分析/办公自动化等高频需求流量密码:揭秘大模型在编程中的创造性应用目录结构 环境搭建:5分钟快速接入DeepSeek场景一:AI辅助代码开发(智能补全+调试)场景二:数据分析超级助…

【从零开始学习计算机科学】编程语言(一)常用编程语言的发展与介绍

【从零开始学习计算机科学】编程语言(一)常用编程语言的发展与介绍 编程语言可读性可写性可靠性代价影响编程语言的因素编程语言的分类编程语言设计中的权衡编程语言的实现方法编程环境编程语言的发展过程低级语言时代高级语言时代第一个高级语言—Fortran第一个结构化程序设…

【蓝桥杯—单片机】第十五届省赛真题代码题解析 | 思路整理

第十五届省赛真题代码题解析 前言赛题代码思路笔记竞赛板配置建立模板明确基本要求显示功能部分频率界面正常显示高位熄灭 参数界面基础写法&#xff1a;两个界面分开来写优化写法&#xff1a;两个界面合一起写 时间界面回显界面校准校准过程校准错误显示 DAC输出部分按键功能部…