MFC 对话框

目录

一、对话款基本认识

二、对话框项目创建

三、控件操作

四、对话框创建和显示 

模态对话框

非模态对话框

五、动态创建按钮

六、访问控件

控件添加控制变量

访问对话框

操作对话框

SendMessage()

七、对话框伸缩功能实现

八、对话框小项目-逃跑按钮

九、小项目


一、对话款基本认识

对话框是与用户进行交互的控件,如文件对话框,字体对话框,颜色对话框等,一般用于告示,提醒等。对话框就是一个窗口,它不仅可以接收消息,而且还可以被移动和关闭,甚至可以在它的客户区中进行绘图。相当于一个窗口,在它上面能够旋转各种标准控件和扩展控件。都是由CWnd类派生来。

Windows应用程序(win桌面应用程序)工作的基本流程是从用户那里得到数据,经过相应的处理之后,先把处理结果输出到屏幕,打印机或者其他输出设备。这就需要用到Windows应用程序的用户接口对话框。

常用对话框

这些控件也是对话框

二、对话框项目创建

创建MFC应用项目,创建基于对话框的程序类型

用户界面,按需选择

高级功能按需选择

生成的类:一个APP类,一个Dialog类

三、控件操作

WM系列消息是对话框接收处理,子控件的消息处理需要在消息映射中指明ID和控件事件

给对话框的控件添加消息处理的3种方式

  1. 双击对话框里面的控件就会在Dlg类消息映射表中添加消息映射
  2. 右击控件,选择类向导,命令一栏中,在里面选择控件的ID值,在选择对应的控件事件
  3. 右击对话框,选择属性,选择控件事件,选择要处理的消息

如何给对话框添加控件?VS中打开工具箱,直接选中拖曳即可

当控件的消息处理无法满足需求时,可以控件也是对话框,可以给控件,对话框添加类,指定ID,父窗口即可

资源添加一个新的对话框,在对话框中右击选择 添加类,会生成一个      .h       .cpp文件

继承的基类选择,可以选CDialog,或者CDialogEx(继承自前者,提供了更加丰富的控件支持)

这个创建后,其构造函数如下:

  1. ButtonText::ButtonText(CWnd* pParent /*=nullptr*/): 这是构造函数的定义,它属于名为ButtonText的类。构造函数的作用是在创建类的对象时进行初始化操作。
  2. :CDialogEx(IDD_DIALOG1, pParent): 这是构造函数的初始化列表(initializer list)。在这里,我们调用了基类(CDialogEx)的构造函数,并传入两个参数:对话框模板资源的ID(IDD_DIALOG1)和父窗口指针(pParent)。通过调用基类的构造函数,确保了从基类继承的成员变量得到了正确的初始化。

在这个构造函数中,传入的 pParent 参数指定了对话框的父窗口。父窗口是指对话框所属的上层窗口,通常用于确定对话框的显示位置和处理窗口间的关系。在这里,pParent 参数指定了对话框的父窗口,可以根据调用这个构造函数时传入的具体参数值来确定。在实际使用中,根据具体的情景,可以传入不同的父窗口指针,以确立对话框与哪个窗口有关联关系。

AddDialogText::AddDialogText(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1, pParent)
{

}

控件的类不想要了,怎么办?项目中删除即可,即可把类的引用修改回来,否则会造成程序连接时候报错。


 

四、对话框创建和显示 

一个控件(对话框),使用消息映射来处理控件事件;一个控件(对话框),添加类,创建类并且show是不一样的。或者提供了更加丰富的功能,更重要的是可以绘制出来,与用户交互,而且拥有自己的消息循环。

创建一个对话框,并设置ID值,在属性一栏中,可以控制外观,位置,行为等,给该对话框添加类。

当点击第一个对话框确定按钮后,就会弹出一个新的对话框。

所以需要在第一个对话框的 .cpp 文件包含新对话框的类。

需要在第一个消息对话框中为Button(确定按钮)使用消息映射机制,

模态对话框

对话框,控件的本质都是对话框,创建他们需要先Create后Show

模态(Model)对话框:指当其显示时,程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中其它任务。当一个模态对话框打开时,用户只能与该对话框进行交互,而其它用户界面对象接收不到输入信息。在其显示时,整个程序会暂停,直到关闭该对话框。

void CMFCApplication1Dlg::OnBnClickedOk()
{
	// 1.模态对话框使用
	CBingoDialog dlg;
	dlg.DoModal();    // 模态对话框,只能操作当前窗口,会阻塞消息循环
}

一但使用后该进程只能先等该对话框处理完后才能继续处理消息。

非模态对话框

对话框,控件的本质都是对话框,创建他们需要先Create后Show

非模态(Modeless)对话框:当其显示时,允许执行程序中其它任务,而不用关闭这个对话框。在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成。对话框资源对应CDialog基类。

需要考虑一个问题,如果在函数内部实例化对话框,创建,绘制对话框,函数执行结束,对话框就会销毁。最好的处理办法就是:在第一个对话框类中,实例化对象,并在调用初始化函数时创建出来,在消息函数中绘制。

void CMFCApplication1Dlg::OnBnClickedOk()
{
	// 2.非模态对话框
	//需要作为MFCApplication1Dlg类的成员变量
	//原因:非模态对话框不会阻塞消息循环,一旦函数结束就会析构掉对象,造成程序崩溃
	// 窗口绘制之前还需要先创建,在这个类初始化时进行操作
	
	if (dlg.m_hWnd == NULL)
	{
		dlg.Create(IDD_DLG_EDAOYUN, this);
	}

	dlg.ShowWindow(SW_SHOW);
}

五、动态创建按钮

动态的需求,需要多少个按钮在程序开始时时不确定的,只能在程序运行时创建

void CBingoDialog::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	TRACE("%s(%d):%s\n", __FILE__, __LINE__, __FUNCTION__);
	if (m_button.m_hWnd == NULL)
	{
		m_button.Create(_T("动态"), BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
			CRect(100, 100, 200, 150), this, 9999);
	}

	TCHAR buf[20] = _T("");
	::SendMessage(m_edit1.m_hWnd, WM_GETTEXT, 20, (LPARAM)buf);
	m_edit1.SendMessage(WM_SETTEXT, sizeof(buf), (LPARAM)buf);
	this->SendMessage(WM_GETTEXT, 20, (LPARAM)buf);
}

相关必要的解释:

  • CButton类是继承自CWND类,m_hWnd就是该类的一个成员变量,记录了Windows系统创建该窗口后,这个窗口的句柄由 m_hWnd 来保存。说明控件(对话框)的本质就是窗口
  • BS_DEFPUSHBUTTON:这是按钮的样式,表示默认的按钮外观。
  • WS_VISIBLE | WS_CHILD:这是窗口样式,表示按钮是可见的并且作为父窗口的子窗口存在。
  • CRect(100, 100, 200, 150):这是按钮控件的位置和大小,使用矩形区域来表示,左上角坐标为 (100, 100),右下角坐标为 (200, 150)。
  • this:这个参数表示按钮控件的父窗口,也就是按钮所在的对话框
  • 9999:这是按钮控件的标识符,用于在程序中唯一标识这个按钮控件。

父窗口,子窗口:当我们在对话框中创建一个按钮时,按钮控件会成为对话框的子窗口,并且对话框将成为该按钮的父窗口。这意味着按钮的显示、布局、事件处理等都是相对于对话框来进行的。同时,对话框也负责管理和维护这些子窗口,比如控制它们的显示和隐藏,处理它们的消息等。

  1. 父窗口

    • 父窗口通常是一个容器窗口,它可以包含其他窗口作为它的子窗口。
    • 父窗口负责管理和布局它的子窗口,包括显示、隐藏、移动、调整大小等操作。
    • 一个窗口可以同时是另一个窗口的子窗口和父窗口,这种多层次的父子关系可以形成窗口的层次结构。
  2. 子窗口

    • 子窗口是被包含在父窗口内的窗口,它的位置和尺寸相对于父窗口来确定。
    • 子窗口可以是各种控件,比如按钮、文本框、列表框等,也可以是其它窗口。
    • 子窗口的行为通常由其父窗口来管理和控制,父窗口处理子窗口的消息并进行相应的响应。

在 MFC 编程中,对话框类通常是一个典型的父窗口,它可以包含各种控件作为其子窗口,比如按钮、编辑框、组合框等。当你在对话框资源编辑器中放置控件时,这些控件就成为了对话框的子窗口。在对话框类的代码中,你可以通过控件的成员变量或者控件 ID 来操作和管理这些子窗口。

上述在按钮消息处理函数中,this指针指向的就是父窗口

六、访问控件

控件都提供一些方法用于访问,比如编辑框,提供了设置默认内容,获取编辑框输入内容给的方法

用编辑框为例,学习相关使用。

控件添加控制变量

右击控件,添加变量

在父类中,会增加以下内容:

int m_value1;
int m_value2;
int m_value3;

父类构造函数

CBingoDialog::CBingoDialog(CWnd* pParent /*=nullptr*/)
	: CDialog(IDD_DLG_EDAOYUN, pParent)
	, m_value1(0)
	, m_value2(0)
	, m_value3(0)
{

}

CEdit m_edit1;
CEdit m_edit2;
CEdit m_edit3;

添加变量 值,控件都会在 DoDataExchange 中指定对话框类成员变量与控件之间的数据交换规则,以及进行数据验证。

void CBingoDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_value1);
	DDV_MinMaxInt(pDX, m_value1, -9999, 9999);
	DDX_Text(pDX, IDC_EDIT2, m_value2);
	DDV_MinMaxInt(pDX, m_value2, -9999, 9999);
	DDX_Text(pDX, IDC_EDIT3, m_value3);
	DDV_MinMaxInt(pDX, m_value3, -9999, 9999);
	DDX_Control(pDX, IDC_EDIT1, m_edit1);
	DDX_Control(pDX, IDC_EDIT2, m_edit2);
	DDX_Control(pDX, IDC_EDIT3, m_edit3);
}

DoDataExchange 是 MFC 对话框类中的一个重要成员函数,用于实现对话框和控件之间的数据交换。在该函数中,可以通过调用 DDX_DDV_ 系列的宏来指定对话框类成员变量与控件之间的数据交换规则,以及进行数据验证。

具体来说,DoDataExchange 函数通常被用来执行两个方面的工作:

  1. 数据传递(DataExchange):将对话框类中的成员变量的值与与之关联的控件进行双向的数据交换。这包括从控件更新数据到成员变量(如 DDX_ControlDDX_Text 等),以及将成员变量的值反向填充到相关联的控件(如 DDX_ControlDDX_Text 等)。

  2. 数据验证(DataValidation):在数据交换过程中,执行数据验证操作,确保用户输入的数据符合预期的格式和范围。这包括使用 DDV_ 系列的宏来对用户输入的数据进行验证,例如格式、范围等。

在你提供的代码中,DoDataExchange 函数拥有一个名为 pDX 的参数,这是数据交换指针,它在数据传递和数据验证过程中扮演着重要的角色。通过在 DoDataExchange 函数中处理 pDX 参数,可以实现对话框和控件之间的数据交换和验证。

在 MFC(Microsoft Foundation Classes)中,DDX_Text 是一个用于数据交换的宏,用于在对话框和控件之间进行文本数据的交换。

具体地说,DDX_Text 宏用于将文本控件(如编辑框)中的数据与对话框类中的成员变量相关联,或者将对话框类中的成员变量的值与文本控件相关联。

DDX_Text(pDX, nIDC, memberName);

其中:

  • pDX 是数据交换指针,负责在对话框和控件之间进行数据交换。
  • nIDC 是控件的 ID,即要进行数据交换的控件的标识符。
  • memberName 是对话框类中的成员变量,用于存储或显示控件中的数据。

在你提供的代码中,DDX_Text(pDX, IDC_EDIT1, m_value1) 的作用是将 ID 为 IDC_EDIT1 的编辑框中的文本与对话框类中名为 m_value1 的成员变量进行关联。这样,在对话框中修改编辑框的内容时,相关联的成员变量 m_value1 也会相应地更新,反之亦然。

通过使用 DDX_Text 宏,可以很方便地实现对话框中控件和对话框类成员变量之间的双向数据交换,这在 MFC 编程中是非常常见和有用的操作。

在 MFC(Microsoft Foundation Classes)中,DDV_MinMaxInt 是一个用于数据验证的宏,用于验证整数类型的数据是否在指定的最小值和最大值范围内。

具体地说,DDV_MinMaxInt 宏用于在对话框数据验证期间检查整数类型的数据,确保其值在指定的最小值和最大值之间。其语法如下:

DDV_MinMaxInt(pDX, value, minVal, maxVal);

其中:

  • pDX 是数据交换指针,负责数据验证。
  • value 是要进行验证的整数值,通常是对话框类中的成员变量。
  • minVal 是允许的最小值。
  • maxVal 是允许的最大值。

在你提供的代码中,DDV_MinMaxInt(pDX, m_value1, -9999, 9999) 的作用是验证对话框类中名为 m_value1 的整数成员变量,确保其值在 -9999 到 9999 的范围内。如果用户输入的值不在这个范围内,MFC 将会显示相应的验证错误消息,并阻止用户继续进行操作,直到输入的值符合要求为止。

通过使用 DDV_MinMaxInt 宏,可以方便地实现对话框中整数类型数据的范围验证,确保用户输入的数据符合预期的范围要求。

DDX_Control 宏用于将对话框中的控件与对话框类中的成员变量进行关联,其作用是将控件的句柄(handle)与对话框类中的成员变量相关联,从而可以通过成员变量来操作控件。

具体来说,DDX_Control 宏的语法如下:

DDX_Control(pDX, nIDC, m_memberName);

其中:

  • pDX 是数据交换指针,负责在对话框和控件之间进行数据交换。
  • nIDC 是控件的 ID,即要进行数据交换的控件的标识符。
  • m_memberName 是对话框类中的成员变量,用于存储控件的句柄。

在你提供的代码中,DDX_Control(pDX, IDC_EDIT1, m_edit1) 的作用是将 ID 为 IDC_EDIT1 的编辑框控件与对话框类中名为 m_edit1 的成员变量进行关联。这样一来,通过 m_edit1 成员变量可以直接操作对应的编辑框控件,例如获取或设置文本内容、启用或禁用控件等操作。

通过使用 DDX_Control 宏,可以方便地实现对话框类成员变量与控件之间的关联,简化了对控件的操作和管理。

访问对话框

GetDlgItem 根据控件的 ID 来获取对应的编辑框控件对象的指针。

SetWindowText:为编辑框设置初始值

GetWindowText:获取编辑框内的值

SetDlgItemText,GetDlgItemText 上面两个功能的综合体

BOOL CBingoDialog::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化
	CWnd* pEdit01 = GetDlgItem(IDC_EDIT1);
	CWnd* pEdit02 = GetDlgItem(IDC_EDIT2);
	//CWnd* pEdit03 = GetDlgItem(IDC_EDIT3);
	CString strText;

	if (pEdit01 != NULL)
	{
		pEdit01->SetWindowText(_T("100"));
		pEdit01->GetWindowText(strText);

	}
	if (pEdit02 != NULL)
	{
		SetDlgItemText(IDC_EDIT2, _T("200"));
		GetDlgItemText(IDC_EDIT2, strText);
	}
	//if (pEdit03 != NULL) pEdit03->SetWinodwText(_T("300"));

	SetDlgItemInt(IDC_EDIT3, 100);
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

操作对话框

在对话框中输入三个值,点击确定按钮后,会把前两个值相加放到第三个中

UpdateData() 是 MFC 中用于进行对话框和控件之间数据交换的函数。通过调用 UpdateData(TRUE),可以将对话框中的控件的当前值更新到关联的成员变量中;而通过调用 UpdateData(FALSE),可以将成员变量的值更新到关联的控件中。

void CBingoDialog::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	//CDialog::OnOK();
	//UpdateData();
	//m_value3 = m_value2 + m_value1;
	//UpdateData(FALSE);

	CString str1, str2, str3;
	m_edit1.GetWindowText(str1);
	m_edit2.GetWindowText(str2);
	int t = _wtoi(str1) + _wtoi(str2);
	TCHAR buf[32] = _T("");
	str3 = buf;
	m_edit3.SetWindowTextW(str3);
}

SendMessage()

一个是调用全局的方法,一个是调用编辑框类的方法

::SendMessage(m_edit1.m_hWnd, WM_GETTEXT, 20, (LPARAM)buf);
m_edit1.SendMessage(WM_SETTEXT, sizeof(buf), (LPARAM)buf);

SendMessage() 是 Windows API 中用于发送消息的函数之一,在 MFC 中也可以使用。通过 SendMessage() 函数,可以向窗口或控件发送特定的消息,以实现各种操作,如获取或设置控件的状态、通知控件发生了特定的事件等。

具体来说,SendMessage() 函数的原型为:

LRESULT SendMessage(
    HWND   hWnd,
    UINT   Msg,
    WPARAM wParam,
    LPARAM lParam
);
  • hWnd:指定要接收消息的窗口或控件的句柄。
  • Msg:指定要发送的消息类型,是一个表示消息的整数值。
  • wParam 和 lParam:作为消息参数传递的额外信息,具体意义取决于不同的消息类型。

在 MFC 中,你可以使用 SendMessage() 函数来与窗口控件进行交互,例如设置控件的状态、获取控件的信息、自定义处理消息等。常见的用法包括发送 WM_SETTEXT 消息来设置控件的文本内容,发送 BM_CLICK 消息来模拟按钮的点击操作,以及发送自定义消息来实现特定的功能。

七、对话框伸缩功能实现

思路:初始化对话框函数中,获取窗口大小,计算得到缩小后的窗口大小

GetWindowRect获取对话框大小

判断一个矩形是否为空:IsRectEmpty(),IsRectNull()。前者是判断矩形面积是否为空,后者是判断矩形的四个坐标值是否为0,不关心是否能做为一个矩形。

SetWindowPos()改变窗口的大小。

BOOL CBingoDialog::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 获取窗口范围
	GetWindowRect(m_large);
	m_small = m_large;
	// 计算得到缩小后的范围
	m_small.right = m_small.left + m_small.Width() / 2;
	m_small.bottom = m_small.top + m_small.Height() / 2;
	
	
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

在缩小按钮按钮事件中完成对窗口的缩放处理

void CBingoDialog::OnBnClickedBtnLarge()
{
	// TODO: 在此添加控件通知处理程序代码
	CRect curRect;
	GetWindowRect(curRect);
	CWnd* pButton = GetDlgItem(IDC_BTN_LARGE);
	CString strTitle;
	if (pButton)
	{
		pButton->GetWindowText(strTitle);
		if (strTitle == _T("放大") && m_large.IsRectEmpty() == FALSE)
		{
			pButton->SetWindowTextW(_T("缩小"));
			SetWindowPos(NULL, curRect.left, curRect.top, m_large.Width(), m_large.Height(), SWP_NOMOVE | SWP_NOZORDER);
			// 窗口Z轴控制
			//SetWindowPos(&wndTopMost, curRect.left, curRect.top, m_large.Width(), m_large.Height(), SWP_NOMOVE);
		}
		else if (m_small.IsRectEmpty() == FALSE)
		{
			pButton->SetWindowTextW(_T("放大"));
			SetWindowPos(NULL, curRect.left, curRect.top, m_small.Width(), m_small.Height(), SWP_NOMOVE | SWP_NOZORDER);
			//SetWindowPos(&wndTopMost, curRect.left, curRect.top, m_small.Width(), m_small.Height(), SWP_NOMOVE);
		}
	}
}

八、小项目-逃跑按钮

创建一个基于对话框的项目,为两个按钮添加变量-控件

给这个项目,类向导,添加MFC类

这是,两个按钮添加变量-控件,是属于CBUTTON类;CMyButton类是属于CButton的子类。

鼠标移动到按钮控件上的消息会被控件捕获,而不会给对话框

不信的话,可以在对话框中设置一个鼠标移动消息验证一下

TRACE("%s(%d):%s %d %d\n", __FILE__, __LINE__, __FUNCTION__, point x, point y);

项目思路:为两个按钮对象给出MouseMove方法,响应消息

两个按钮创建变量-控件后,控件就会被类关联;使用CMyButton 指向这两个控件变量

	CMyButton m_btn_light;
	CMyButton m_btn_left;

CMyButton中设置一个类指针

CMyButton* m_pButton;

在对话框初始化时关联起来

	m_btn_left.m_pButton = &m_btn_light;
	m_btn_light.m_pButton = &m_btn_left;

处理逻辑

void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	ShowWindow(SW_HIDE);
	if (m_pButton != NULL)
	{
		m_pButton->ShowWindow(SW_SHOW);
	}
	CButton::OnMouseMove(nFlags, point);
}

点击成功提示

void CRunningButtonDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	MessageBox(_T("恭喜你,点到我了"), _T("成功!"));
}

九、小项目-属性页添加

在八的基础上,给对话框添加一个新的按钮,点击后,会给出一个新的对话框

添加对话框资源

给新的对话框控件:Group Box,单选框,静态文本,列表

给这个对话框添加类,类向导,添加MFC类

给单选框添加控制变量-值,不必设置范围

这样做的意义就是有了对话框类,成员变量是控件的值,就可以拿到这些值了。

但是设置三个值记录太麻烦了,不如再次基础上魔改以下

修改为BOOL数组记录值

 修改初始化函数,和关联函数

为新对话框类重写初始化函数,选择这个类,属性,重写,选择要重写的类,要在初始化时为列表进行初始化,单选框不用,因为我们只需要获得它的状态。

BOOL PROP_01::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	// TODO:  在此添加额外的初始化
	// 因为GetDlgItem拿到根据ID拿控件的对象地址,默认类型时CWND,需要强制转换
	// 就可以通过地址来操作类的成员属性
	CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST_COMPANY);
	if (pListBox)
	{
		pListBox->AddString(_T("阿里巴巴"));
		pListBox->AddString(_T("华为"));
		pListBox->AddString(_T("腾讯"));
		pListBox->AddString(_T("京东"));
		pListBox->AddString(_T("百度"));
	}
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

按照上面方法再创建一个对话框,添加控件

为对话框添加MFC类,右击对话框,类向导,添加MFC类

为多选框添加控制变量-值,和上面一样

按照上面再添加一个,最后一个了

类向到,添加MFC类

添加控制变量-值

十、属性页处理

再追加一个MFC类,类向导,MFC类

将三个对话框作为成员变量添加给类 CMyProSheet

两个构造函数都要处理

父对话框触发点击事件

运行程序试试看

程序崩溃,尝试Debug,点击重试,程序就可以定位到崩溃处

问题出在这里

可能时对话框实例失败,验证以下,问题不在这里

查看调用堆栈,貌似也没啥问题,嗯?发现问题

查看路径下源码行处,发现对于处理单选框需要指定Group属性

单选框只能选一个,CTRL+D,可见Tab顺序

需要3,4,5是一个tab中,只需要再第一个单选框选中即可 GROUP=TRUE

那么单选框也就不需要数组了,Int 即可

接下来,优化对话框的上一步,下一步,去掉帮助按钮,未优化

优化:重写三个对话框类的激活方法(不是消息,是类的一个方法)

给公司添加控制变量

优化:重写OnwizardNext(),必须选择才能执行到下一步

十一、一些开发经验

需要初始化的控件可以在父窗口类初始化时进行。

添加控制变量(控件):值,可以拿到控件的值(编辑框的内容等等);控件,可以拿到控件的句柄保存到一个对象中。

将控制变量放到父窗口类中,我们可以自由拿到,通过父窗口对象操作控件

当需要处理控件的消息时,需要为控件添加控制变量到父窗口类中;如果想要处理该控件的消息,就需要实例化这个控件(所有控件都是继承自CWIND,都是窗口)。就需要创建出来一个类,利用多态,新类指向控制变量-控件,在新类中设置处理消息的函数,就可以了。参考八

获取窗口大小的操作都是放到初始化时完成的

在函数中不可实例化对象,因为函数结束对象销毁,不妨把要实例化的类放在类中,在函数中创建重绘。

添加MFC类,其实道理和八一样,对话框(控件)有了自己的类,就可以有更多操作的控件;再框架中要通过消息映射机制,操作空间有限

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/162557.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文章分类列表进行查询(实体类日期格式设置)

categoryController GetMappingpublic Result<List<Category>> list(){List<Category> cs categoryService.list();return Result.success(cs);} categoryService //列表查询List<Category> list(); categoryServiceImpl Overridepublic List<Cat…

科研学习|科研软件——面板数据、截面数据、时间序列数据的区别是什么?

一、数据采集方式不同 面板数据是通过在多个时间点上对同一组体进行观测而获得的数据。面板数据可以是横向面板数据&#xff0c;即对同一时间点上不同个体的观测&#xff0c;也可以是纵向面板数据&#xff0c;即对同一个体在不同时间点上的观测。采集面板数据需要跟踪相同的个体…

Idea安装完成配置

目录&#xff1a; 环境配置Java配置Maven配置Git配置 基础设置编码级设置File Header自动生成序列化编号配置 插件安装MyBtisPlusRestfulTooklkit-fix 环境配置 Java配置 Idea右上方&#xff0c;找到Project Settings. 有些版本直接有&#xff0c;有些是在设置下的二级菜单下…

哈希

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;unordered系列关联式容器un…

Java学习 10.Java-类和对象

一、面向对象的初步认知 1.1 什么是面向对象 面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情&#xff0c;用面向对象的思想来设计程序&#xff0c;更符合人们对事物的认知&#xff0c;对于大型程序的设计、拓展以及维护都非常友好 1.2 面向对…

Redisson 分布式锁实战应用解析

文章目录 前言一、Redisson介绍二、Redisson的使用1.1 引入依赖1.2 编写配置1.3 示例测试_011.4 示例测试_02 三、Redisson源码分析2.1 加锁源码2.2 看门狗机制 前言 分布式锁主要是解决分布式系统下数据一致性的问题。在单机的环境下&#xff0c;应用是在同一进程下的&#x…

2023年【陕西省安全员B证】考试报名及陕西省安全员B证模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年陕西省安全员B证考试报名为正在备考陕西省安全员B证操作证的学员准备的理论考试专题&#xff0c;每个月更新的陕西省安全员B证模拟试题祝您顺利通过陕西省安全员B证考试。 1、【多选题】《陕西省建设工程质量和…

运行ps软件提示由于找不到vcruntime140.dll无法继续执行代码怎么修复

今天我在打开ps时候突然电脑出现找不到vcruntime140.dll无法继续执行代码&#xff0c;我很困扰不知道什么原因&#xff0c;于是我花了一天时间在网上找了5个可以解决这个问题的方案分享给大家&#xff0c;同时我自己也解决了问题。分享给大家就是为了大家以后遇到这个问题不用像…

为什么Transformer模型中使用Layer Normalization(Layer Norm)而不是Batch Normalization(BN)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Vue3-自定义hook函数

Vue3-自定义hook函数 功能&#xff1a;可以将组合式API封装成一个函数&#xff0c;用于解决代码复用的问题。注意&#xff1a;需要在src文件夹下创建一个文件夹hooks&#xff0c;在里面放js文件&#xff0c;命名随意&#xff0c;主要是将setup函数中的代码放入js文件中。 // s…

基于token的鉴权机制-JWT

在实际开发项目中&#xff0c;由于Http是一种无状态的协议&#xff0c;我们想要记录用户的登录状态&#xff0c;或者为用户创建身份认证的凭证&#xff0c;可以使用Session认证机制或者JWT认证机制。 什么是JWT? 网络应用环境间传递声明执行的一种基于JSON的开放标准。适用于…

基于Adapter用CLIP进行Few-shot Image Classification

文章目录 【ECCV 2022】《Tip-Adapter: Training-free Adaption of CLIP for Few-shot Classification》【NeuIPS 2023】《Meta-Adapter: An Online Few-shot Learner for Vision-Language Model》 【ECCV 2022】《Tip-Adapter: Training-free Adaption of CLIP for Few-shot C…

第一次组会汇报(2023/11/18)

目录 一&#xff0c;浅谈学习规划 二&#xff0c; 两个比较典型的注意力机制 ㈠SEnet ⒈结构图 ⒉机制流程讲解 ⒊源码&#xff08;pytorch框架实现&#xff09;及逐行解释 ⒋测试结果 ㈡CBAM ⒈结构图 ⒉机制流程讲解 ⒊源码&#xff08;pytorch框架实现&#xff09;…

Docker命令

1. 基础命令 # 启动docker systemctl start docker # 关闭docker systemctl stop docker # 开机自启动docker systemctl enable docker 2. 镜像 ● 拉取centos镜像 docker pull 镜像名[:tag] 示例&#xff1a;docker pull centos:centos7 ● 查看本地主机所有镜像 docker i…

【刷题专栏—突破思维】LeetCode 138. 随机链表的复制

前言 随机链表的复制涉及到复制一个链表&#xff0c;该链表不仅包含普通的next指针&#xff0c;还包含random指针&#xff0c;该指针指向链表中的任意节点或空节点。 文章目录 原地修改链表 题目链接&#xff1a; LeetCode 138. 随机链表的复制 原地修改链表 题目介绍&#xf…

OpenAI的多函数调用(Multiple Function Calling)简介

我在六月份写了一篇关于GPT 函数调用&#xff08;Function calling) 的博客https://blog.csdn.net/xindoo/article/details/131262670&#xff0c;其中介绍了函数调用的方法&#xff0c;但之前的函数调用&#xff0c;在一轮对话中只能调用一个函数。就在上周&#xff0c;OpenAI…

Java中的集合内容总结——Collection接口

集合概述 Java 集合可分为 Collection 和 Map 两大体系&#xff1a; Collection接口&#xff1a;用于存储一个一个的数据。 List子接口&#xff1a;用来存储有序的、可以重复的数据&#xff08;主要用来替换数组&#xff0c;"动态"数组&#xff09; 实现类&#xf…

python的文件目录操作 1

我们在实际开发中&#xff0c;经常需要对文件进行读取、遍历、修改等操作&#xff0c;通过 python 的标准内置os模块&#xff0c;能够以简洁高效的方式完成这些操作。常见的操作整理如下&#xff1a; 文件夹操作&#xff1a;包括文件夹的创建、修改&#xff08;改名/移动&…

JS进阶——深入面向对象

1、编程思想 1.1 面向过程编程 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候再一个一个的一次调用就可以了。 1.2 面向对象编程&#xff08;oop&#xff09; 面向对象是把事务分解成为一个个对象&#xff0c;然…

【Hello Go】Go语言复合类型

复合类型 分类指针基本操作new函数指针作为函数的参数 数组概述操作数据数组初始化数组比较在函数之间传递数组 slice概述切片的创建和初始化切片操作切片和底层数组关系内建函数appendcopy 切片作为函数传参 map概述创建和初始化常用操作赋值遍历 删除map作函数参数 结构体结构…
最新文章