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);
	}
}
相关推荐
程序员JerrySUN13 分钟前
驱动开发硬核特训 · Day 1
java·linux·运维·开发语言·c++·驱动开发
Vitalia26 分钟前
⭐算法OJ⭐数据流的中位数【最小堆】Find Median from Data Stream
数据结构·c++·算法·最小堆
Rainbow Sea39 分钟前
自定义实现C++拓展pytorch功能
c++·pytorch·python
仟濹1 小时前
【C/C++】双指针与前缀和
c语言·c++·算法
我言秋日胜春朝★1 小时前
【C++11】特殊类的设计 && 单例模式 && 类型转换
开发语言·c++·单例模式
矛取矛求1 小时前
STL c++ list——模拟实现
c++
阿巴~阿巴~2 小时前
二分 —— 基本算法刷题路程
数据结构·c++·算法
徽京人2 小时前
第八届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组 购物单
c++·职场和发展·蓝桥杯
半桔2 小时前
哈希表(开散列)的实现
数据结构·c++·面试·散列表·哈希
Do vis.5762 小时前
set map 代理模式思维导图
c++