Visual Studio 2010的新特性里面Ribbon界面是一个很重要的东西,Ribbon界面非常易用和高效,也不去强调和证明它将成为未来应用程序界面的一种趋势。为了让我们的应用程序“Ready for Windows 7”,我们有必要根据实际的情况需要,为我们的应用程序添加Ribbon界面。
为了推广Ribbon界面,为了讨好程序员们,让程序员可以轻松地为各种应用程序创建Ribbon界面,微软真是不遗余力,不断地推出新的Ribbon界面接口。为了可以让所有基于C++的普通Windows应用程序都可以添加Ribbon界面,微软在Windows 7 SDK中,又推出了基于COM的接口——Scenic Ribbon API。
利用Scenic Ribbon API,我们可以更加灵活方便地为各种Windows应用程序添加Ribbon界面,改善应用程序的用户体验。在接下来的文章中,我们就介绍一下如何利用这种新的方式为普通Windows应用程序添加Ribbon界面。
我们都知道,Ribbon界面是随着Office 2007一同发布的。在过去的几年中,微软不断地吸取用户对Ribbon界面的反馈,不断地对其进行改进,到了Windows 7,微软正式加入了命名为Scenic Ribbon的第二代Ribbon界面,即取代第一代Ribbon的升级版本。随着Scenic Ribbon成为Windows 7的一部分以及微软所提供的Scenic Ribbon API,这意味着今后第三方程序开发者能在自己开发的应用程序中免费用上这种界面形式。Scenic Ribbon作为第二代Ribbon界面,所适用的是所有的Windows应用程序,和前代有所不同是理所当然的。例如,由于最初Ribbon界面是Office专用,因此使用Ribbon界面的Office 2007程序窗口左上角都有一个比较显眼的Office图标按钮。当应用到其他程序之后,这个图标显然不能继续存在,因此在Scenic Ribbon中,这个位置就被相应应用程序自身的图标所取代。另外,为了满足各种应用程序的需要,Scenic Ribbon还添加了部分Ribbon控件,使得Ribbon界面的控件更加丰富,能够应对各种应用程序对Ribbon界面控件的需要。值得一提的是,Office作为Ribbon界面的开山鼻祖,到了Office的下一个版本Office 2010,也全面使用了Scenic Ribbon以替代第一代Ribbon界面。
同时微软在VisualC++2010也提供了Ribbon资源设计器,使Ribbon开发更加简单快捷。
Scenic Ribbon API是一套基于COM的非托管API。通过这套API,我们可以为所有基于Windows的非托管应用程序创建Ribbon界面面板,添加Ribbon控件,处理Ribbon控件的各种动作,执行某种业务逻辑等等。而至于Ribbon界面的布局,各个控件的位置和属性等,则是通过基于XAML的xml文件来进行定义和描述的。编译器会将这个XML文件编译成相应的资源文件,头文件和二进制的BML文件。而Scenic Ribbon API最终会读取这些描述控件信息的文件并创建Ribbon界面。在业务逻辑层,Scenic Ribbon API提供了相应的Execute函数来处理所有控件的消息,在其中我们可以完成相应的业务逻辑。
在Windows 7中,微软还为我们提供了用于为非托管代码(Native)应用程序创建Ribbon界面的Scenic Ribbon API的解决方案。另外,针对基于WPF的托管代码应用程序,微软还将提供另外的基于WPF的Ribbon界面解决方案。
Firefox 3.7已经采用Windows7的Ribbon界面。
下面我们亲自来动手构建一个基于VisualC++2010开发windows7的tabelt pc应用的WindowsRibbon范例
1.帅气的VS2010启动画面,启动VS2010
2.创建inkdoc的MFC工程
3.MFC向导1
4.MFC向导2,选择中文界面,多文档程序,以及windows7风格
5.MFC向导3,跳过
6.MFC向导4,创建文档格式,文件名
7.MFC向导5。跳过
8.MFC向导6,选择Ribbon
9.MFC向导7,设置高级选项
10.MFC设置8,设置CFORMVIEW,
11.打印提示,不理睬,直接跳过
12.VisualC++2010自带的Ribbon编辑器
13.操作与工具箱控件一样操作,设置按钮属性
14.设置按钮
15.设置按钮属性,
16.为按钮添加事件
17.类似菜单的操作
18.在Formview,选择对话框,插入flash控件,然后为flash添加MFC activeX 类向导
19.插入flash控件类
帅的惊动了优快云的windows7的tabelt pc应用的WindowsRibbon范例的效果图
tablet PC的轨迹核心代码如下
#include <windows.h> #include <comdef.h> #include <msinkaut.h> #include <msinkaut_i.c> //包含windows SDK for windows7的核心tabletpc头文件 #include "resource.h" const TCHAR* gc_szAppName = TEXT("Basic Recognition"); // 建立轨迹指针,识别指针,轨迹画板指针 IInkCollector * g_pIInkCollector = NULL; IInkDisp * g_pIInkDisp = NULL; IInkRecognizerContext * g_pIInkRecoContext = NULL; //定义初始化变量 const LPOLESTR gc_pwsInputScopes[] = { L"(!IS_DEFAULT)", L"(!IS_URL)", L"(!IS_FILE_FULLFILEPATH)", L"(!IS_FILE_FILENAME)", L"(!IS_EMAIL_USERNAME)", L"(!IS_EMAIL_SMTPEMAILADDRESS)", L"(!IS_LOGINNAME)", L"(!IS_PERSONALNAME_FULLNAME)", L"(!IS_PERSONALNAME_PREFIX)", L"(!IS_PERSONALNAME_GIVENNAME)", L"(!IS_PERSONALNAME_MIDDLENAME)", L"(!IS_PERSONALNAME_SURNAME)", L"(!IS_PERSONALNAME_SUFFIX)", L"(!IS_ADDRESS_FULLPOSTALADDRESS)", L"(!IS_ADDRESS_POSTALCODE)", L"(!IS_ADDRESS_STREET)", L"(!IS_ADDRESS_STATEORPROVINCE)", L"(!IS_ADDRESS_CITY)", L"(!IS_ADDRESS_COUNTRYNAME)", L"(!IS_ADDRESS_COUNTRYSHORTNAME)", L"(!IS_CURRENCY_AMOUNTANDSYMBOL)", L"(!IS_CURRENCY_AMOUNT)", L"(!IS_DATE_FULLDATE)", L"(!IS_DATE_MONTH)", L"(!IS_DATE_DAY)", L"(!IS_DATE_YEAR)", L"(!IS_DATE_MONTHNAME)", L"(!IS_DATE_DAYNAME)", L"(!IS_DIGITS)", L"(!IS_NUMBER)", L"(!IS_ONECHAR)", L"(!IS_TELEPHONE_FULLTELEPHONENUMBER)", L"(!IS_TELEPHONE_COUNTRYCODE)", L"(!IS_TELEPHONE_AREACODE)", L"(!IS_TELEPHONE_LOCALNUMBER)", L"(!IS_TIME_FULLTIME)", L"(!IS_TIME_HOUR)", L"(!IS_TIME_MINORSEC)", L"((0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?-? ?)?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?-? ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9)", L"(!IS_PERSONALNAME_FULLNAME)|((!IS_PERSONALNAME_PREFIX)? +(!IS_PERSONALNAME_GIVENNAME)+ +(!IS_PERSONALNAME_MIDDLENAME)* +(!IS_PERSONALNAME_SURNAME)+)", L"MN(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)(A|B)(!IS_DIGITS)(X|Y)((0|1)*)" }; const LONG gc_lMaxInputScopeMenuItemLength = 40; // 定义笔势常量 const InkApplicationGesture gc_igtSingleStrokeGestures[] = { IAG_Scratchout, IAG_Triangle, IAG_Square, IAG_Star, IAG_Check, IAG_Circle, IAG_DoubleCircle, IAG_Curlicue, IAG_DoubleCurlicue, IAG_SemiCircleLeft, IAG_SemiCircleRight, IAG_ChevronUp, IAG_ChevronDown, IAG_ChevronLeft, IAG_ChevronRight, IAG_Up, IAG_Down, IAG_Left, IAG_Right, IAG_UpDown, IAG_DownUp, IAG_LeftRight, IAG_RightLeft, IAG_UpLeftLong, IAG_UpRightLong, IAG_DownLeftLong, IAG_DownRightLong, IAG_UpLeft, IAG_UpRight, IAG_DownLeft, IAG_DownRight, IAG_LeftUp, IAG_LeftDown, IAG_RightUp, IAG_RightDown, IAG_Tap }; const UINT gc_nRecommendedForMixedMode[] = { 0 /*Scratchout*/, 3/*Star*/, 6/*Double Circle*/, 7 /*Curlicue*/, 8 /*Double Curlicue*/, 25 /*Down-Left Long*/ }; const InkApplicationGesture gc_igtMultiStrokeGestures[] = { IAG_ArrowUp, IAG_ArrowDown, IAG_ArrowLeft, IAG_ArrowRight, IAG_Exclamation, IAG_DoubleTap }; const _ATL_FUNC_INFO IInkRecognitionEventsImpl<CAdvRecoApp>::mc_AtlFuncInfo = {CC_STDCALL, VT_EMPTY, 3, {VT_UNKNOWN, VT_VARIANT, VT_I4}}; const _ATL_FUNC_INFO IInkCollectorEventsImpl<CAdvRecoApp>::mc_AtlFuncInfo[2] = { {CC_STDCALL, VT_EMPTY, 3, {VT_UNKNOWN, VT_UNKNOWN, VT_BOOL|VT_BYREF}}, {CC_STDCALL, VT_EMPTY, 4, {VT_UNKNOWN, VT_UNKNOWN, VT_VARIANT, VT_BOOL|VT_BYREF}} }; const TCHAR gc_szAppName[] = TEXT("优快云专家尹成的程序,http://blog.youkuaiyun.com/yincheng01"); ///////////////////////////////////////////////////////// // //清除Com指针 ///////////////////////////////////////////////////////// void Cinkdoc::CleanUp() // Release all objects { if (g_pIInkRecoContext != NULL) { g_pIInkRecoContext->Release(); g_pIInkRecoContext = NULL; } if (g_pIInkDisp != NULL) { g_pIInkDisp->Release(); g_pIInkDisp = NULL; } if (g_pIInkCollector != NULL) { g_pIInkCollector->Release(); g_pIInkCollector = NULL; } } void Cinkdoc::Reco() //识别{ //获取识别结果,并显示最优化识别结果 &n