控件操作
控件操作包括如何创建一个控件,如何获取控件,如何修改一个控件的内容,如何添加事件处理程序
1.添加控件
MFC的控件主要是在工具栏中选择控件添加,可以直接拖动,也可以先点击再在对话框中拖动绘制
直接拖动

先点击再在对话框中拖动绘制

两种方法都可以
2.对齐方式
当选中一个控件时,右上角会有对齐按钮一栏,可以选择对齐方式

3.参照线
对话框的上方和左边,都有一个参照线添加器,点击任意一个位置就可以添加一个参照线
每一个参照线会有一个小箭头,拖动小箭头可以改变参照线的位置

若想删除参照系,按住小箭头拖到两边的边缘即可自动删除
参照线方便我们给一些控件对齐

4.控件属性
4.1 初始常用属性
选中一个控件,可以在属性视图中,修改一些基本的属性

4.2 手动修改属性
一些常用的属性,例如控件的文字,禁用状态,我们可能会需要动态的改变
要改变这些属性,不能直接通过控件变量修改,而是需要调用CWnd中自带的一些方法
所有的方法都在此文档中:https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cwnd-class?view=msvc-170
下面列举一些常用的方法
SetWindowText
将窗口的标题、或者控件的主要文字,设置为指定的文本。
比如按钮中间的文字描述,edit框中的文字
void SetWindowText(LPCTSTR lpszString);参数
lpszString:指向要用作新标题或控件文本的CString对象或 null 结尾的字符串。
CWnd *pWnd = GetDlgItem(IDC_EDITNAME);
pWnd->SetWindowText(_T("Gerald Samper"));GetWindowText
int GetWindowText(
LPTSTR lpszStringBuf,
int nMaxCount
) const;
void GetWindowText(CString& rString) const;参数
lpszStringBuf:指向接收复制的窗口标题字符串的缓冲区。nMaxCount:指定要复制到缓冲区的最大字符数,包括结尾的 null 字符。 如果字符串长于nMaxCount中指定的字符数,则将其截断。rString:一个CString对象,它将接收复制的窗口标题字符串。
返回值
指定复制的字符串的长度(以字符为单位),不包括结尾的 null 字符。 如果 CWnd 没有标题栏或标题栏为空,则返回值为 0。
TIP
如果 CWnd 对象是控件,则 GetWindowText 成员函数将复制控件中的文本,而不是复制标题栏。
CWnd *btn = GetDlgItem(IDC_BUTTON);
Cstring str;
btn->SetWindowText(str);GetWindowTextLength
返回 CWnd 对象标题栏标题的长度
int GetWindowTextLength() const;5.获取控件
5.1 添加控件变量
右键控件=》添加变量,可以创建一个该控件类型的变量,通过这个变量可以调用该控件上的函数

输入变量名称,点击完成

之后可以在头文件中发现这个变量的定义

可以使用该变量调用相应的函数,例如在OnInitDialog()中给这个按钮修改文字内容,需要调用SetWindowTextW()
BOOL CMainDlg::OnInitDialog() {
CDialogEx::OnInitDialog();
my_btn.SetWindowTextW(_T("点我你会变帅"));
return TRUE;
}_T()是个宏,会把参数内容转化成宽字符,详细后面会说到
#define _T(x) __T(x)
#define __T(x) L ## x5.2 通过GetDlgItem获取句柄
如果不想创建全局变量,可以在用到的时候,使用GetDlgItem()函数,根据控件ID获取该控件的指针
GetDlgItem一共有两个重载,一个返回CWnd*,一个返回HWND
CWnd* GetDlgItem(int nID) const;
void GetDlgItem(int nID, HWND* phWnd) const;参数:
- nID:控件的ID,可在属性页找到,是一个宏
- phWnd:
HWND*类型的指针
返回值:
- CWnd*:返回一个CWnd类型的指针,
- CWnd 是 MFC 中所有窗口类(如对话框
CDialog、视图CView、按钮CButton等)的父类 - 它封装了 Windows 窗口的底层操作,通过成员函数简化了窗口管理(如创建、销毁、绘制、消息处理等)
- CWnd 内部持有窗口句柄
m_hWnd(类型为HWND),将 Windows API 中的窗口操作(如ShowWindow、InvalidateRect)封装为成员函数 - 通过
Attach()和Detach()可实现 CWnd 对象与 HWND 句柄的关联与分离
- CWnd 是 MFC 中所有窗口类(如对话框
BOOL CMainDlg::OnInitDialog() {
CDialogEx::OnInitDialog();
// 方法一:获取控件指针(返回CWnd*,需类型转换)
CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON1);
pButton->SetWindowTextW(_T("点我你会变帅"));
// 方法二:获取控件句柄
HWND pBtn;
GetDlgItem(IDC_BUTTON1, &pBtn);
CButton* pButton = (CButton*)CWnd::FromHandle(pBtn); // 转为MFC指针
pButton->SetWindowTextW(_T("点我你会变帅"));.
return TRUE;
}INFO
此GetDlgItem是MFC封装的函数,并不是Windows.h中的函数,若要使用Windows.h的函数,需要加上::操作符
HWND hWndButton = ::GetDlgItem(m_hWnd, IDC_BUTTON1); // 获取句柄
CButton* pButton = (CButton*)CWnd::FromHandle(hWndButton); // 转为MFC指针MFC中对Windows.h很多函数进行了封装,更加方便实用
5.3 通过控件类名查找
适用场景:需批量操作同类型控件(如所有编辑框)。
// 查找第一个CEdit控件
CWnd* pEdit = FindWindowEx(m_hWnd, NULL, _T("Edit"), NULL);
while (pEdit != nullptr) {
// 操作pEdit
pEdit = FindWindowEx(m_hWnd, pEdit->m_hWnd, _T("Edit"), NULL);
}6.CWnd和HWND相互转换
二者区别:
- HWND:Windows API中的窗口句柄,本质是32位无符号整数(
void*),用于系统标识窗口资源,无成员函数,需通过API(如::ShowWindow(hWnd))操作。 - CWnd:MFC窗口类的基类(如
CDialog、CButton均派生自它),封装了窗口操作(如MoveWindow())并内部持有m_hWnd成员(即对应的HWND)。
6.1 CWnd→HWND
GetSafeHwnd()
安全获取HWND,若CWnd*为NULL则返回NULL,避免空指针崩溃。
CWnd* pWnd = GetDlgItem(IDC_BUTTON); // 获取控件指针
HWND hWnd = pWnd->GetSafeHwnd(); // 安全转换m_hWnd
m_hWnd是CWnd类中的一个属性,其值为HWND类型的句柄
CWnd* pWnd = GetDlgItem(IDC_BUTTON); // 获取控件指针
HWND hWnd = pWnd->m_hWnd; // 快速访问,需前置非空校验6.1 CWnd←HWND
FromHandle()
返回临时CWnd*指针**,由MFC框架自动管理。若hWnd无关联的永久CWnd对象,框架会创建临时对象(不可长期保存)。
HWND hWnd = ::FindWindow(NULL, _T("窗口标题"));
CWnd* pTempWnd = CWnd::FromHandle(hWnd); // 临时对象,仅当前作用域有效FromHandlePermanent()
返回永久CWnd*指针**,仅当hWnd已关联到MFC创建的CWnd对象(如通过Create()生成的窗口)时有效,否则返回NULL。
CWnd* pPermWnd = CWnd::FromHandlePermanent(hWnd);
if (pPermWnd) {
pPermWnd->SetWindowText(_T("永久对象可长期操作"));
}Attach()
HWND hWnd = ::FindWindow(NULL, _T("窗口标题"));
CWnd myWnd; // 声明CWnd对象
myWnd.Attach(hWnd); // 关联句柄
myWnd.ShowWindow(SW_SHOW); // 操作窗口
myWnd.Detach(); // 解除关联(重要!)