Windows 7程式開發系列之二(JumpList篇2 – Destination)

來源:互聯網
上載者:User

        JumpList中除了有User Task外,還有Destination。與User Task不同,Destination中是與該程式相關聯的檔案的連結。Destination還可以分類,Windows已經自動為我們管理了“最近“和“常用“兩個類別。比如記事本程式,使用“最近”這個類別:

       這對於大多數程式已經足夠。但Windows也為我們提供了管理自己的類別的介面。程式可以根據自己的需要,添加自己的類別。本節將介紹如何將自己的類別加入JumpList。

一、向
JumpList中加入自訂類別

     首先來定義一些準備要放入JumpList的檔案:

LPCTSTR szFiles[] = {<br />TEXT("TestFile1.txt"),<br />TEXT("TestFile2.txt"),<br />TEXT("TestFile3.txt")<br />};

     響應按鍵訊息,當按下“j”的時候,建立JumpList。

case WM_CHAR:<br />switch(wParam)<br />{<br />case 'j':<br />CreateJumpList();<br />break;<br />}<br />break;

//建立Destination List<br />void CreateJumpList()<br />{<br />//建立檔案<br />for (int i = 0; i < ARRAYSIZE(szFiles); ++i)<br />{<br />CreateFile(szFiles[i], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);<br />}<br />//JumpList<br />ICustomDestinationList *pCDL = NULL;<br />HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL,<br />CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCDL));<br />if(SUCCEEDED(hr))<br />{<br />//BeginList<br />UINT uMaxSlots;<br />IObjectArray *pOARemoved = NULL;<br />hr = pCDL->BeginList(&uMaxSlots, IID_PPV_ARGS(&pOARemoved));<br />if (SUCCEEDED(hr))<br />{<br />//ObjectCollection<br />IObjectCollection *pOC = NULL;<br />hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,<br />CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pOC));<br />if(SUCCEEDED(hr))<br />{<br />//每個檔案分別建立ShellItem<br />for(int i = 0; i < ARRAYSIZE(szFiles); ++i)<br />{<br />//拼接檔案路徑<br />WCHAR pszPath[MAX_PATH];<br />WCHAR pszCurDir[MAX_PATH];<br />GetCurrentDirectory(ARRAYSIZE(pszCurDir), pszCurDir);<br />PathCombine(pszPath, pszCurDir, szFiles[i]);<br />//根據檔案路徑建立ShellItem<br />IShellItem *pSI = NULL;<br />hr = SHCreateItemFromParsingName(pszPath, NULL, IID_PPV_ARGS(&pSI));<br />if (SUCCEEDED(hr))<br />{<br />pOC->AddObject(pSI);<br />pSI->Release();<br />}<br />}<br />IObjectArray *pOA = NULL;<br />hr = pOC->QueryInterface(IID_PPV_ARGS(&pOA));<br />if (SUCCEEDED(hr))<br />{<br />//將自訂Category加入JumpList<br />pCDL->AppendCategory(TEXT("My Custom Category"), pOA);<br />pOA->Release();<br />}<br />hr = pCDL->CommitList();<br />pOC->Release();<br />}<br />pOARemoved->Release();<br />}<br />pCDL->Release();<br />}<br />}

     上面的代碼首先在當前檔案夾內,將上面定義的幾個檔案建立出來。然後其他的步驟與建立User Task類似。不過中途向IObejctCollection

介面中加入的是IShellItem

介面,而不是IShellLink

介面。建立IShellItem

介面時,先取得檔案的完整路徑,然後使用API函數SHCreateItemFromParsingName

建立。取得IObjectArray

介面後調用AppendCategory

將自訂的類別加入JumpList。

     執行上面程式,在視窗上按“j”。沒有作用,效果沒有達到。前面提到過,Destination中的檔案是與我們的應用程式關聯的檔案。我們加入的是3個txt檔案,而我們的應用程式目前並沒有與txt檔案關聯。下面還有一些工作要做。

二、Application ID

      首先要提一下AppID,它是一個字串,Windows用它來標識一個程式。在預設的情況下,我們的程式不需要設定AppID,Windows會自動為我們產生和管理AppID。但是在某些情況下,我們自己管理AppID更好,比如上面提到的檔案關聯。只有與我們的程式關聯的檔案才會顯示到Destination中。Windows7中,工作列按鈕的分組也是以AppID為依據的,具有相同AppID的視窗,他們的工作列按鈕會被分為一組,即使它們由不同的程式建立。反之,具有不同AppID的視窗,即使她們是由同一個程式建立,它們的工作列按鈕也不會被分到一組中。下面我們來做一下這個實驗:

       1.為應用程式設定AppID。API函數SetCurrentProcessExplicitAppUserModelID

用於設定應用程式的AppID(函數名字稍微有點長)。

       2.為視窗設定AppID。視窗預設的AppID與建立它的應用程式相同。因此,由同一個程式建立的兩個視窗,在工作列中會被歸為一組(前提是這兩個視窗都具有工作列按鈕)。如果我們為視窗設定不同的AppID,這兩個視窗就不會被歸為一組。設定視窗的AppID沒有直接的API函數。與設定IShellLink

介面的title一樣,需要用到IPropertyStore

這個介面。編寫下面的函數,用於設定視窗的AppID。

void SetWndAppID( HWND hWnd, LPCTSTR szAppID )<br />{<br />IPropertyStore *pPS = NULL;<br />HRESULT hr = SHGetPropertyStoreForWindow(hWnd, IID_PPV_ARGS(&pPS));<br />if(SUCCEEDED(hr))<br />{<br />PROPVARIANT pv;<br />if(szAppID != NULL)<br />{<br />hr = InitPropVariantFromString(szAppID, &pv);<br />}<br />else<br />{<br />PropVariantInit(&pv);<br />}<br />if(SUCCEEDED(hr))<br />{<br />hr = pPS->SetValue(PKEY_AppUserModel_ID, pv);<br />if(SUCCEEDED(hr))<br />{<br />pPS->Commit();<br />}<br />PropVariantClear(&pv);<br />}<br />pPS->Release();<br />}<br />}

       該函數接受一個視窗控制代碼和AppID(字串)。通過API函數SHGetPropertyStoreForWindow

取得IPropertyStore

介面。通過字串初始化一個PropVariant

,然後將其設定為AppID。

       建立一個Windows程式,在其中建立兩個視窗,最好都是overlappped視窗,這樣的視窗在工作列中會有按鈕。在沒有為視窗設定AppID的情況下,兩個視窗的工作列按鈕被合并為一組(前提是開啟了Windows7的工作列按鈕合并)。

工作列按鈕被合并:

如果我們為視窗設定不同的 AppID:

LPCTSTR APP_ID[] = {<br />TEXT("wilford.TestAppID.ID"),<br />TEXT("wilford.TestAppID.ID1"),<br />TEXT("wilford.TestAppID.ID2")<br />};

SetWndAppID(g_hWnd1, APP_ID[1]);<br />SetWndAppID(g_hWnd2, APP_ID[2]);

工作列按鈕不會被分組:

三、將檔案類型與AppID關聯

      檔案關聯是通過註冊表來實現的,所要設定的項較多,我使用了一些輔助的函數(這些代碼來自Microsoft的教程),用來完成這些工作。如何操作註冊表不是本篇的課題,因此就不作講解了,在文末的代碼下載中會提供這些輔助代碼,下面只說一下需要設定哪些索引值。

      1.在註冊表中註冊AppID。通過下面的註冊表匯出檔案的內容,我們可以看到註冊一個AppID所需要的註冊表結構。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT/Wilford.JumpList2]

"FriendlyTypeName"="Custom Jump List Document"

[HKEY_CLASSES_ROOT/Wilford.JumpList2/CurVer]

@="Wilford.JumpList2"

[HKEY_CLASSES_ROOT/Wilford.JumpList2/DefaultIcon]

@="c://Users//wilford//Documents//Visual Studio 2008//Projects//Course//JumpList2//Debug//JumpList2.exe,0"

[HKEY_CLASSES_ROOT/Wilford.JumpList2/shell]

@="Open"

[HKEY_CLASSES_ROOT/Wilford.JumpList2/shell/Open]

[HKEY_CLASSES_ROOT/Wilford.JumpList2/shell/Open/Command]

@="c://Users//wilford//Documents//Visual Studio 2008//Projects//Course//JumpList2//Debug//JumpList2.exe %1"

        2.將檔案類型與AppID關聯。這裡將.txt類型的檔案與我們上面建立的AppID相關聯。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT/.txt/OpenWithProgids]

"Wilford.JumpList2"=hex(0):

        在程式中加入註冊AppID的代碼,當按下“r”鍵時,註冊AppID。當然如果不在程式中做,而是直接匯入上面的註冊表檔案,也是可以的,對應的程式路徑需要改一下。

case 'r':<br />if (!FileRegistration::AreFileExtensionsRegistered(APP_ID))<br />{<br />if (E_ACCESSDENIED == FileRegistration::RegisterFileExtensions(<br />APP_ID, szExt, ARRAYSIZE(szExt)))<br />{<br />MessageBox(g_hWnd, TEXT("Access Denied!"), TEXT("Error"), MB_OK | MB_ICONERROR);<br />}<br />}<br />break;

        現在再重新建立JumpList,可以看到應有的效果了。

 

Windows7程式開發系列就到這裡了。以後如果還有新的研究,會發新的教程上來。

 

本節原始碼

Application ID示範代碼

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.