25、Windows API Shell编程(1)

简介:     所谓Shell(壳),一般是指由操作系统提供的,用于计算机用户向操作系统输入相关指令并得到结果的程序。Shell可以字符形式的,也可以是图形界面形式的。     Windows Shell最重要的组成部件是explorer.exe。

    所谓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),例如:

◇定制不同类型的文件的右键菜单、拖拽菜单(比如WinRARAdobe Acrobat等应用程序具有这样的功能);

◇开发系统通知区域图标、并为图标定制菜单和气泡弹出功能(QQMSNVisual 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_SYSTEMCSIDL_WINDOWS分别代表“系统”和“Windows”目录。

SHGetNameFromIDListSHGetPathFromIDListShell API函数通过CSIDL获得有关于目录的详细信息。

2、操作“我的文档”等特殊目录

    操作“我的文档”等特殊目录相关操作涉及的API

SHGetSpecialFolderPath通过文件夹的CSIDL,获得文件夹的路径;

SHGetFolderLocation获取文件夹的路径,并保存在ITEMIDLIST结构中;

SHGetPathFromIDListPIDL转换为路径。

    两种方法来获取特殊文件夹的路径,一种是直接使用SHGetSpecialFolderPath,

另外一种更为通用,使用SHGetFolderLocationPIDLCSIDL获得文件夹位置后,再使用SHGetPathFromIDList获取文件路径字符串。


img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 获取并显示特殊目录,遍历回收站示例
 
   
/* 头文件  */
#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;

LPMALLOC pMalloc
= NULL;
// 分配
SHGetMalloc( & pMalloc);
// 回收站位置
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);
pMalloc
-> Release();
peidl
-> Release();
pisf
-> Release();
return 0 ;
}

3、绑定、遍历、属性获取

1)相关API,接口,数据结构

SHGetDesktopFolder是获取以IShellFolder接口形式返回的桌面文件夹

2IShellFolder接口

IshellFolderWindows Shell程序对目标进行管理的一个重要接口。每一个目录对应一个实例化的IshellFolder接口。IshellFolder接口的成员包括EnumObj ectsGetAttributesOfGetDisplayNameOf等。[2]

3)IEnumIDList接口。

IEnumIDList接口提供了一组标准的方法,用于遍历PIDL (Item identifier lists的指针),其成员包括CloneNextResetSkip等。[3]

示例代码,见上。

3、浏览文件对话框

示例代码

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 弹出“浏览文件夹”对话框
 
   
/* 头文件  */
#include
< Windows.h >
#include
< shlobj.h >
/* 函数申明  */
DWORD Browse(HWND hwnd) ;

/* ************************************
* WinMain
* 功能 程序入口点,调用Browse
*
* 参数 未使用
*************************************
*/
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
Browse(NULL);
}

/* ************************************
* WinMain
* 功能 弹出“浏览文件夹”对话框,
并获取用户选择的文件夹目录
*
* 参数 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 };
LPMALLOC pMalloc
= NULL;

// “浏览文件夹”的根路径,开发人员可根据情况选择,比如只浏览“我的文档”。
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);
return 0 ;
}

参考

[1] 精通Windows API 函数、接口、编程实例

[2] http://msdn.microsoft.com/en-us/library/bb775075%28VS.85%29.aspx

[3] http://msdn.microsoft.com/en-us/library/bb761982%28VS.85%29.aspx

[4] http://msdn.microsoft.com/en-us/library/bb773177%28VS.85%29.aspx

目录
相关文章
|
1天前
|
API C++ Windows
windows编程入门_链接错误的配置
windows编程入门_链接错误的配置
7 0
|
9天前
|
监控 Shell 开发工具
Shell编程
Shell编程
|
14天前
|
存储 Java 关系型数据库
掌握Java 8 Stream API的艺术:详解流式编程(一)
掌握Java 8 Stream API的艺术:详解流式编程
47 1
|
29天前
|
存储 Java Shell
bigdata-04-shell编程基础
bigdata-04-shell编程基础
13 0
|
1月前
|
Shell Linux C++
【Shell 编程设计】 编写自己的清理后台的Shell脚本
【Shell 编程设计】 编写自己的清理后台的Shell脚本
31 1
|
1月前
|
算法 Linux API
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
28 0
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
|
1月前
|
存储 Shell 数据安全/隐私保护
【Shell 编程指南】Shell read命令 (从标准输入读取数值)
【Shell 编程指南】Shell read命令 (从标准输入读取数值)
25 0
|
1月前
|
Shell C语言 C++
【Shell 编程指南】shell中的(),{}几种语法用法
【Shell 编程指南】shell中的(),{}几种语法用法
17 0
|
1月前
|
Shell 程序员 Linux
【Shell 编程指南】shell运算操作符之(())
【Shell 编程指南】shell运算操作符之(())
19 0
|
1月前
|
Linux API C++
【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用
【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用
21 1