MFC 2008,新的用户界面

来源:互联网 发布:round robin 算法代码 编辑:程序博客网 时间:2024/06/06 04:18

早听说Visual C++ 2008 FR1提供了很多新的功能,其中就包括MFC的新界面。现在拿到Visual Studio 2008 SP1简体中文版,急不可待的用了一下。果然,在向导中,就可以在工程里加入modern风格的界面了,可以模仿Office和Visual Stidio的界面风格。

阅读向导生成的代码发现,MFC用了一套新的框架类:

SDI:CFrameWndEx

MDI:CMDIFrameWndEx,CMDIChildWndEx

让我们先从框架类看起吧。
CFrameWndEx和CMDIFrameWndEx都是通过类CFrameImpl实现具体的框架绘制操作。CFrameWndEx和CMDIFrameWndEx都对我们熟悉的消息做了处理:

WM_NCHITTEST

WM_NCCALCSIZE

WM_NCPAINT

WM_NCMOUSEMOVE

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_ACTIVATEAPP

WM_MOUSEMOVE

WM_SIZE

WM_SIZING

......

这些消息的处理又是调用CFrameImpl完成的。

MFC能显示多种风格的界面,这是如何实现的呢?看到向导创建了如下的代码:

void CMainFrame::OnApplicationLook(UINT id){ CWaitCursor wait; theApp.m_nAppLook = id; switch (theApp.m_nAppLook) { case ID_VIEW_APPLOOK_WIN_2000:  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));  break; case ID_VIEW_APPLOOK_OFF_XP:  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));  break; case ID_VIEW_APPLOOK_WIN_XP:  CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));  break; case ID_VIEW_APPLOOK_OFF_2003:  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));  CDockingManager::SetDockingMode(DT_SMART);  break; case ID_VIEW_APPLOOK_VS_2005:  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));  CDockingManager::SetDockingMode(DT_SMART);  break; default:  switch (theApp.m_nAppLook)  {  case ID_VIEW_APPLOOK_OFF_2007_BLUE:   CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);   break;  case ID_VIEW_APPLOOK_OFF_2007_BLACK:   CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);   break;  case ID_VIEW_APPLOOK_OFF_2007_SILVER:   CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);   break;  case ID_VIEW_APPLOOK_OFF_2007_AQUA:   CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);   break;  }  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));  CDockingManager::SetDockingMode(DT_SMART); } RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE); theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);}

这段代码是切换界面风格的命令处理函数。CMFCVisualManager是UI界面的基类(事实上,他还有一个基类:CMFCBaseVisualManager),他提供类似于Windows2000风格的UI界面。其他几种UI界面类都是从它直接或间接派生的。SetDefaultManager用来设置不同的UI界面风格类。从上面的代码可以看出CMFCVisualManager是一个单件,一个程序只需要一个这样的类就可以了。

AFX_IMPORT_DATA static CMFCVisualManager* m_pVisManager;

当设置新界面风格时,SetDefaultManager销毁原来的界面风格类,创建新的界面风格类。界面风格类通过(RUNTIME_CLASS创建,这是一种工厂方法。MFC很早就使用这种方法创建对象了,比C++的RTTI出来得还早。

CMFCVisualManager提供了很多类似于OnNcPaint的虚函数,这些函数不用说就是用来绘制界面的。CFrameImpl正是调用CMFCVisualManager来实现界面绘制工作的,例如:

BOOL CFrameImpl::OnNcPaint(){ ASSERT_VALID(m_pFrame); if (!IsOwnerDrawCaption() || g_bInSettingChange) {  return FALSE; } return CMFCVisualManager::GetInstance()->OnNcPaint(m_pFrame, m_lstCaptionSysButtons, m_rectRedraw);}

看看应用程序类,这个类是MFC程序中必不可少的一个类。MFC用CWinAppEx替代了CWinApp。CWinAppEx从CWinApp派生。向导生成的代码中,主要是InitInstance这个函数有了变化。

LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU) InitContextMenuManager(); InitKeyboardManager(); InitTooltipManager(); CMFCToolTipInfo ttParams; ttParams.m_bVislManagerTheme = TRUE; theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,  RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);

MFC新增加鼠标管理器(CMouseManager)、键盘管理器(CKeyboardManager,管理加速键)、上下文菜单管理器(CContextMenuManager)、工具提示管理器(CTooltipManager)、外壳管理器(CShellManager)和用户工具管理器(CUserToolsManager),真是令人眼花撩乱。这些管理器可以通过CWinAppEx的函数访问。应用程序类在这里创建了上下文菜单管理器、键盘管理器和工具提示管理器。

CWinAppEx中有一对新的方法:LoadState()和SaveState()。LoadState在创建主框架时(CFrameImpl::OnLoadFrame)被调用,SaveState在销毁主框架之时(CFrameImpl::OnCloseFrame)调用。PreLoadState、PreSaveState、LoadCustomState和SaveCustomState是留给派生类使用的,它们在CWinAppEx中实现为空;它们在LoadState和SaveState中被分别调用。其实很多类都有LoadState和SaveState这一对方法,它们用这一对函数读取配置和保存配置。CWinAppEx在LoadState中读取各个管理器的状态,在SaveSate中保存各个管理器的状态。

LoadState、SaveSate和ClearState都是虚函数,意味着它们可以被派生类改写。

应用程序的状态通常被保存在注册表中,它的具体位置是:HKEY_CURRENT_USER/"Software"/RegistryKey/ProfileName,你可以用函数GetAppRegistryKey获取这个值。

 

 

原创粉丝点击