SDI實現多檢視並切換檢視
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控制元件類
帥的驚動了CSDN的windows7的tabelt pc應用的WindowsRibbon範例的效果圖
tablet PC的軌跡核心程式碼如下
[cpp] view plain copy print?- #include <windows.h>
- #include <comdef.h>
- #include <msinkaut.h>
- #include <msinkaut_i.c> //包含windows SDK for windows7的核心tabletpc標頭檔案
- #include "resource.h"
- constTCHAR* 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)*)"
- };
- constLONG 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
- };
- constUINT 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}}
- };
- constTCHAR gc_szAppName[] = TEXT("CSDN專家尹成的程式,http://blog.csdn.net/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() //識別
- {
- //獲取識別結果,並顯示最優化識別結果
- HCURSOR hCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
- //獲取軌跡指標用於識別
- IInkStrokes* pIInkStrokes = NULL;
- HRESULT hr = g_pIInkDisp->get_Strokes(&pIInkStrokes);
- if (SUCCEEDED(hr))
- {
- hr = g_pIInkRecoContext->putref_Strokes(pIInkStrokes);
- if (SUCCEEDED(hr))
- { //利用識別指標獲取識別結果
- IInkRecognitionResult* pIInkRecoResult = NULL;
- InkRecognitionStatus RecognitionStatus;
- hr = g_pIInkRecoContext->Recognize(&RecognitionStatus, &pIInkRecoResult);
- if (SUCCEEDED(hr) && (pIInkRecoResult!= NULL))
- {
- BSTR bstrBestResult = NULL;
- hr = pIInkRecoResult->get_TopString(&bstrBestResult);
- pIInkRecoResult->Release();
- pIInkRecoResult = NULL;
- if (SUCCEEDED(hr) && bstrBestResult)
- {
- MessageBoxW(hwnd, bstrBestResult,
- L"識別結果", MB_OK);
- SysFreeString(bstrBestResult);
- }
- }
- g_pIInkRecoContext->putref_Strokes(NULL);
- }
- pIInkStrokes->Release();
- }
- ::SetCursor(hCursor);
- }
- void Cinkdoc::start() // 開始建立
- {
- //並建立com指標介面
- HRESULT hr;
- hr = CoCreateInstance(CLSID_InkRecognizerContext,
- NULL, CLSCTX_INPROC_SERVER,
- IID_IInkRecognizerContext,
- (void **) &g_pIInkRecoContext);
- if (FAILED(hr))
- {
- return -1;
- }
- hr = CoCreateInstance(CLSID_InkCollector,
- NULL, CLSCTX_INPROC_SERVER,
- IID_IInkCollector,
- (void **) &g_pIInkCollector);
- if (FAILED(hr))
- return -1;
- hr = g_pIInkCollector->get_Ink(&g_pIInkDisp);
- if (FAILED(hr))
- return -1;
- hr = g_pIInkCollector->put_hWnd((long)this->hwnd);
- if (FAILED(hr))
- return -1;
- hr = g_pIInkCollector->put_Enabled(VARIANT_TRUE);
- if (FAILED(hr))
- return -1;
- }
- //筆勢事件
- HRESULT Cinkdoc::OnGesture(
- IInkCursor* /*pIInkCursor*/,
- IInkStrokes* pInkStrokes,
- VARIANT vGestures,
- VARIANT_BOOL* pbCancel
- )
- {
- if (((VT_ARRAY | VT_DISPATCH) != vGestures.vt) || (NULL == vGestures.parray))
- return E_INVALIDARG;
- if (0 == vGestures.parray->rgsabound->cElements)
- return E_INVALIDARG;
- / /陣列中的手勢應該是排序的承認
- / /置信水平。此示例拿起最高之一。
- / /注意:當在InkAndGesture收集模式,除了預期的手勢
- / /應用程式也有可能是帶著身份證IAG_NoGesture手勢物件
- / /此應用程式時,如果取消與ISG_NoGesture物件
- / /最高水平的信心陣列(第一項)。
- InkApplicationGesture idGesture = IAG_NoGesture;
- IDispatch** ppIDispatch;
- HRESULT hr = ::SafeArrayAccessData(vGestures.parray, (void HUGEP**)&ppIDispatch);
- if (SUCCEEDED(hr))
- {
- CComQIPtr<IInkGesture> spIInkGesture(ppIDispatch[0]);
- if (spIInkGesture != NULL)
- {
- hr = spIInkGesture->get_Id(&idGesture);
- }
- ::SafeArrayUnaccessData(vGestures.parray);
- }
- / /載入資源字串表的姿態名稱
- UINT idGestureName;
- bool bAccepted; // will be true, if the gesture is known to this application
- if (IAG_NoGesture != idGesture)
- {
- bAccepted = GetGestureName(idGesture, idGestureName);
- }
- else
- {
- bAccepted = false;
- idGestureName = 0;
- }
- //如果當前的收集模式ICM_GestureOnly或者如果我們接受
- //的姿態,手勢的中風將被刪除從墨跡物件,
- //因此,視窗需要在招'區更新。
- if (ID_MODE_GESTURES == m_nCmdMode || true == bAccepted)
- {
- // Get the rectangle to update.
- RECT rc;
- CComPtr<IInkRectangle> spIInkRect;
- if (m_spIInkRenderer != NULL
- && pInkStrokes != NULL
- && SUCCEEDED(pInkStrokes->GetBoundingBox(IBBM_Default, &spIInkRect))
- && SUCCEEDED(spIInkRect->GetRectangle(&rc.top, &rc.left,
- &rc.bottom, &rc.right)))
- {
- HDC hdc = m_wndInput.GetDC();
- if (NULL != hdc)
- {
- if (FAILED(m_spIInkRenderer->InkSpaceToPixel((long)hdc, &rc.left, &rc.top))
- || FAILED(m_spIInkRenderer->InkSpaceToPixel((long)hdc, &rc.right,
- &rc.bottom)))
- {
- m_wndInput.GetClientRect(&rc);
- }
- ReleaseDC(hdc);
- }
- else
- {
- m_wndInput.GetClientRect(&rc);
- }
- }
- else
- {
- m_wndInput.GetClientRect(&rc);
- }
- m_wndInput.InvalidateRect(&rc);
- }
- else// if something's failed,
- {
- *pbCancel = VARIANT_TRUE;
- idGestureName = IDS_GESTURE_UNKNOWN;
- }
- m_wndResults.SetGestureName(idGestureName);
- m_wndResults.Invalidate();
- return hr;
- }
- // Recognition event handlers 識別器事件
- HRESULT Cinkdoc::OnRecognitionWithAlternates(
- IInkRecognitionResult* pIInkRecoResult,
- VARIANT /*vCustomParam*/,
- InkRecognitionStatus /*RecognitionStatus*/
- )
- {
- if (NULL == pIInkRecoResult)
- return E_INVALIDARG;
- m_wndResults.ResetResults();
- // Get the best lCount results
- HRESULT hr;
- CComPtr<IInkRecognitionAlternates> spIInkRecoAlternates;
- hr = pIInkRecoResult->AlternatesFromSelection(
- 0,
- -1,
- CRecoOutputWnd::mc_iNumResults,
- &spIInkRecoAlternates
- );
- LONG lCount = 0;
- if (SUCCEEDED(hr) && SUCCEEDED(spIInkRecoAlternates->get_Count(&lCount)))
- {
- IInkRecognitionAlternate* pIInkRecoAlternate = NULL;
- for (LONG iItem = 0; (iItem < lCount) && (iItem < CRecoOutputWnd::mc_iNumResults); iItem++)
- {
- if (SUCCEEDED(spIInkRecoAlternates->Item(iItem, &pIInkRecoAlternate)))
- {
- BSTR bstr = NULL;
- if (SUCCEEDED(pIInkRecoAlternate->get_String(&bstr)))
- {
- m_wndResults.m_bstrResults[iItem].Attach(bstr);
- }
- pIInkRecoAlternate->Release();
- }
- }
- }
- // Update the output window with the new results
- m_wndResults.Invalidate();
- return S_OK;
- }
- //識別結果獲取
- LRESULT Cinkdoc::OnRecognizer(
- WORD/*wNotifyCode*/,
- WORD wID,
- HWND/*hWndCtl*/,
- BOOL& /*bHandled*/
- )
- {
- if (m_spIInkRecognizers == NULL || wID == m_nCmdRecognizer)
- return 0;
- HRESULT hr;
- CComPtr<IInkRecognizer> spIInkRecognizer;
- if (ID_RECOGNIZER_DEFAULT == wID)
- {
- hr = m_spIInkRecognizers->GetDefaultRecognizer(0, &spIInkRecognizer);//獲取預設識別器設定之
- }
- else
- {
- hr = m_spIInkRecognizers->Item(wID - ID_RECOGNIZER_FIRST, &spIInkRecognizer);//否則獲取第一個識別器設定之
- }
- if (SUCCEEDED(hr) && UseRecognizer(spIInkRecognizer))
- {
- UpdateMenuRadioItems(mc_iSubmenuRecognizers, wID, m_nCmdRecognizer);
- m_bstrCurRecoName.Empty();
- spIInkRecognizer->get_Name(&m_bstrCurRecoName);
- UpdateStatusBar();
- m_nCmdRecognizer = wID;
- }
- return 0;
- }
- //輸入獲取
- LRESULT Cinkdoc::OnInputScopeCoerce(
- WORD/*wNotifyCode*/,
- WORD wID,
- HWND/*hWndCtl*/,
- BOOL& /*bHandled*/
- )
- {
- if (m_spIInkRecoContext == NULL )
- return 0;
- if (m_spIInkStrokes != NULL)
- {
- m_spIInkRecoContext->putref_Strokes(NULL);
- }
- if (FAILED(m_spIInkRecoContext->put_RecognitionFlags (m_bCoerceInputScope?IRM_None:IRM_Coerce)))
- {
- MessageBox(TEXT("獲取結果失敗!"),
- gc_szAppName, MB_ICONERROR | MB_OK);
- // Re-attach the stroke collection to the context
- if (m_spIInkStrokes != NULL)
- {
- m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes);
- }
- return 0;
- }
- m_bCoerceInputScope = !m_bCoerceInputScope;
- // 收集筆跡
- if (m_spIInkStrokes != NULL)
- {
- m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes);
- }
- // 更新識別結果
- CComVariant vCustomData; // no custom data
- m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData);
- return 0;
- }