如何在MFC单框架中实现类似浏览器的多页面切换功能
MFC类浏览器独立页面切换规范实现方案
核心实现逻辑
- 每个独立业务页面单独封装为
CDialog派生类,内置自身控件、消息响应、业务逻辑,与主窗口完全解耦 - 主窗口仅负责页面的调度、切换,不需要处理具体页面的内部逻辑
- 切换页面时采用隐藏/显示方式,无需反复销毁重建控件,性能更稳定
优化后完整实现代码
#include <afxwin.h> #include <afxext.h> // 先定义页面ID #define IDD_LOGIN_PAGE 1001 #define IDD_HOME_PAGE 1002 #define LOGIN_BTN 5 #define LOGOUT_BTN 6 // 登录页面类:独立封装登录页所有逻辑 class CLoginPage : public CDialog { public: CLoginPage(CWnd* pParent = nullptr) : CDialog(IDD_LOGIN_PAGE, pParent) {} protected: virtual BOOL OnInitDialog() override { CDialog::OnInitDialog(); // 登录页控件全部在这创建,不用写在主窗口 CButton* loginBtn = new CButton(); loginBtn->Create( "Login", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(CPoint(100, 60), CSize(150, 25)), this, LOGIN_BTN); return TRUE; } DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CLoginPage, CDialog) END_MESSAGE_MAP() // 登录后主页面类:独立封装登录后所有逻辑 class CHomePage : public CDialog { public: CHomePage(CWnd* pParent = nullptr) : CDialog(IDD_HOME_PAGE, pParent) {} protected: virtual BOOL OnInitDialog() override { CDialog::OnInitDialog(); // 主页(登出按钮所在页)控件全部在这创建 CButton* logoutBtn = new CButton; logoutBtn->Create( "Logout", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(CPoint(40, 32), CSize(200, 70)), this, LOGOUT_BTN); return TRUE; } DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CHomePage, CDialog) END_MESSAGE_MAP() class CMainFrame: public CFrameWnd { CPoint mCoordinate; CSize mDimension; // 主窗口维护所有页面实例 CLoginPage* m_pLoginPage; CHomePage* m_pHomePage; CWnd* m_pCurrentPage; // 当前激活的页面 public: CMainFrame() { // Get primary screen resolution int widthScreen = GetSystemMetrics(SM_CXSCREEN); int heightScreen = GetSystemMetrics(SM_CYSCREEN); // Set size and position to middle screen mDimension.cx = 280; mDimension.cy = 133; mCoordinate.x = (widthScreen / 2) - (mDimension.cx / 2); mCoordinate.y = (heightScreen / 2) - (mDimension.cy / 2); Create( NULL, "Pandora", WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, CRect(mCoordinate, mDimension)); // 初始化所有页面,只创建一次 m_pLoginPage = new CLoginPage(this); m_pLoginPage->Create(IDD_LOGIN_PAGE, this); m_pLoginPage->SetWindowPos(nullptr, 0, 0, mDimension.cx, mDimension.cy, SWP_NOZORDER); m_pLoginPage->ShowWindow(SW_SHOW); m_pHomePage = new CHomePage(this); m_pHomePage->Create(IDD_HOME_PAGE, this); m_pHomePage->SetWindowPos(nullptr, 0, 0, mDimension.cx, mDimension.cy, SWP_NOZORDER); m_pHomePage->ShowWindow(SW_HIDE); m_pCurrentPage = m_pLoginPage; }; ~CMainFrame() { // 销毁页面资源 if (m_pLoginPage) delete m_pLoginPage; if (m_pHomePage) delete m_pHomePage; } // 页面切换公共方法 void SwitchPage(CWnd* pTargetPage) { if (pTargetPage == m_pCurrentPage || pTargetPage == nullptr) return; m_pCurrentPage->ShowWindow(SW_HIDE); pTargetPage->ShowWindow(SW_SHOW); m_pCurrentPage = pTargetPage; } protected: afx_msg int OnCreate(LPCREATESTRUCT); afx_msg void login(); afx_msg void logout(); DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(LOGIN_BTN, &CMainFrame::login) ON_COMMAND(LOGOUT_BTN, &CMainFrame::logout) END_MESSAGE_MAP() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { return 0; }; void CMainFrame::login() { SwitchPage(m_pHomePage); }; void CMainFrame::logout() { SwitchPage(m_pLoginPage); }; class CApplication : public CWinApp { BOOL InitInstance() { CMainFrame* mainWnd = new CMainFrame(); m_pMainWnd = mainWnd; mainWnd->ShowWindow(SW_NORMAL); mainWnd->UpdateWindow(); return TRUE; } }; CApplication app;
扩展说明
如果需要新增更多页面,只需要按照以下步骤操作即可,符合类浏览器多页面的扩展要求:
- 新建对应业务的
CDialog派生类,封装自身的控件和逻辑 - 在主窗口中新增该页面的实例变量,初始化时创建该页面
- 新增对应的切换触发逻辑,调用
SwitchPage方法即可完成跳转
内容的提问来源于stack exchange,提问作者juragan
相关产品推荐
相关产品推荐

