基于Windows 7中的 Ribbon开发技术应用

简介:
 
Windows 7的画图工具采用了微软所称的Scenic Ribbon 界面,这种界面起初是在Office 2007中出现的,也在WordPad出现过。虽然很多用户还在抱怨 “不习惯Ribbon界面”、“很多功能找不到位置”等等,但是,随着微软的“强制”推行,Ribbon界面也在越来越被人们所接受, 很多应用软件也开始采用Ribbon界面。更重要的是,在即将到来的Windows 7中,操作系统本身更是大量地应用了Ribbon界面。不管我们愿意或者不愿意,Ribbon界面开始大张旗鼓地攻占我们的软件界面,成为继下拉式菜单后新的标准用户界面。作为用户,我们需要逐渐熟悉这种新的软件用户界面;而作为开发者,更是需要了解和认识这种新的软件用户界面,新的交互方式,从而利于这种新界面的优势,为用户提供更加优秀的软件。“Ribbon来了!”
 
      为了支持开发人员,微软正在确保其设备驱动程序和应用模式在Vista和Windows 7 之间不变,以确保其兼容性。但是公司正在努力工作使开发人员接触Windows 7的新技术,以使他们能够在他们自己的解决方案中应用一些新的高级特性。这包括诸如Jump Lists,PowerShell(《Windows Powershell应用编程最佳实践》此书我正在编写中6月左右出版),“画图”的Scenic Ribbon control以及写字板,以及其它的组件。
     
 在Office 2007之后介绍了这个Scenic Ribbon.许多昂贵的商业解决方案都已经用到它。但最后,在即将推出的windows 7,微软推出了Scenic Ribbon.在这里我第一次尝试在实例中使用从而在这里讲解出来。Scenic Ribbon是一个在ActiveX对象附加在窗口上,它的整个宽度的窗口,它的高度可配置的。它的尺寸会根据你的需要而调整。Ribbon从一个XML中获得显示数据。这意味着您只使用几个函数调用,一些初始化并加载数据,以及一个意外事件处理程序触发Ribbon。由于Ribbon是一个ActiveX界面,应用程序在XP或Vista下使用会初始化失败,但它会继续运行。当创建的XML时 ,运行intentcl.exe程序,创建项目工程文件。 
 
• 创建一个IUIFramework
IUIFramework *  u_f  =   0 ;
HRESULT hr 
=  CoCreateInstance(CLSID_ScenicIntentUIFramework,
             
0 ,CLSCTX_ALL,__uuidof(IUIFramework),( void ** ) & u_f); 
 
• 执行一个IUIApplication
这个界面(除了IUnknown成员)有以下三个功能:
  1、当一个命令创建时调用ribbon:
virtual  HRESULT __stdcall OnCreateUICommand(UINT32 commandId,
        UI_COMMANDTYPE typeID,IUICommandHandler 
** commandHandler); 
2、 当ribbon被一个命令是释放时:
virtual  HRESULT __stdcall OnDestroyUICommand(UINT32 commandId, 
        UI_COMMANDTYPE typeID,IUICommandHandler 
* commandHandler); 
3、当ribbon变化时,视图也被相应的改变:
virtual  HRESULT __stdcall OnViewChanged(UINT32 viewId,UI_VIEWTYPE typeID, 
        IUnknown 
* view,UI_VIEWVERB verb,INT32 uReasonCode); 
 •调用IUIFramework::Initialize( )与父窗口的ribbon,和执行IUIApplication 。 
•调用IUIFramework::LoadUI( )与HINSTANCE和资源名称。
 
下面的图解释了需要采取的步骤,以实现一个简单的Ribbon应用。
 
     
 命令处理程序OnCreateUICommand是调用每一个命令。看看下面的命令是XML格式。必须返回一个执行IUICommandHandler(AddRef ()+!)将处理命令两个成员函数:
 
HRESULT __stdcall UpdateProperty(UINT32 commandId,REFPROPERTYKEY key,
        
const  PROPVARIANT  * currentValue,PROPVARIANT  * newValue); 
当命令调用执行时。这个“verb”是UI_EXECUTIONVERB枚举,并通知您,触发什么样的事件,例如,字体选择下拉,一个按钮按下等使用OnDestroyUICommand时,将没有必要了调用接口,但不调用Release() 。Ribbon将调用它。这只是通知你的目的是要被销毁,而不是请求释放它自己。
nViewChanged允许从IUIFramework和查询其状态请求一个接口。如果typeId == UI_VIEWTYPE_RIBBON和verb== UI_VIEWVERB_CREATE或UI_VIEWVERB_SIZE 例如,这会告诉你,ribbon创建或改变大小,这样你就可以查询IUnknown指IUIRibbon并获得其预期的高度。
为了避免上述所有的问题,把这些接口包装到类库。一个RIBBON类,并且你使用如下:
RIBBON(HWND hh  =   0 );
~ RIBBON();
bool  Initialize(); 
Ribbon初始化成功返回Ture
bool  LoadMarkup(HINSTANCE hInst,LPCWSTR resourceName); 
Ribbon初始化成功返回Ture
bool LoadMarkup(HINSTANCE hInst,LPCWSTR resourceName);
从资源里加载ribbon,如果现有的ribbon被加载,则释放它。
void DestroyMarkup();
销毁加载的ribbon。
int& DesiredHeight();
返回理想高度ribbon
void SetHeight(int);
允许设置ribbon高度
 
      调用类库向父窗口发送一个预定义的MESSAGE_RIBBON (const int MESSAGE_RIBBON = RegisterWindowMessage(L"{E733E4DA-904C-486b-B5FB-6201773D69DE}");),
与WPARAM设置为RIBBON *类,和LPARAM设置为RIBBON_MESSAGE结构:
struct  RIBBON_MESSAGE
{
 IUIFramework 
*  u_f;       //  Pointer to the IUIFramework of the ribbon
 UINT32 cmd;             //  Command ID 
 UINT32 reason;                  //  Reason code (When View is changed)
 UI_COMMANDTYPE type;            //  Type of the command
 UI_VIEWTYPE vtype;              //  Verb Type of the view change (When View is changed)
 UI_VIEWVERB vverb;              //  Verb of the view change (When View is changed)
 UI_EXECUTIONVERB verb;          //  Verb of the command
  const  PROPERTYKEY *  key;         //  Contains the new value
  const  PROPVARIANT *  cv;          //  Contains the current value
 IUISimplePropertySet *  pset;     //  Contains an interface which you can set/query values
  void *  view;                     //  Contains an IUnknown* of the view interface
                                
//  (when view is changed) which you
                                
//  can use to query for an IUIRibbon.
  bool  update;                    //  true if view is changed.
 }; 
 
因此,如果您只是想重定向消息到WM_COMMAND ,您检查update ==false,erb== UI_EXECUTIONVERB_EXECUTE ,和type == UI_COMMANDTYPE_ACTION 。
LRESULT CALLBACK Main_DP(HWND hh,UINT mm,WPARAM ww,LPARAM ll)
 {
 
if  (mm  ==  MESSAGE_RIBBON)
         {
        RIBBON_MESSAGE
*  rm  =  (RIBBON_MESSAGE * )ll;
        
if  ( ! rm)
        
if  (rm -> update  ==   false   &&  rm -> verb  ==  UI_EXECUTIONVERB_EXECUTE 
                                
&&  rm -> type  ==  UI_COMMANDTYPE_ACTION)
            SendMessage(hh,WM_COMMAND,rm
-> cmd, 0 );
        }

}
 分析Ribbon的XML数据格式由于ribbon本质上是一个代表性的一个XML地图,在这里您将实际花费大部分的时间来制定一个好的和工作ribbon.。
 
ribbon基本要素:一套命令,每个人可以有一个ID,一个符号,一个标签,一个提示,和一套图像。您定义这些命令为“按钮”和其他因素,如标签或一组标签。 
一套要素,包括一个“应用程序的菜单” ,一个“快速访问工具栏”“ribbon” ,其中载有一些标签。每个标签可以有一些组,每个组都可以有一些预定义的控制。
 
这些组都必须标明具体的“大小”和布局;所以举例来说,如果你想说, 6组内的按钮,你只有三种预定义的方式,安排他们。 
这里是一组实例命令:
< Command  Name ="cmdNew"  LabelTitle ="New"  Symbol ="cmdNew"  
  Comment
="New"  Id ="22001"  TooltipTitle ="Tooltip Title"  
  TooltipDescription
="Tooltip Text" >
     
< Command.SmallImages >
        
< Image > 1-32a.bmp </ Image >  
      
</ Command.SmallImages >
      
< Command.LargeImages >
        
< Image > 1-32a.bmp </ Image >
      
</ Command.LargeImages >
    
</ Command >
< Command  Name ="cmdOpen"  LabelTitle ="Open"  
   Symbol
="cmdOpen"  Comment ="Open"  Id ="22002"   />
< Command  Name ="cmdSave"  LabelTitle ="Save"  
   Symbol
="cmdSave"  Comment ="Save"  Id ="22003"   />
< Command  Name ="Tab1"  LabelTitle ="First Tab"  Symbol ="_44"  Id ="30001" />
< Command  Name ="Tab2"  LabelTitle ="Second Tab"  Id ="30002" />
< Command  Name ="cx1"  LabelTitle ="Check Box 1"   />
< Command  Name ="Font1"  LabelTitle ="Font Selection1"   />
< Command  Name ="cpick1"  LabelTitle ="Choose Color"   />
< Command  Name ="cmdn1"  LabelTitle ="Main Menu"   />
< Command  Name ="g1"  LabelTitle ="Group 1"   />  
 
请注意, “按钮”命令,将需要的图片(小16x16 ,或大32x32,或64x64点英寸,但我已经发现,ribbon大的图像调整得很好) ,但其他的“命令”像标签标或
一组标签只需要姓名和头衔,因为没有命令编号与他们有联系的。
以下是如何创造一个“应用程序的菜单”:
  < Ribbon.ApplicationMenu >
    
< ApplicationMenu  CommandName ="cmdn1" >
      
< MenuGroup  Class ="MajorItems" >
        
< Button  CommandName ="cmdNew"   />
        
< Button  CommandName ="cmdOpen"   />
        
< Button  CommandName ="cmdSave"   />
      
</ MenuGroup >
    
</ ApplicationMenu >
</ Ribbon.ApplicationMenu >  
 
现在,你有一个应用程序的菜单中有三个按钮:新建,打开,保存。 以下是如何建立快速访问工具栏:
< Ribbon.QuickAccessToolbar >
     
< QuickAccessToolbar  CustomizeCommandName ="cmdCustomize" >
         
< QuickAccessToolbar.ApplicationDefaults >
             
< Button  CommandName ="cmdNew"   />
         
</ QuickAccessToolbar.ApplicationDefaults >
     
</ QuickAccessToolbar >
</ Ribbon.QuickAccessToolbar >  
 
现在,你有一个快速访问工具栏的新的内部指令,加上一个按钮“ cmdCustomize ”这应该可以自定义快速访问工具栏。请注意,Ribbon使用户可以改变按钮,出现在快速访问工具栏。
而且,这里是如何创建一个标签与一些组:
< Ribbon.Tabs >
            .
    
< Tab  CommandName ="Tab1"   >
      
< Tab.ScalingPolicy >
        
< ScalingPolicy >
          
< ScalingPolicy.IdealSizes >
            
< Scale  Group ="g1"  Size ="Large"   />
            
< Scale  Group ="g2"  Size ="Large"   />
            
< Scale  Group ="g3"  Size ="Large"   />
            
< Scale  Group ="g4"  Size ="Large"   />
          
</ ScalingPolicy.IdealSizes >
        
</ ScalingPolicy >
      
</ Tab.ScalingPolicy >
      
< Group  CommandName ="g1"  SizeDefinition ="OneButton" >
        
< Button  CommandName ="cmdNew"   />
      
</ Group >
      
< Group  CommandName ="g2"  SizeDefinition ="ThreeButtons" >
        
< Button  CommandName ="cmdNew"   />
        
< Button  CommandName ="cmdOpen"   />
        
< Button  CommandName ="cmdSave"   />
        
< DialogLauncher  CommandName ="cmdSave"   />
      
</ Group >
      
< Group  CommandName ="g3"  SizeDefinition ="OneFontControl" >
        
< FontControl  CommandName  = "Font1"   FontType  = "RichFont"   />
      
</ Group >
      
< Group  CommandName ="g4" >
        
< DropDownColorPicker  CommandName ="cpick1"  ChipSize  = "Large"   />
      
</ Group >
</ Tab >  
 
注意,该标签已经提到命令“ Tab1 ”其中包含的标签名称。此标签有四个组,缩放的政策不是任意设置为“大” , “中等”或“小” ,但它依赖于一些控制和布局模板。
 
这意味着,如果您的组是“ OneButton ” ,它必须被设置为“大”规模的大小。 
有一个预定义的一些模板,但你也可以使用<SizeDefinition>定制模板。您可以查看示例的自定义模板。 每个小组可以有许多事情,包括按钮,旋转按钮,下拉,字体控制,颜色选择器,对话框启动器,分离器,和所有的东西中描述的标记元素网页。我的上述4组有一些按钮,字体选择和颜色选择器.我们如何获得从颜色选择器值?检查type == UI_COMMANDTYPE_COLORANCHOR和PROPVARIANT “cv”值包含一个整数,代表的RGB 。 
我们如何获得字体选择值?该类型UI_COMMANDTYPE_FONT和PROPVARIANT “cv”值包含一个IUnknown ,但我还没有找到如何获得让字体!
 
根据您的应用程序的背景,您可能需要一些标签和/或组显示或者隐藏。明确的插入每一个组/标签,ribbon提供了“应用模式” ,这是一个32位模式的字节设置,他们应该是“active” 。应用模式适用于组和标签。
例如,这里的定义是在“ Tab1 ”
<Tab CommandName="Tab1" ApplicationModes="0,2">
 
这意味着,当位0或2位在当前选定的模式设置,然后在标签的显示。因此,当我请Ribbon:: SetModes ( 0 ) ,此标签将会隐藏。当我使用2个或8或任何整数,那么0或2位设置,该标签将显示。 同样可以很容易的适用于程序组。

<Group CommandName="g1" SizeDefinition="OneButton" ApplicationModes="3">
    
为了获取/设置ribbon管理的一些状态,。您可以使用IUIFramework::  GetUICommandProperty获得一个特殊键,或者您也可以查询“cv” IUnknown成员通过RIBBON_MESSAGE结构的IPropertyStore ;使用GetValue ( ) / SetValue ( ) /提交到读/写性能引用控制。还有一些“整体”键,您查询IUIFramework直接的IPropertyStore 。 
例如,当我得到通知, WndProc的颜色选择,它适用于它的背景颜色的ribbon如下:
PROPVARIANT val;
//  Get the property of the control we pushed
HRESULT hr  =  rm -> u_f -> GetUICommandProperty(rm -> cmd,UI_PKEY_Color, & val); 
IPropertyStore
*  st  =   0 ;
rm
-> u_f -> QueryInterface(__uuidof(IPropertyStore),( void ** ) & st);
if  (st  &&  SUCCEEDED(hr))
 {
 st
-> SetValue(UI_PKEY_GlobalBackgroundColor,val);
 st
-> Commit();
  }
 
如果在字体控制,您只需查询IUnknown 指针* pointer的IPropertyStore和使用UI_PKEY_FontProperties_XXXX键。
     
 
总结:随着Windows平台的发展升级,往往都伴随着系统图形界面的重新设计。从Windows XP到Windows Vista,最大的革新就是Windows Aero的引入。而在微软的下一代Windows平台Windows 7中,虽然Aero被保留下来,但是Windows 7的图形用户界面更多的是朝着Office 2007相同的方向前进,无论是系统自带的工具软件,例如画图、写字板等,还是上层的第三方应用软件,例如Office 2007 ,AutoCAD、SnagIt等等,都全面应用了Ribbon界面。

 

本文转自高阳 51CTO博客,原文链接:http://blog.51cto.com/xiaoyinnet/196081 ,如需转载请自行联系原作者

相关文章
|
7天前
|
安全 前端开发 Windows
Windows Electron 应用更新的原理是什么?揭秘 NsisUpdater
本文介绍了 Electron 应用在 Windows 中的更新原理,重点分析了 `NsisUpdater` 类的实现。该类利用 NSIS 脚本,通过初始化、检查更新、下载更新、验证签名和安装更新等步骤,确保应用的更新过程安全可靠。核心功能包括差异下载、签名验证和管理员权限处理,确保更新高效且安全。
18 4
Windows Electron 应用更新的原理是什么?揭秘 NsisUpdater
|
29天前
|
XML 缓存 前端开发
Electron-builder 是如何打包 Windows 应用的?
本文首发于微信公众号“前端徐徐”,作者徐徐深入解析了 electron-builder 在 Windows 平台上的打包流程。文章详细介绍了 `winPackager.ts`、`AppxTarget.ts`、`MsiTarget.ts` 和 `NsisTarget.ts` 等核心文件,涵盖了目标创建、图标处理、代码签名、资源编辑、应用签名、性能优化等内容,并分别讲解了 AppX/MSIX、MSI 和 NSIS 安装程序的生成过程。通过这些内容,读者可以更好地理解和使用 electron-builder 进行 Windows 应用的打包和发布。
103 0
|
30天前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
26 0
|
1月前
|
数据可视化 程序员 C#
C#中windows应用窗体程序的输入输出方法实例
C#中windows应用窗体程序的输入输出方法实例
46 0
|
1月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
63 0
|
2月前
|
存储 安全 程序员
Windows任务管理器开发原理与实现
Windows任务管理器开发原理与实现
|
3月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
68 0
|
3月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
182 0
|
3月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
242 0
|
3月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
57 0