基於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界面。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章