MFC实现堆栈窗口:多个子界面可任意切换

1、效果

  在Qt中可使用QStackedWidget控件直接拖动布置即可实现,但在MFC中并未提供类似的控件,因此需要自己简单实现。

2、实现原理

  实现原理比较简单,父级对话框在显示的区域部分,通过切换子对话框即可实现。子对话框去掉边框后移动到父级对话框的显示区域即可。需要注意的是子对话框需要用非模态方式创建,同时记得在父级对话框销毁指针。

3、源码

cpp 复制代码
// SwitchChildrenDlgDlg.h: 头文件

#pragma once

#include "CChild1Dlg.h"
#include "CChild2Dlg.h"

// CSwitchChildrenDlgDlg 对话框
class CSwitchChildrenDlg : public CDialogEx
{
// 构造
public:
	CSwitchChildrenDlg(CWnd* pParent = nullptr);	// 标准构造函数
	virtual ~CSwitchChildrenDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_SWITCHCHILDRENDLG_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	//afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnBnClickedOk();
	afx_msg void OnBnClickedCancel();
	afx_msg void OnCbnSelchangeComboType();
private:
	CChild1Dlg* m_Child1Dlg;
	CChild2Dlg* m_Child2Dlg;
	CComboBox m_cmbType;
};
cpp 复制代码
CSwitchChildrenDlg::CSwitchChildrenDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_SWITCHCHILDRENDLG_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

CSwitchChildrenDlg::~CSwitchChildrenDlg()
{
	if (m_Child1Dlg)
	{
		delete m_Child1Dlg;
		m_Child1Dlg = nullptr;
	}

	if (m_Child2Dlg)
	{
		delete m_Child2Dlg;
		m_Child2Dlg = nullptr;
	}
}

BOOL CSwitchChildrenDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将"关于..."菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	if (!m_Child1Dlg)
	{
		m_Child1Dlg = new CChild1Dlg(this);
		m_Child1Dlg->Create(IDD_CHILD1_DLG, this);
	}

	if (!m_Child2Dlg)
	{
		m_Child2Dlg = new CChild2Dlg(this);
		m_Child2Dlg->Create(IDD_CHILD2_DLG, this);
	}

	m_cmbType.AddString(_T("地域"));
	m_cmbType.AddString(_T("范围"));
	m_cmbType.SetCurSel(0);
	OnCbnSelchangeComboType();

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CSwitchChildrenDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_cmbType.GetCurSel() == 0)
	{
		m_Child1Dlg->OnBnClickedOk();
	}
	else if (m_cmbType.GetCurSel() == 1)
	{
		m_Child2Dlg->OnBnClickedOk();
	}

	CDialogEx::OnOK();
}

void CSwitchChildrenDlg::OnCbnSelchangeComboType()
{
	// TODO: 在此添加控件通知处理程序代码
	CRect cltrect;
	GetClientRect(cltrect);//获取当前主对话框的坐标

	if (m_cmbType.GetCurSel() == 0)
	{
		m_Child1Dlg->ShowWindow(SW_SHOW);
		m_Child2Dlg->ShowWindow(SW_HIDE);
		//设置动态对话框的位置
		m_Child1Dlg->SetWindowPos(&wndTop, cltrect.left + 10, cltrect.top + 30, cltrect.Width(), cltrect.Height() - 100, SWP_NOACTIVATE);
	}
	else if (m_cmbType.GetCurSel() == 1)
	{
		if (!m_Child2Dlg)
		{
			m_Child2Dlg = new CChild2Dlg(this);
			m_Child2Dlg->Create(IDD_CHILD2_DLG, this);
		}
		m_Child2Dlg->ShowWindow(SW_SHOW);
		m_Child1Dlg->ShowWindow(SW_HIDE);
		//设置动态对话框的位置
		m_Child2Dlg->SetWindowPos(&wndTop, cltrect.left + 10, cltrect.top + 30, cltrect.Width(), cltrect.Height() - 100, SWP_NOACTIVATE);
	}
}
相关推荐
fqbqrr9 小时前
2607C++,使用微软detours勾挂工具
c++
蓝悦无人机12 小时前
C++基础 — 函数总结
开发语言·c++
我不是懒洋洋14 小时前
从零实现一个分布式监控:Prometheus的核心设计
c++
An_s14 小时前
c++对接pdfium(一)win系统篇
开发语言·c++
众少成多积小致巨14 小时前
C++ 规范参考(上)
c++
一拳一个呆瓜17 小时前
【STL】iostream 编程:使用提取运算符
c++·stl
我不是懒洋洋18 小时前
从零实现一个分布式日志平台:ELK的核心设计
c++
神仙别闹19 小时前
基于QT(C++)实现Windows 自启动项查看和分析
c++·windows·qt
fpcc19 小时前
数据结构和算法—拓扑的应用
数据结构·c++·算法
王老师青少年编程19 小时前
csp信奥赛C++高频考点专项训练:【排序算法】案例1:三位数排序
c++·排序算法·csp·高频考点·信奥赛·三位数排序