MFC上位机实现界面切换
配置界面
首先按照下面的路线找到你的主对话框资源
资源视图-----Dialog-----IDD_你的工程名_DIALOG

先删除没用的控件 两个按钮控件 (确定)( 取消)
还有中间的一段描述文字

按钮文字是给人看的,ID 是给程序看的。
IDC表明是控件的ID
BTN表明是button按钮控件
最后一位一般都来描述功能语义
在属性栏更改三个按钮的ID
第一个按钮 ID:IDC_BTN_HOME
第二个按钮 ID:IDC_BTN_PARAM
第三个按钮 ID:IDC_BTN_ABOUT
下一步就是在资源视图中添加对话框资源

在资源视图中右键项目资源
选择 添加资源
选择 Dialog
点击 新建
这样会新增一个新的对话框资源。
给每个对话框资源改 ID
选中每个新对话框,在属性窗口中改它的 ID:
IDD_DLG_PAGE_HOME
IDD_DLG_PAGE_PARAM
IDD_DLG_PAGE_ABOUT
正好对应三个按钮

方便测试结果 可以先给三个子页面加上三个静态文本来描述对应页面
我这里就不赘述了 比较简单
下一步 为子页面资源创建对应类
这里开始把"资源"和"类"关联起来
1.给首页资源添加类
在资源视图中选中 IDD_DLG_PAGE_HOME 点击对话框资源
右键选择添加类名:CPageHomeDlg
基类默认就行:CDialogEx

另外两个类也是同理
创建好后应该是这种:

cpp
// jialiDlg.h: 头文件
//
#pragma once
// CjialiDlg 对话框
class CjialiDlg : public CDialogEx
{
// 构造
public:
CjialiDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_JIALI_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
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()
};
这是我们默认的主对话框文件 还没有进行编写代码 我们可以通过
cpp
class CjialiDlg : public CDialogEx
了解到CjialiDlg是主对话框类名
现在我们将在.h文件中进行编写代码
cpp
private:
enum PAGE_INDEX
{
PAGE_HOME = 0,
PAGE_PARAM,
PAGE_ABOUT
};//先定义这几个页面的编号
cpp
private:
CPageHomeDlg m_pageHome;
CPageParamDlg m_pageParam;
CPageAboutDlg m_pageAbout;
这里简单插一句
你在CPageHomeDlg.h文件能看到定义的类名CPageHomeDlg
cpp
class CPageHomeDlg : public CDialogEx
{
}
然后你用CPageHomeDlg 去定义一个对象叫m_pageHome
这里和C语言中结构体去定义变量思路类似
定义的m_pageHome 是主界面控制首页页面的入口
后面对首页的一切操作,都会通过 m_pageHome 完成
继续编写.h代码
cpp
void InitPages();
专门负责页面初始化,获取页面显示区域位置,创建三个子页面
独封装成函数
如果把这些代码全放进 OnInitDialog(),后面不好维护
cpp
void SwitchPage(int nPage);//页面切换
还有三个按钮的响应函数
cpp
afx_msg void OnBnClickedBtnHome();
afx_msg void OnBnClickedBtnParam();
afx_msg void OnBnClickedBtnAbout();
修改完的.h文件结构应该如下:
cpp
// jialiDlg.h: 头文件
//
#pragma once
#include "CPageAboutDlg.h"
#include "CPageHomeDlg.h"
#include "CPageParamDlg.h"
// CjialiDlg 对话框
class CjialiDlg : public CDialogEx
{
// 构造
public:
CjialiDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_JIALI_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
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()
private:
enum PAGE_INDEX
{
PAGE_HOME = 0,
PAGE_PARAM,
PAGE_ABOUT
};
private:
CPageHomeDlg m_pageHome;
CPageParamDlg m_pageParam;
CPageAboutDlg m_pageAbout;
private:
void InitPages();
void SwitchPage(int nPage);
public:
afx_msg void OnBnClickedBtnHome();
afx_msg void OnBnClickedBtnParam();
afx_msg void OnBnClickedBtnAbout();
};
现在进行.c文件的编写
cpp
BOOL CjialiDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 初始化....
InitPages();//添加
return TRUE;
}
cpp
void CjialiDlg::InitPages()
{
CRect rect;
GetDlgItem(IDC_STATIC_PAGE_AREA)->GetWindowRect(&rect);
ScreenToClient(&rect);
m_pageHome.Create(IDD_DLG_PAGE_HOME, this);
m_pageParam.Create(IDD_DLG_PAGE_PARAM, this);
m_pageAbout.Create(IDD_DLG_PAGE_ABOUT, this);
m_pageHome.MoveWindow(&rect);
m_pageParam.MoveWindow(&rect);
m_pageAbout.MoveWindow(&rect);
m_pageHome.ShowWindow(SW_HIDE);
m_pageParam.ShowWindow(SW_HIDE);
m_pageAbout.ShowWindow(SW_HIDE);
}
我们现在的方案并不是
点首页就创建首页
点参数就销毁首页再创建参数
而是:
启动时
把 3 个页面都创建出来,摆在同一个位置。
选择谁显示 然后让其他两个页面隐藏
详细讲解一下 InitPages() 这个函数
cpp
CRect rect;
CRect 是 MFC 里表示矩形区域的一个类。
它本质上描述一个矩形框的位置。
通常包含 4 个值:
left
top
right
bottom
这 4 个值是什么意思
left = 100
top = 50
right = 500
bottom = 350
那它表示一个矩形:
左边界在 x=100
上边界在 y=50
右边界在 x=500
下边界在 y=350
所以这个例子里:
宽 = 500 - 100 = 400
高 = 350 - 50 = 300
因为我们需要一个变量,来保存:
页面显示区域的位置和大小
后面三个页面都要用它来定位。
cpp
GetDlgItem(IDC_STATIC_PAGE_AREA)->GetWindowRect(&rect);
ScreenToClient(&rect);
IDC_STATIC_PAGE_AREA 是我们当时在主页面添加的静态文字
但是他现在就是一个占位框的
以后所有子页面都摆到这块区域里
不写死坐标是因为将来维护的时候 界面有布局有大变化的话会很麻烦
GetDlgItem(IDC_STATIC_PAGE_AREA)
在当前主对话框里,找到 ID 为 IDC_STATIC_PAGE_AREA 的那个控件
返回的是一个控件指针 CWnd*
然后获取这个占位控件在屏幕上的矩形坐标,保存到 rect
ScreenToClient(&rect);
是坐标切换 因为GetWindowRect拿到的是整个屏幕的坐标
需要切换成对话框内的坐标
补全剩下的函数在,c文件中
cpp
void CjialiDlg::SwitchPage(int nPage)
{
m_pageHome.ShowWindow(SW_HIDE);
m_pageParam.ShowWindow(SW_HIDE);
m_pageAbout.ShowWindow(SW_HIDE);
switch (nPage)
{
case PAGE_HOME:
m_pageHome.ShowWindow(SW_SHOW);
break;
case PAGE_PARAM:
m_pageParam.ShowWindow(SW_SHOW);
break;
case PAGE_ABOUT:
m_pageAbout.ShowWindow(SW_SHOW);
break;
default:
m_pageHome.ShowWindow(SW_SHOW);
break;
}
}
void CjialiDlg::OnBnClickedBtnHome()
{
SwitchPage(PAGE_HOME);
}
void CjialiDlg::OnBnClickedBtnParam()
{
SwitchPage(PAGE_PARAM);
}
void CjialiDlg::OnBnClickedBtnAbout()
{
SwitchPage(PAGE_ABOUT);
}

实现效果 三个按钮可以换出三个子页面
后面会继续更新MFC的相关简单应用