天天看點

25、Windows API Shell程式設計(1)

    所謂Shell(殼),一般是指由作業系統提供的,用于計算機使用者向作業系統輸入相關指令并得到結果的程式。Shell可以字元形式的,也可以是圖形界面形式的。

    Windows Shell最重要的組成部件是explorer.exe。在使用Windows作業系統時,開始菜單、工作列、資料總管等都是explorer.exe提供的。是以Shell程式設計也是圖形使用者界面設計的重要組成部分。掌握Shell程式設計,需首先了解下面4個方面的内容。

(1) Windows Shell程式設計接口。

     Windows Shell提供一系列程式設計接口,例如可以擷取特殊檔案夾,使用檔案浏覽對話框等。

    Shell程式設計接口的函數名通常是以“SH”開始。

(2) Windows Shell擴充。

    Windows平台的Shell是可擴充的。可以為Windows Shell開發擴充程式(Extention),例如:

◇定制不同類型的檔案的右鍵菜單、拖拽菜單(比如WinRAR、Adobe Acrobat等應用程式具有這樣的功能);

◇開發系統通知區域圖示、并為圖示定制菜單和氣泡彈出功能(QQ、MSN、Visual Studio等應用程式具有這樣的功能);

◇定制工作列、定制工具欄等;

◇增加自動播放對話框中的選項;

◇添加控制台項;

◇為不同檔案類型檔案屬性頁、檔案夾的屬性頁(右鍵屬性)增加選項頁。

上面是幾種典型的Shell擴充應用。

(3)系統資料庫在Shell應用中具有重要作用。

Shell應用在很大程度上依賴于系統資料庫,舉例如下。

◇檔案類型輔助:特定擴充名的檔案的圖示、預設打開程式等是通過系統資料庫來配置的。

◇Shell擴充的安裝:比如特定類型檔案的右鍵菜單、拖拽菜單(Context Meun)的菜單項及輸入處理函數所在的動态連結庫。

(4)相關頭檔案和庫檔案。

    進行Shell程式的設計,需要使用一些頭檔案和庫檔案。

    一般Shell API都在shlobj.h頭檔案中聲明,由She1132.dll導出,連結時需要使用到She1132.lib庫。

一、目錄管理

1、基本介紹

    計算機使用者使用Shell最常進行的操作就是檔案操作。Shell最重要的功能之一是進行檔案浏覽、查找、管理以及将檔案和應用程式關聯。

Windows Shell中有很多特殊目錄和檔案,比如所有Windows使用者都經常接觸到的“我的檔案”、“桌面”、“資源回收筒”、“程式檔案”(Program files)等。這些目錄都是Shell特殊目錄。可以通過Shell程式設計接口開發程式,擷取和操作這些特殊目錄。

Shell有一種特殊的檔案和目錄管理方式,每個目錄都有一個PIDL (Pointer of Item identifier list,項辨別符表指針)值,這個值惟一辨別一個檔案夾。

由系統定義的特殊檔案夾的CSIDL (constant special item ID list)是常數,比如:

CSIDL_ DESKTOP代表“桌面”檔案夾,是根目錄;

CSIDL_FAVORITES代表“收藏夾”;

CSIDL_FONTS代表字型檔案夾;

CSIDL_MYDOCUMENTS,代表“我的檔案”;

CSIDL_MYMUSIC代表“我的音樂”;

CSIDL PROFILE代表“使用者”檔案夾,一般情況下是C:\Documents and Settings\username;

CSIDL_PROGRAMS代表“程式”檔案夾,一般情況下是C:\Program Files; .

CSIDL_RECENT,代表“最近的文檔”;

CSIDL_STARTMENU,代表“開始菜單”目錄;

CSIDL_SYSTEM、CSIDL_WINDOWS分别代表“系統”和“Windows”目錄。

SHGetNameFromIDList、SHGetPathFromIDList等Shell API函數通過CSIDL獲得有關于目錄的詳細資訊。

2、操作“我的檔案”等特殊目錄

    操作“我的檔案”等特殊目錄相關操作涉及的API:

SHGetSpecialFolderPath通過檔案夾的CSIDL,獲得檔案夾的路徑;

SHGetFolderLocation擷取檔案夾的路徑,并儲存在ITEMIDLIST結構中;

SHGetPathFromIDList從PIDL轉換為路徑。

    兩種方法來擷取特殊檔案夾的路徑,一種是直接使用SHGetSpecialFolderPath,

另外一種更為通用,使用SHGetFolderLocation從PIDL或CSIDL獲得檔案夾位置後,再使用SHGetPathFromIDList擷取檔案路徑字元串。

25、Windows API Shell程式設計(1)
25、Windows API Shell程式設計(1)

擷取并顯示特殊目錄,周遊資源回收筒示例

/* 頭檔案 */

#include <Windows.h>

#include <shlobj.h>

#include <stdio.h>

/* 函數申明 */

DWORD ListFileInRecycleBin();

VOID GetSpecialFolder();

/*************************************

* int main()

* 功能 調用相關函數

*

* 參數 未使用

**************************************/

int main()

{

GetSpecialFolder();

ListFileInRecycleBin();

}

* VOID GetSpecialFolder()

* 功能 擷取并顯示特殊目錄

VOID GetSpecialFolder()

// 擷取我的檔案的路徑

CHAR szMyDocument[MAX_PATH];// My Document的路徑

// 使用SHGetSpecialFolderPath擷取特殊目錄路徑

SHGetSpecialFolderPath(NULL,szMyDocument,CSIDL_PERSONAL,FALSE);

// 擷取桌面的路徑

CHAR szDesktop[MAX_PATH]; //DeskTop的路徑

LPITEMIDLIST pidl = NULL;

LPMALLOC pMalloc = NULL;

// 配置設定

SHGetMalloc(&pMalloc);

// 使用SHGetFolderLocation、SHGetPathFromIDList可以擷取任意目錄的路徑

SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &pidl);

SHGetPathFromIDList(pidl,szDesktop);

// 釋放

pMalloc->Free(pidl);

pMalloc->Release();

// 顯示結果

printf("My Document:\t %s\n",szMyDocument);

printf("DeskTop:\t %s\n",szDesktop);

* VOID ListFileInRecycleBin()

* 功能 周遊并顯示資源回收筒中的檔案

DWORD ListFileInRecycleBin()

CHAR pszPath[MAX_PATH]; // 儲存路徑

// IShellFolder接口

IShellFolder *pisf = NULL;

IShellFolder *pisfRecBin = NULL;

// 擷取“根”目錄,桌面

SHGetDesktopFolder(&pisfRecBin);

IEnumIDList *peidl = NULL; // 對象周遊接口

LPITEMIDLIST pidlBin = NULL;

LPITEMIDLIST idlCurrent = NULL;

// 資源回收筒位置

SHGetFolderLocation(NULL, CSIDL_BITBUCKET, NULL, 0, &pidlBin);

// 綁定資源回收筒對象

pisfRecBin->BindToObject(pidlBin,NULL,IID_IShellFolder,(void **) &pisf);

// 列舉資源回收筒中的對象,得到IEnumIDList接口,包括SHCONTF_FOLDERS、

// SHCONTF_NONFOLDERS、SHCONTF_INCLUDEHIDDEN類型的對象

pisf->EnumObjects(NULL,

SHCONTF_FOLDERS | SHCONTF_NONFOLDERS |SHCONTF_INCLUDEHIDDEN,

&peidl);

STRRET strret;

ULONG uFetched;

HANDLE hOutPut = GetStdHandle(STD_OUTPUT_HANDLE);

printf("\nFiles In Recycle Bin:\n");

while(1)

// 周遊IEnumIDList對象,idlCurrent為目前對象

if(peidl->Next(1,&idlCurrent,&uFetched) == S_FALSE)

break;

// 擷取資源回收筒目前對象目前的路徑,這裡沒有輸出結果,讀者可自行修改

SHGetPathFromIDList(idlCurrent, pszPath);

// DisplayName,删除前的路徑

pisf->GetDisplayNameOf(idlCurrent,SHGDN_NORMAL,&strret);

// 顯示,printf可能會造成字元編碼不正确。

WriteConsoleW(hOutPut,L"\t",1,NULL,NULL);

WriteConsoleW(hOutPut,strret.pOleStr,lstrlenW(strret.pOleStr),NULL,NULL);

WriteConsoleW(hOutPut,L"\n",1,NULL,NULL);

// 釋放資源

pMalloc->Free(pidlBin);

pMalloc->Free(strret.pOleStr);

peidl->Release();

pisf->Release();

return 0;

3、綁定、周遊、屬性擷取

1)相關API,接口,資料結構

SHGetDesktopFolder是擷取以IShellFolder接口形式傳回的桌面檔案夾

2)IShellFolder接口

IshellFolder是Windows Shell程式對目标進行管理的一個重要接口。每一個目錄對應一個執行個體化的IshellFolder接口。IshellFolder接口的成員包括EnumObj ects、GetAttributesOf、GetDisplayNameOf等。[2]

3)IEnumIDList接口。

IEnumIDList接口提供了一組标準的方法,用于周遊PIDL (Item identifier lists的指針),其成員包括Clone、Next、Reset、Skip等。[3]

示例代碼,見上。

3、浏覽檔案對話框

示例代碼

25、Windows API Shell程式設計(1)
25、Windows API Shell程式設計(1)

彈出“浏覽檔案夾”對話框

DWORD Browse(HWND hwnd) ;

* WinMain

* 功能 程式入口點,調用Browse

int WINAPI WinMain(

HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow

)

Browse(NULL);

* 功能 彈出“浏覽檔案夾”對話框,

并擷取使用者選擇的檔案夾目錄

* 參數 HWND hwnd 父視窗句柄

DWORD Browse(HWND hwnd)

// 用于儲存路徑

CHAR szRoot[MAX_PATH];

CHAR szChoose[MAX_PATH];

CHAR szDisplayName[MAX_PATH];

// 相關變量

LPITEMIDLIST pidlRoot = NULL;

LPITEMIDLIST pidlSelected = NULL;

BROWSEINFO bi = {0};

// “浏覽檔案夾”的根路徑,開發人員可根據情況選擇,比如隻浏覽“我的檔案”。

SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &pidlRoot);

SHGetPathFromIDList(pidlRoot,szRoot);

// 填充 BROWSEINFO 結構

bi.hwndOwner = hwnd;

bi.pidlRoot = pidlRoot;

bi.pszDisplayName = szDisplayName;

bi.lpszTitle = "Choose a target";

bi.ulFlags = 0;

bi.lpfn = NULL;

bi.lParam = 0;

// 彈出對話框

pidlSelected = SHBrowseForFolder(&bi);

// DisplayName

MessageBox(NULL,szDisplayName,"Display Name:",MB_OK);

// 選擇的檔案夾

SHGetPathFromIDList( pidlSelected, szChoose );

MessageBox(NULL,szChoose,"Choose:",MB_OK);

ILFree(pidlRoot);

參考

[1] 精通Windows API 函數、接口、程式設計執行個體

繼續閱讀