使用vs2010创建MFC C++ Ribbon程序

Your First MFC C++ Ribbon Application with Visual Studio 2010

Earlier this month, I put together my first C++ sample in about a hundred years. I did that using win32 and Visual Studio 2010. Why? Well, a surprising number of folks are doing real work on impressive applications in C++, and not just inside Microsoft. Some are even working on refacing C++ applications with WPF.

Besides, it‘s good to learn, or re-learn, new things. It often gives you a different perspective on how to solve problems. Plus, since I‘ll be doing some intro videos in C++, I figured it would be good to get back into it.

So, continuing in the same theme, I decided to try out MFC for the first time ... ever. I wrote some Borland OWL code back in the early 90s, but I‘m sure there are more differences than just TEverything vs. CEverything.

For the examples here, you‘ll need Visual Studio 2010 (I used the RC) and Windows 7. You can run it on older versions of Windows, but the Win7 ribbon style likely won‘t look the same.

In this sample we‘ll:

  • Create an MFC Document/View application with a ribbon control
  • Create a custom ribbon category
  • Add ribbon buttons
  • Change the application theme
  • Change the MDI tab container theme

Let‘s go!

Creating the Project

In Visual Studio 2010, pick the Visual C++ language. For many of us with language-specific IDE preferences, it‘s down under "Other Languages". Select MFC and then the MFC Application option.

Give your project a name and hit OK. As was the case in the Win32 project, you‘ll get an application Wizard that walks you through the startup steps.

The second page of the wizard has all the Application Type options. As someone who usually works inWPF and Silverlight, I am totally jealous! The wizard offers you options for Basic apps, Windows Explorer type apps, Office type apps and even Visual Studio type applications. You can even pick the styles and colors you want, right from this page:

For this sample, I picked the following options:

  • Multiple Documents (Tabbed)
  • Document/view architecture support (default)
  • English language (default)
  • Use Unicode Libraries (default)
  • Office project style
  • Office 2007 (Blue theme) visual style
  • Enable visual style switching (default)
  • Use MFC in a shared DLL (default)

The next page of the wizard offers you the ability to support compound documents / OLE embedding

I decided not to bother with that for this sample. Leave it at "none"

The next wizard page is for Document Template Properties. This allows you to create all the metadata for your document type. On this page, I typed in "hello" for the file extension

Next, we move on to Database support. If you‘re going to make calls into OLE DB or ODBC, you can set the right options here. I decided not to complicate things and instead just leave it at the default of "none"

Next stop, "User Interface Features." Are you kidding me? This is awesome. From this one step, you can stick with classic menus, menu bar and toolbar, or a ribbon. You can also set the style of your main window and, if traditional MDI, the child windows. Excellent! I left the defaults on, using a ribbon as the commandbar/menu choice.

The next tab is for advanced features. From here you can choose support for activeX controls, integration with MAPI (outlook/exchange), sockets and more. I left all the defaults in place

The final page shows you the classes that will be generated

Hit "Finish" and look at the generated project:

Nice! You get classes for your application and the windows, as well as for your document and document view. You also get a bunch of resources for the ribbon icons. Let‘s run this baby and see what it looks like.

Wow. Just...wow. Sure, that‘s a pretty busy app (selected a bunch of options), but that is a great structure coming right out of the wizard. Sure beats the blank slate we usually see. Here‘s a some close-ups

Ok, maybe I should have picked the Dialog project to do my first Hello World. There‘s a lot here! :) Nah. Let‘s have at this.

Modifying the Ribbon

One thing you noticed is that the design of the application is more Office 2007 and less Windows 7. That‘s ok. During the app wizard, had I chosen "Windows 7" instead of "Office 2007", I would have gotten the win7 style ribbons and UI.

The end result of combining "Office" with "Windows 7" looks a little hokey. Perhaps other combinations would work better.

So, we‘ll stick to the Office 2007 theme for this example. However, if you want to change it, since we support changing the overall theme and code was generated to handle that, all you need to change is the parameter that sets the "App Look":

// Office 2007 style
CMainFrame::CMainFrame()
{
    // TODO: add member initialization code here
    theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"),
        ID_VIEW_APPLOOK_OFF_2007_BLUE);
}

// Change to this for Windows 7 style
CMainFrame::CMainFrame()
{
    // TODO: add member initialization code here
    theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"),
        ID_VIEW_APPLOOK_WINDOWS_7);
}

Opening the Ribbon Resource Editor

Visual Studio includes a designer for the Ribbon. To use it, double click the MfcHelloWorld.rc file in the Resource Files folder. Your file may be named differently, but will have a "rc" extension. Then, find the Ribbon folder and double-click the IDR_RIBBON resource folder

Once you see the ribbon displayed, click on the toolbox to display the ribbon controls

Adding a Ribbon Category with Buttons

Drag a category from the Ribbon Editor toolbox next to the Home category on the ribbon resource editor. Give the category the caption "View" by right-clicking and selecting properties. Also set the keys property to "V" (for the accelerator key) and the large and small images the same as those used by "Home". If you were to use a different image set, you‘d put those keys here.

In the new "View" category, right-click the default panel and set its caption to "Theme". Then drag two buttons on to the Theme panel.

The first button has the following properties:

I picked some pre-existing images just to give the button something to size around. You‘d want to load in new images in a real application.

And a menu items collection with these items. We‘re reusing IDs from an existing function, so the IDs are important.

Windows 2000 ID_VIEW_APPLOOK_WIN_2000
Office XP ID_VIEW_APPLOOK_OFF_XP
Windows XP ID_VIEW_APPLOOK_WIN_XP
Windows 7 ID_VIEW_APPLOOK_WINDOWS_7
Visual Studio 2005 ID_VIEW_APPLOOK_VS_2005
Visual Studio 2008 ID_VIEW_APPLOOK_VS_2008
Office 2007 Blue ID_VIEW_APPLOOK_OFF_2007_BLUE
Office 2007 Black ID_VIEW_APPLOOK_OFF_2007_BLACK
Office 2007 Silver ID_VIEW_APPLOOK_OFF_2007_SILVER

The second button has these properties:

And a menu items collection with these items:

3D ID_TAB_THEME_3D
3D OneNote ID_TAB_THEME_3D_ONENOTE
3D Rounded ID_TAB_THEME_3D_ROUNDED
3D Visual Studio ID_TAB_THEME_3D_VISUAL_STUDIO
Flat ID_TAB_THEME_FLAT

The View category should look something like this when complete

If you run the application now, the theme buttons will be disabled.

Wiring up the Ribbon Buttons

Now to wire it all up.

In the MainFrm.h header file, add a prototype for OnAppTheme():

afx_msg void OnAppTheme();

In the code in MainFrm.cpp, around CMainFrame::OnApplicationLook, add the following empty function:

void CMainFrame::OnAppTheme()
{
}

Finally, inside the message map block in MainFrm.cpp, add the highlighted line (handler for ID_APP_THEME):

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
    ON_WM_CREATE()
    ON_COMMAND(ID_APP_THEME, &CMainFrame::OnAppTheme)
    ON_COMMAND(ID_WINDOW_MANAGER, &CMainFrame::OnWindowManager)
    ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
    ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
    ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar)
    ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar)
    ON_COMMAND(ID_TOOLS_OPTIONS, &CMainFrame::OnOptions)
END_MESSAGE_MAP()

If you don‘t take those three steps, the ribbon button will not be enabled. The handlers for the menu options themselves are already set, as they fall under the ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000 ... ) block.

Now run the application and switch between the various application themes using the new ribbon button. Pretty nice, eh? :)

Aside: Where the ribbon data is Stored

You may wonder where all that ribbon config information is stored. If you look under your resource files, you‘ll see a ribbon.mfcribbon-ms file. Double-click that and it will open in the XML editor so you can see the contents. The ribbon resource editor overwrites/modifies this file, so don‘t hand-edit it unless you know what to expect.

Changing the Document Tab Style

The previous example worked so well because we simply provided another UI entry point into existing code. What about brand new code? For this part, we‘ll implement an option to change the document tab style.

Create the Function Prototypes

In MainFrm.h, add our three prototype functions. The first is for the drop-down button, the second is for the menu options inside the button. The third is called by the button that sets the look.

afx_msg void OnTabTheme();
afx_msg void OnTabLook(UINT id);
afx_msg void OnUpdateTabLook(CCmdUI* pCmdUI);

Create the Functions

Next, create the actual functions in MainFrm.cpp. We‘ll add the implementation code shortly.

void CMainFrame::OnTabTheme()
{
}

void CMainFrame::OnTabLook(UINT id)
{
}

void CMainFrame::OnUpdateTabLook(CCmdUI* pCmdUI)
{
}

Add the Message Map

Inside the Message Map block in MainFrm.cpp, add the following three lines

ON_COMMAND(ID_TAB_THEME, &CMainFrame::OnTabTheme)
ON_COMMAND_RANGE(ID_TAB_THEME_3D, ID_TAB_THEME_FLAT, &CMainFrame::OnTabLook)
ON_UPDATE_COMMAND_UI_RANGE(ID_TAB_THEME_3D, ID_TAB_THEME_FLAT, &CMainFrame::OnUpdateTabLook)

Compile and run to make sure the app compiles and the tab theme button is enabled.

Add Application Field to Hold Tab Style

Open up MfcHelloWorld.h and add in the following:

public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();

// Implementation
    UINT  m_nAppLook;
    UINT  m_nTabLook;
    BOOL  m_bHiColorIcons;

The new line is line 6, m_nTabLook. Like m_nAppLook, this is going to hold an ID that specifies the look for the tab controls in the app.

Inside the constructor CMainFrame::CMainFrame in MainFrm.cpp, add the TabLook line right under the AppLook line. This will initialize the value from stored settings (or the default specified)

theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_OFF_2007_BLUE);
theApp.m_nTabLook = theApp.GetInt(_T("TabLook"), ID_TAB_THEME_3D_ONENOTE);

Inside CMainFrame::OnCreate in MainFrm.cpp, add in a new line for OnTabLook right under the call to OnApplicationLook. This will call our function to update the look.

OnApplicationLook(theApp.m_nAppLook);
OnTabLook(theApp.m_nTabLook);

Inside the same function, remove the lines that sets the Tab Control style. We‘re going to move these to another function, so you may want to just cut and paste them or comment them out for now. In any case, make sure they aren‘t present in the OnCreate function.

CMDITabInfo mdiTabParams;
mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // other styles available...
mdiTabParams.m_bActiveTabCloseButton = TRUE;      // set to FALSE to place close button at right of tab area
mdiTabParams.m_bTabIcons = FALSE;    // set to TRUE to enable document icons on MDI taba
mdiTabParams.m_bAutoColor = TRUE;    // set to FALSE to disable auto-coloring of MDI tabs
mdiTabParams.m_bDocumentMenu = TRUE; // enable the document menu at the right edge of the tab area
EnableMDITabbedGroups(TRUE, mdiTabParams);

Handle the Menu Button Click and Set the Field

OnUpdateTabLook takes an instance of a UI control. OnTabLook takes the command ID for a control. Following the pattern used by the application look, we‘ll set the radio button on our menu to indicate the current tab style.

void CMainFrame::OnTabLook(UINT id)
{
    theApp.m_nTabLook = id;

    theApp.WriteInt(_T("TabLook"), theApp.m_nTabLook);
}

void CMainFrame::OnUpdateTabLook(CCmdUI* pCmdUI)
{
    pCmdUI->SetRadio(theApp.m_nTabLook == pCmdUI->m_nID);
}

Now is a good time to save, build and run. When you select the menu to change the tab style, you should see the radio button change along with it. The tab theme won‘t change, but the menu will otherwise work. If you close and re-open the application, your selected theme should have the radio button next to it.

Actually Change the Tab Theme

Next we‘ll add in the switch statement to actually change the tab theme. open up some space in between the two lines in OnTabLook and add in the switch statement that handles all the tab looks we defined.

void CMainFrame::OnTabLook(UINT id)
{
    theApp.m_nTabLook = id;

    CMDITabInfo mdiTabParams;
    mdiTabParams.m_bActiveTabCloseButton = TRUE;      // set to FALSE to place close button at right of tab area
    mdiTabParams.m_bTabIcons = FALSE;    // set to TRUE to enable document icons on MDI taba
    mdiTabParams.m_bAutoColor = TRUE;    // set to FALSE to disable auto-coloring of MDI tabs
    mdiTabParams.m_bDocumentMenu = TRUE; // enable the document menu at the right edge of the tab area

    switch (theApp.m_nTabLook)
    {
    case ID_TAB_THEME_3D:
        mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D;
        break;

    case ID_TAB_THEME_3D_ONENOTE:
        mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE;
        break;

    case ID_TAB_THEME_3D_ROUNDED:
        mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ROUNDED;
        break;

    case ID_TAB_THEME_3D_VISUAL_STUDIO:
        mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_VS2005;
        break;

    case ID_TAB_THEME_FLAT:
        mdiTabParams.m_style = CMFCTabCtrl::STYLE_FLAT_SHARED_HORZ_SCROLL;
        break;
    }

    EnableMDITabbedGroups(TRUE, mdiTabParams);

    theApp.WriteInt(_T("TabLook"), theApp.m_nTabLook);
}

All we‘re doing in this function is mapping from the menu options to the built-in tab themes, and building a parameter set containing that style information as well as a few other options.

  

When you run the app, change the tab themes around and take a look at how the MDI tabs switch with them. Close and open the app, and notice that the settings are saved.

Feel free to play with the other tab parameter settings. For example, you can put the close button on the far right, you can stop the auto-coloring of the tabs, add or remove the document menu and even add icons. All very nice.

Conclusion

I‘m impressed. I have a feeling that, given the need, I could get up to speed in MFC in a reasonably short amount of time (not saying it would be good code, but it would work <g>). It helps that I did do windows programming in C++ a zillion years ago, so the concepts were familiar. It also helps that the MFC application wizard generates so much structure for your right out of the bad.

Ok MFC gurus. What did I do wrong in the above code? Any anti-patterns? Suggestions for improvement? I especially wonder about the empty functions in the message map just to enable the menu buttons.

http://10rem.net/blog/2010/03/25/your-first-mfc-cplusplus-ribbon-application-with-visual-studio-2010

时间: 2024-08-10 06:48:10

使用vs2010创建MFC C++ Ribbon程序的相关文章

C++ 使用VS2010创建MFC ActiveX工程项目

1.ActiveX的基本概念 ActiveX控件可以看作是一个极小的服务器应用程序,它不能独立运行,必须嵌入到某个容器程序中,与该容器一起运行.这个容器包括WEB网页,应用程序窗体等... ActiveX控件的后缀名是OCX或者DLL.一般是以OCX和动态库共存的形式打包成cab或者exe的文件放在服务器上,客户端下载后运行安装cab或exe解压成OCX和动态库共存的文件,然后注册ocx文件. ActiveX控件是基于com标准,使得软件部件在网络环境中进行交互的技术集.它与具体的编程语言无关.

c++ ActiveX基础1:使用VS2010创建MFC ActiveX工程项目

1.ActiveX的基本概念 ActiveX控件可以看作是一个极小的服务器应用程序,它不能独立运行,必须嵌入到某个容器程序中,与该容器一起运行.这个容器包括WEB网页,应用程序窗体等... ActiveX控件的后缀名是OCX或者DLL.一般是以OCX和动态库共存的形式打包成cab或者exe的文件放在服务器上,客户端下载后运行安装cab或exe解压成OCX和动态库共存的文件,然后注册ocx文件. ActiveX控件是基于com标准,使得软件部件在网络环境中进行交互的技术集.它与具体的编程语言无关.

VS2010开发MFC ActiveX,摄像头拍照上传Webservice(1)

最近工作项目,BS中需要用到摄像头拍照,需要存储本地,同时上传到服务器,尝试使用vc++做ActiveX来实现. 完全没有使用过vc,上网搜索各种知识,初步完成.在这里记录下有帮助的资料. 第一步:编写一个ActiveX 第二部:使用vfw.h开发摄像头拍照功能 第三步:裁剪,转换图并上传 转载出处:http://blog.csdn.net/longhuahaha/article/details/8556964 1.ActiveX的基本概念 ActiveX控件可以看作是一个极小的服务器应用程序,

VS 2008 创建MFC程序对话框的步骤

用过不少编程语言,可是刚开始学的时候最容易忘记一些简单的流程或者生疏了.那么这里就说说VS 2008 创建MFC程序对话框的步骤.我主要是android开发方面的.平时使用jni调用不少c++代码.所以就用到了调试c++代码的MFC啦. 1.文件--新建项目 2.选择对话框,然后就可以拖控件进行监听 3.起始对话框的类名 4.项目新建后,依次双击箭头指向就可看到可视化界面. 5.可视化对话框 这里就可以增加button,输入框以及监听事件,还有你的逻辑代码进行测试.

VS2010的MFC对话框程序中添加菜单栏的过程

VS2010的MFC对话框程序中添加菜单栏的过程 最近在看一个用MFC写的界面的项目的代码,在代码和界面中一直没有看到关于菜单控件是如何添加进对话框的,于是就百度了下.结果,与其它控件(Button等)添加的方式不一样: VS2010的MFC对话框程序中添加菜单栏的过程大致分了这五步. 一.将Menu加入Resource视图中 在WorkSpace中的Resource视图下,在左边目录的任意位置上,先右键-->选择Insert Resource(插入资源)选项,在弹出的对话框中选择Menu以后,

MFC Wizard创建的空应用程序中各个文件内容的解析

创建的MFC应用程序名为:wd,那么: 一.wd.h解析 // wd.h : main header file for the WD application // #if !defined(AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_) #define AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_ //////////////////////////////

VS2010远程调试你的程序vc++/wpf/C#/MFC

VS2010远程调试你的程序vc++/wpf/C#/MFC 1 背景说明 在进行设备控制软件开发的时候,需要进行设备的上机调试.我们在安装了工作环境(VS2010+Access+流程图等软件)的电脑上编码写好待调试的软件之后,待机器零配件和电气安装好之后,再在设备上进行调试,这个时候,设备会自带自己的工控电脑,这个工控电脑没有安装代码调试的软件.一般的解决办法是,将开发所需要的所有软件在目标工控机上再安装一遍,然后将代码拷贝到目标机,然后在目标机上修改代码和调试代码.这样做有一下几个缺点. (1

C++MFC编程笔记day01 MFC介绍、创建MFC程序和重写消息处理

一.MFC概念和作用 1.全称Microsoft Foundation Class Library,我们称为微软基础类库,封闭了绝大部分的win32 Api函数,C++语法中的数据结构,程序的执行流程 MFC就是一个库(动态库,静态库) MFC还是一个程序框架 2.为什么使用MFC 基于框架编程,提高工作效率,减少开发周期,节约开发成本. 二.几个重要的头文件 afx.h    -绝大部分类的声明头文件 afxwin.h -包含了afx.h和windows.h afxext.h -提供了扩展窗口

VS2012与VS2015同时安装用VS2012创建MFC程序时弹出编译错误”fatal error C1083: 无法打开包括文件:“mprapidef.h”: No such file or directory”的解决办法

在WIndows 7操作系统上同时安装VS2012与VS2015并用VS2012创建MFC程序时弹出编译错误"fatal error C1083: 无法打开包括文件:"mprapidef.h": No such file or directory"的解决办法: I installed vs2015 and vs2012, then the same problem occurs,however, I find a solution. open visual stud