Skip to content

控件操作

控件操作包括如何创建一个控件,如何获取控件,如何修改一个控件的内容,如何添加事件处理程序

1.添加控件

MFC的控件主要是在工具栏中选择控件添加,可以直接拖动,也可以先点击再在对话框中拖动绘制

直接拖动

PixPin_2025-06-19_16-11-51

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

PixPin_2025-06-19_16-12-09

两种方法都可以

2.对齐方式

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

image-20250619161401349

3.参照线

对话框的上方和左边,都有一个参照线添加器,点击任意一个位置就可以添加一个参照线

每一个参照线会有一个小箭头,拖动小箭头可以改变参照线的位置

image-20250619161708354

若想删除参照系,按住小箭头拖到两边的边缘即可自动删除

参照线方便我们给一些控件对齐

image-20250619161858851

4.控件属性

4.1 初始常用属性

选中一个控件,可以在属性视图中,修改一些基本的属性

image-20250619162117260

4.2 手动修改属性

一些常用的属性,例如控件的文字,禁用状态,我们可能会需要动态的改变

要改变这些属性,不能直接通过控件变量修改,而是需要调用CWnd中自带的一些方法

所有的方法都在此文档中:https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cwnd-class?view=msvc-170

下面列举一些常用的方法

SetWindowText

将窗口的标题、或者控件的主要文字,设置为指定的文本。

比如按钮中间的文字描述,edit框中的文字

c++
void SetWindowText(LPCTSTR lpszString);

参数

  • lpszString:指向要用作新标题或控件文本的 CString 对象或 null 结尾的字符串。
c++
CWnd *pWnd = GetDlgItem(IDC_EDITNAME);
pWnd->SetWindowText(_T("Gerald Samper"));

GetWindowText

c++
int GetWindowText(
    LPTSTR lpszStringBuf,
    int nMaxCount
) const;

void GetWindowText(CString& rString) const;

参数

  • lpszStringBuf:指向接收复制的窗口标题字符串的缓冲区。
  • nMaxCount:指定要复制到缓冲区的最大字符数,包括结尾的 null 字符。 如果字符串长于 nMaxCount 中指定的字符数,则将其截断。
  • rString:一个 CString 对象,它将接收复制的窗口标题字符串。

返回值

指定复制的字符串的长度(以字符为单位),不包括结尾的 null 字符。 如果 CWnd 没有标题栏或标题栏为空,则返回值为 0。

TIP

如果 CWnd 对象是控件,则 GetWindowText 成员函数将复制控件中的文本,而不是复制标题栏。

c++
CWnd *btn = GetDlgItem(IDC_BUTTON);
Cstring str;
btn->SetWindowText(str);

GetWindowTextLength

返回 CWnd 对象标题栏标题的长度

c++
int GetWindowTextLength() const;

5.获取控件

5.1 添加控件变量

右键控件=》添加变量,可以创建一个该控件类型的变量,通过这个变量可以调用该控件上的函数

image-20250619162534064

输入变量名称,点击完成

image-20250619162726678

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

image-20250619162832575

可以使用该变量调用相应的函数,例如在OnInitDialog()中给这个按钮修改文字内容,需要调用SetWindowTextW()

c++
BOOL CMainDlg::OnInitDialog() {
    CDialogEx::OnInitDialog(); 
   
	my_btn.SetWindowTextW(_T("点我你会变帅"));

    return TRUE; 
}

_T()是个宏,会把参数内容转化成宽字符,详细后面会说到

c++
#define _T(x)       __T(x)

#define __T(x)      L ## x

5.2 通过GetDlgItem获取句柄

如果不想创建全局变量,可以在用到的时候,使用GetDlgItem()函数,根据控件ID获取该控件的指针

GetDlgItem一共有两个重载,一个返回CWnd*,一个返回HWND

c++
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 中的窗口操作(如 ShowWindowInvalidateRect)封装为成员函数
    • 通过 Attach()Detach() 可实现 CWnd 对象与 HWND 句柄的关联与分离
c++
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的函数,需要加上::操作符

c++
HWND hWndButton = ::GetDlgItem(m_hWnd, IDC_BUTTON1);  // 获取句柄
CButton* pButton = (CButton*)CWnd::FromHandle(hWndButton);  // 转为MFC指针

MFC中对Windows.h很多函数进行了封装,更加方便实用

5.3 通过控件类名查找

适用场景:需批量操作同类型控件(如所有编辑框)。

c++
// 查找第一个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窗口类的基类(如CDialogCButton均派生自它),封装了窗口操作(如MoveWindow())并内部持有m_hWnd成员(即对应的HWND)。

6.1 CWnd→HWND

GetSafeHwnd()

安全获取HWND,若CWnd*NULL则返回NULL,避免空指针崩溃。

c++
CWnd* pWnd = GetDlgItem(IDC_BUTTON);  // 获取控件指针
HWND hWnd = pWnd->GetSafeHwnd();      // 安全转换

m_hWnd

m_hWndCWnd类中的一个属性,其值为HWND类型的句柄

c++
CWnd* pWnd = GetDlgItem(IDC_BUTTON);  // 获取控件指针
HWND hWnd = pWnd->m_hWnd;  // 快速访问,需前置非空校验

6.1 CWnd←HWND

FromHandle()

返回临时CWnd*指针**,由MFC框架自动管理。若hWnd无关联的永久CWnd对象,框架会创建临时对象(不可长期保存)。

c++
HWND hWnd = ::FindWindow(NULL, _T("窗口标题"));  
CWnd* pTempWnd = CWnd::FromHandle(hWnd);  // 临时对象,仅当前作用域有效

FromHandlePermanent()

返回永久CWnd*指针**,仅当hWnd已关联到MFC创建的CWnd对象(如通过Create()生成的窗口)时有效,否则返回NULL

c++
CWnd* pPermWnd = CWnd::FromHandlePermanent(hWnd);
if (pPermWnd) {
    pPermWnd->SetWindowText(_T("永久对象可长期操作"));
}

Attach()

c++
HWND hWnd = ::FindWindow(NULL, _T("窗口标题"));  

CWnd myWnd;                    // 声明CWnd对象
myWnd.Attach(hWnd);            // 关联句柄
myWnd.ShowWindow(SW_SHOW);     // 操作窗口
myWnd.Detach();                // 解除关联(重要!)

MIT Licensed