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

    ◇定制不同类型的文件的右键菜单、拖拽菜单(比如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获取文件路径字符串。

    获取并显示特殊目录,遍历回收站示例
    /* 头文件 */
    #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、浏览文件对话框

    示例代码

    弹出“浏览文件夹”对话框
    /* 头文件 */
    #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

  • 相关阅读:
    CMD指令
    六种Socket I/O模型幽默讲解
    性格与职业的选择
    为什么主引导记录的内存地址是0x7C00?
    pandas数据分析第二天
    pandas数据结构和介绍第一天
    tornado options
    tornado.web.StaticFileHandler
    mysql多条更新
    pandas
  • 原文地址:https://www.cnblogs.com/mydomain/p/1958477.html
Copyright © 2020-2023  润新知