自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Visual Studio 2010響應(yīng)Ribbon控件消息

開發(fā) 后端
利用XML文件定義和描述Ribbon界面,從分工的意義上講,其實(shí)那是UI設(shè)計(jì)師的活兒。作為程序員,更加專注的是如何令Visual Studio 2010響應(yīng)Ribbon控件,完成相應(yīng)的業(yè)務(wù)邏輯。

Visual Studio 2010與Windows 7的完美配合,在本文中體現(xiàn)在Visual Studio 2010響應(yīng)Ribbon控件消息上。UI美工們已經(jīng)幫我們完成了設(shè)計(jì)工作,下面現(xiàn)在,該輪到程序員上場了!51CTO編輯推薦《Visual Studio 2010應(yīng)用與開發(fā)詳解

在Ribbon界面編輯完成的基礎(chǔ)上,我們來看看如何利用Windows Scenic Ribbon API處理各種控件消息,讓Ribbon界面真正地投入使用。

如何利用XML文件創(chuàng)建Ribbon控件,對控件進(jìn)行排布和設(shè)置控件的縮放策略等等,可以說,這些工作都是UI設(shè)計(jì)師的任務(wù)。對程序員來說,更重要的是對控件的消息進(jìn)行處理實(shí)現(xiàn)其業(yè)務(wù)邏輯。

添加消息處理功能

我們可以創(chuàng)建了一個(gè)派生自IUIApplication的Ribbon界面宿主對象類CApplication,并利用這個(gè)類完成了Ribbon界面的創(chuàng)建,初始化以及與Windows應(yīng)用程序的集成。要對Ribbon控件的消息進(jìn)行處理,我們還是要借助這個(gè)宿主對象類。為了使得CApplication類具有控件消息處理的能力,我們需要修改它的定義,讓它同時(shí)也從IUICommandHandler派生。而IUICommandHandler類,則是Scenic Ribbon API提供給我們的控件消息處理類,只要CApplication從這個(gè)類派生,就具有了相應(yīng)的控件消息的處理能力。

為了對Visual Studio 2010響應(yīng)Ribbon控件消息進(jìn)行處理,我們修改CApplication類的定義如下:

  1. // 引入Scenic Ribbon API的頭文件  
  2. #include <uiribbon.h> 
  3. // 引入編譯生成的資源頭文件  
  4. #include "ribbonres.h"  
  5. // 調(diào)用Windows API獲得系統(tǒng)時(shí)間  
  6. #include "windows.h"  
  7. #include "stdio.h"  
  8.  
  9. IUIFramework* g_pFramework = NULL;  
  10. // Ribbon界面宿主程序  
  11. class CApplication  
  12.     : public CComObjectRootEx<CComMultiThreadModel> 
  13.         , public IUIApplication  // 處理Ribbon界面的創(chuàng)建和初始化  
  14.         , public IUICommandHandler // 處理Ribbon控件的消息 

然后,我們需要利用COM_INTERFACE_ENTRY宏定義COM_MAP,在CApplication類的定義中,添加:

  1. public:  
  2.     BEGIN_COM_MAP(CApplication)  
  3.           COM_INTERFACE_ENTRY(IUIApplication)  
  4.                   COM_INTERFACE_ENTRY(IUICommandHandler)  
  5.     END_COM_MAP() 

這樣,Visual Studio 2010響應(yīng)Ribbon控件的消息就會發(fā)送到CApplication類,由CApplication類進(jìn)行處理。在整個(gè)Scenic Ribbon API中,Ribbon控件消息的處理流程如下圖所示。除了之前我們介紹的跟Ribbon界面創(chuàng)建和初始化相關(guān)的過程之外,為了完成控件消息,我們首先需要為感興趣的控件進(jìn)行注冊,這些工作都會在OnCreateCommand函數(shù)中完成。完成控件的注冊后,當(dāng)我們需要進(jìn)行消息處理的控件有消息發(fā)生時(shí),IUIFramework就會將這些消息發(fā)送給CApplication,而我們就可以在CApplication類中對具體的消息進(jìn)行處理。Ribbon控件的消息主要分成兩種:一種是來自控件的動(dòng)作消息,比如按鈕控件被點(diǎn)擊,ComboBox的選擇發(fā)生了變化等。這類消息都在Execute函數(shù)中進(jìn)行處理;另外一種是則對控件屬性進(jìn)行更新的消息,這類消息在UpdateProperty函數(shù)中進(jìn)行處理。

UpdateProperty函數(shù)

注冊感興趣的控件

按照Ribbon界面控件消息的處理流程,我們首先需要在OnCreateCommand函數(shù)中為我們感興趣的控件進(jìn)行注冊,這樣當(dāng)控件有動(dòng)作發(fā)生的時(shí)候,CApplication類才會收到相應(yīng)的控件消息,進(jìn)而可以對其進(jìn)行處理。在CApplication類的OnCreateCommand函數(shù)中,我們完成相應(yīng)控件的注冊:

  1. STDMETHOD(OnCreateUICommand)(UINT32 nCmdID, __in UI_COMMANDTYPE typeID, __deref_out IUICommandHandler** ppCommandHandler)   
  2.     {   
  3.         // 對相應(yīng)控件的消息進(jìn)行注冊  
  4.         if (nCmdID == cmdMyButton   
  5.             || nCmdID == cmdDeleteTable  
  6.             || nCmdID == cmdAddTable  
  7.             || nCmdID == cmdPrintRelationships)  
  8.         {  
  9.             return QueryInterface(IID_PPV_ARGS(ppCommandHandler));  
  10.         }  
  11.         return E_NOTIMPL;   
  12.     } 

在這段代碼中,我們根據(jù)控件的Symbol選取了幾個(gè)需要進(jìn)行消息處理的控件,當(dāng)這幾個(gè)控件有動(dòng)作發(fā)生時(shí),比如比鼠標(biāo)點(diǎn)擊,或者是進(jìn)行了選擇,IUIFramework會發(fā)送相應(yīng)的消息給宿主對象CApplication,從而讓我們可以有機(jī)會對這些消息進(jìn)行處理。

處理控件消息

對于普通的控件點(diǎn)擊消息或者是選擇消息等動(dòng)作消息,我們需要重寫CApplication類的消息處理函數(shù)Execute函數(shù),在其中對消息進(jìn)行處理:

  1. // 消息處理函數(shù)  
  2. STDMETHODIMP Execute(UINT nCmdID,  
  3.         UI_EXECUTIONVERB verb,   
  4.         __in_opt const PROPERTYKEY* key,  
  5.         __in_opt const PROPVARIANT* ppropvarValue,  
  6.         __in_opt IUISimplePropertySet* pCommandExecutionProperties)  
  7.     {  
  8.         HRESULT hr = S_OK;  
  9.  
  10.         switch (verb)  
  11.         {  
  12.                         // 只處理感興趣的消息類型  
  13.         case UI_EXECUTIONVERB_EXECUTE:  
  14.                                     // 判斷消息來源  
  15.             if (nCmdID == cmdMyButton)  
  16.             {  
  17.                                                // 執(zhí)行具體的業(yè)務(wù)邏輯  
  18.                                                // 這里我們獲得系統(tǒng)時(shí)間并進(jìn)行輸出  
  19.                 SYSTEMTIME sys;  
  20.                 GetLocalTime( &sys );  
  21.                 wchar_t strInfo[256] = L"";  
  22.                 wsprintf( strInfo, L"當(dāng)前系統(tǒng)時(shí)間:  
  23. %4d/%02d/%02d %02d:%02d:%02d.%03d 星期%1d\n",  
  24.                     sys.wYear,sys.wMonth,sys.wDay,  
  25.                     sys.wHour,sys.wMinute,sys.wSecond,sys.wMilliseconds,  
  26.                     sys.wDayOfWeek);  
  27.                  // 顯示消息框  
  28.                                                  MessageBox(NULL, strInfo,  
  29.                     L"當(dāng)前系統(tǒng)時(shí)間”,  
  30.                     MB_OK);  
  31.             }  
  32.             break;  
  33.         }      
  34.         return hr;  
  35.     } 

現(xiàn)在編譯運(yùn)行這個(gè)解決方案,當(dāng)我們點(diǎn)擊cmdMyButton 所對應(yīng)的“MyButton”這個(gè)按鈕時(shí),就可以得到一個(gè)消息框報(bào)告當(dāng)前的系統(tǒng)時(shí)間。當(dāng)然,我們這里只是對按鈕控件的動(dòng)作進(jìn)行處理,對于其他類型控件的消息處理,都是按照相同的流程進(jìn)行。

按鈕控件的點(diǎn)擊事件
圖2  按鈕控件的點(diǎn)擊事件

在運(yùn)行時(shí)對控件屬性進(jìn)行修改

在某些情況下,我們需要在運(yùn)行時(shí)對控件的屬性進(jìn)行修改。例如,在應(yīng)用程序運(yùn)行的某種狀態(tài)下,我們可能需要禁用某些控件,或者是修改控件的標(biāo)簽文本,圖標(biāo)等等。對控件屬性的修改,可以通過直接修改控件屬性達(dá)到,也可以通過調(diào)用InvalidateUICommand函數(shù)刷新控件的屬性,然后在UpdateProperty函數(shù)中進(jìn)行控件屬性更改消息處理,實(shí)現(xiàn)具體的屬性修改。下面我們分別來看看這兩種方式是如何進(jìn)行的。

在這個(gè)例子中,我們處理兩個(gè)按鈕控件的點(diǎn)擊消息,讓他們分別禁用另外的按鈕控件和修改按鈕的標(biāo)簽文本。在Execute函數(shù)中,處理相應(yīng)的按鈕消息,實(shí)現(xiàn)控件屬性的改變:

  1. STDMETHODIMP Execute(UINT nCmdID,  
  2.         UI_EXECUTIONVERB verb,   
  3.         __in_opt const PROPERTYKEY* key,  
  4.         __in_opt const PROPVARIANT* ppropvarValue,  
  5.         __in_opt IUISimplePropertySet* pCommandExecutionProperties)  
  6.     {  
  7.         HRESULT hr = S_OK;  
  8.  
  9.         switch (verb)  
  10.         {  
  11.         case UI_EXECUTIONVERB_EXECUTE:  
  12.             if (nCmdID == cmdMyButton)  
  13.             {  
  14.                 //  
  15.                 PROPVARIANT varNew;  
  16.  
  17.                 BOOL _fEnabled = FALSE;  
  18.                                                 // 初始化屬性值  
  19.                 hr = UIInitPropertyFromBoolean(UI_PKEY_Enabled,  
  20.                                                          _fEnabled, &varNew);  
  21.                 if (FAILED(hr))  
  22.                 {  
  23.                     return hr;  
  24.                 }  
  25.                                                 // 為控件cmdDeleteTable設(shè)置新的屬性值  
  26.                 hr = g_pFramework->SetUICommandProperty(cmdDeleteTable,   
  27.                                                         UI_PKEY_Enabled, varNew);  
  28.                 if (FAILED(hr))  
  29.                 {  
  30.                     return hr;  
  31.                 }  
  32.             }  
  33.             else if (nCmdID == cmdAddTable)  
  34.             {  
  35.                 // 發(fā)送屬性更新消息對控件屬性UI_PKEY_Label進(jìn)行更新  
  36.                 hr = g_pFramework->InvalidateUICommand(  
  37.                                                              cmdPrintRelationships,  
  38.                                                              UI_INVALIDATIONS_PROPERTY, &UI_PKEY_Label);  
  39.                 if (FAILED(hr))  
  40.                 {  
  41.                               return hr;  
  42.                 }  
  43.             }  
  44.             break;  
  45.         }      
  46.         return hr;  
  47.     } 

在cmdMyButton按鈕的消息處理中,我們使用SetUICommandProperty就可以直接修改控件的屬性了。在這里,我們通過設(shè)置cmdDeleteTable按鈕控件的UI_PKEY_Enabled屬性為FALSE,達(dá)到了禁用這個(gè)控件的目的。而在cmdAddTable按鈕的消息處理中,我們只是調(diào)用了IUIFramework的InvalidateUICommand函數(shù),這表示它會自動(dòng)調(diào)用CApplication類的UpdateProperty來實(shí)現(xiàn)控件屬性的更新,所以對于第二種方式,我們還需要實(shí)現(xiàn)這個(gè)函數(shù),在其中完成屬性的更新:

  1. STDMETHODIMP UpdateProperty(UINT nCmdID,  
  2.         __in REFPROPERTYKEY key,  
  3.         __in_opt const PROPVARIANT* ppropvarCurrentValue,  
  4.         __out PROPVARIANT* ppropvarNewValue)  
  5.     {  
  6.         UNREFERENCED_PARAMETER(ppropvarCurrentValue);  
  7.  
  8.         HRESULT hr = E_FAIL;  
  9.  
  10.         if (key == UI_PKEY_Label)  
  11.         {  
  12.             // 更新控件cmdPrintRelationships的標(biāo)簽文本  
  13.             if (nCmdID == cmdPrintRelationships)  
  14.             {  
  15.                 hr = UIInitPropertyFromString(UI_PKEY_Label,   
  16.                         L"New Label", ppropvarNewValue);  
  17.             }  
  18.         }  
  19.         return hr;  
  20.     } 

現(xiàn)在,我們就可以編譯運(yùn)行整個(gè)解決方案,點(diǎn)擊相應(yīng)的按鈕控件,就可以看到對控件屬性修改的效果了:

修改控件屬性
圖3  修改控件屬性

到這里,我們完成了整個(gè)Ribbon歷程:從創(chuàng)建XML文件到添加宿主對象,從創(chuàng)建到初始化,從控件消息處理到控件屬性更新。現(xiàn)在,Ribbon界面對我們來說,已經(jīng)不再僅僅是微軟的一種界面技術(shù),她切切實(shí)實(shí)地來到了我們身邊,可以為我們所用,提高應(yīng)用程序的用戶體驗(yàn)。

擁抱Ribbon,擁抱Windows 7,擁抱Visual Studio 2010!

【編輯推薦】

  1. 微軟稱C++將得到Visual Studio 2010更多支持
  2. Visual Studio 2010新特性:動(dòng)態(tài)語言功能
  3. 微軟對Visual Studio 2010的Bug熟視無睹?
  4. Visual Studio 2010 Beta1試用手記
  5. Visual Studio 2010重要新功能一覽
責(zé)任編輯:彭凡 來源: ITPUB
相關(guān)推薦

2010-04-16 14:08:46

Visual Stud

2009-11-12 12:42:35

Visual Stud

2010-02-23 09:02:00

Visual Stud

2009-12-02 09:43:38

Visual Stud

2009-11-13 09:05:05

Visual Stud

2009-11-10 13:43:37

Visual Stud

2009-11-11 09:48:06

Visual Stud

2010-02-22 16:43:33

Visual Stud

2009-11-13 10:12:37

Visual Stud

2010-04-12 08:43:45

Visual Stud

2009-11-11 14:26:13

Visual Stud

2009-11-13 14:59:12

Visual Stud

2010-04-06 17:32:02

Visual Stud

2011-02-13 17:10:28

Visual Stud

2009-12-11 13:14:45

Visual Stud

2009-11-10 15:27:42

Visual Stud

2010-04-16 14:22:07

Visual Stud

2009-12-02 10:58:13

Visual Stud

2009-05-19 09:01:16

微軟.NETVisual Stud

2010-03-11 14:37:47

Visual StudScrum
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號