zoukankan      html  css  js  c++  java
  • VS2010与Windows7共舞:对库进行编程

    对库进行编程

      在Windows 7操作系统中,我们可以手动地对库进行管理,进行库的创建,文件夹的添加和删除等等。但是作为程序员,我们更加关心的是如何以编程的方式对库进行操作。为了帮助我们在应用程序中使用库这种新的文件管理方式,Windows 7为我们提供了一组API用于库的编程开发。

      VS2010与Windows7共舞:对库进行编程(图一)

      图1  与库相关的API

      其中,位于最顶层的用户界面API包括我们之前提到的通用文件对话框CFD,导航栏树形控件等等。使用新的用户界面API,我们可以调用支持库的新版通用文件对话框,从而让我们的应用程序在打开或者保存文件时,可以支持库这一新的特性。 


    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->private void button1_Click(object sender, EventArgs e)

          {

              string strPath;

              // 创建新版的通用保存文件对话框

              System.Windows.Forms.SaveFileDialog _fd = new System.Windows.Forms.SaveFileDialog();

              // 设置对话框的各种属性

              fd.Title = "请选择文件保存的位置";

              fd.FileName = "[选择文件夹…-]";

              fd.Filter = "Library|no.files"; // 设置可选项,只能选择Library

              // 显示对话框

              if (_fd.ShoWDialog() == System.Windows.Forms.DialogResult.OK)

                  {

                  // 获取用户选择的结果

                  string dir_path = System.IO.Path.GetDirectoryName(_fd.FileName);

                  if (dir_path != null && dir_path.Length > 0)

                      {

                      // 传递用户选择的路径

                      strPath = dir_path;

                      }

                  }

                  // 利用用户选择的路径进行后继处理

          }

      通过使用新版的通用文件对话框CFD,我们可以轻松的让我们的应用程序支持库这一新的文件管理方式。

      除了用户界面API,我们重点关注的是位于中间的Shell API。利用Shell API,我们可以对库进行管理,实际上就是通过Shell API修改.library-ms这个文件,当这个文件被修改后,系统会读取这个文件的信息对库进行重新组织。这组Shell API包装了多个COM对象,利用这些对象,我们可以对库进行操作,其中几个比较常用的对象是:

      ?IShellLink 这个对象代表到文件、 文件夹,或可执行文件的一个链接

      ?IShellFolder 对象实际上代表着一个文件夹对象,我们可以通过遍历IShellFolder对象,访问这个文件夹下的所有内容,检索文件夹中的项目的显示名称、 分析文件夹的显示名称和获取文件夹下的项目 ID 列表等等

      ?IShellLibrary是Windows 7新引入的一个对象,它与一个库相对应。通过这个对象,我们可以对库进行各种操作。

      另外,Shell API也提供了多个辅助函数用于对库进行操作,比如:

      ?创建库

      ?打开一个已经存在的库

      ?添加文件夹到库中或者删除一个库中的文件夹

      ?获得一个库的文件夹列表

      ?获得或者设置库的各种选项

      ?获得或者设置库的图标

      通过这些Shell API,我们完全可以操作系统中的库,对其进行操作和管理。

      利用非托管代码操作库

      对于非托管代码,我们可以利用Windows 7提供的Shell API操作库,对库进行管理。在本文中,我们假设开发的是一个常见的下载软件。在下载软件中,我们常常使用文件夹对各种下载的资源进行分类管理,例如:

      VS2010与Windows7共舞:对库进行编程(图二)

     图2  下载软件的分类管理

      在下载软件中,这些资源都被组织在“All downloads”下,但是实际上这些下载资源可能被保存在硬盘的不同分区,不同目录下。为了便于利用Windows的资源管理器对所有下载资源进行访问,我们需要创建一个“MyDownload”库,让这个库跟下载软件的“All downloads”文件分类管理方式相对应,然后在这个库中管理我们所有下载的资源。

      为了演示Shell API对库的操作,我们创建一个简单的Visual C++控制台应用程序,在主函数中,我们创建库并对库进行操作:


    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->#include "stdafx.h"

    // 引入头文件

    #include <shobjidl.h> // 引入Shell API

    #include <objbase.h> // 定义 IID_PPV_ARGS宏

    #include <Knownfolders.h> // 引入FOLDERID

    int _tmain(int argc, _TCHAR* argv[])

    {

        // 初始化COM

        CoInitialize(NULL);

        // 利用Shell API创建库

        IShellLibrary *pIShelLibrary;

        HRESULT hr = SHCreateLibrary(IID_PPV_ARGS(&pIShelLibrary));

        if (SUCCEEDED(hr))

        {

            // 如果库创建成功,添加不同的文件路径到当前库中

            IShellItem *pIShellItem;

            SHAddFolderPathToLibrary(pIShelLibrary,

            L"C:\\Users\\Public\\Pictures");

            SHAddFolderPathToLibrary(pIShelLibrary,

            L"C:\\Users\\Public\\Music");

            SHAddFolderPathToLibrary(pIShelLibrary,

            L"D:\\Tools");

            SHAddFolderPathToLibrary(pIShelLibrary,

            L"D:\\Video");

            // 将当前库保存到系统的库目录下

            // 也就是添加一个新的库“MyDownload”

            hr = pIShelLibrary->SaveInKnownFolder(FOLDERID_Libraries ,

            L"MyDownload",

            LSF_MAKEUNIQUENAME,

            &pIShellItem);

           // 释放对象

           pIShellItem->Release();

           pIShelLibrary->Release();

        }

        // 释放COM

        ::CoUninitialize();

        return 0;

    }

      在这段代码中,我们首先引入了使用Shell API所需要的头文件。然后在主函数中,因为这些API都是基于COM的,所以我们首先需要进行COM环境的初始化,完成COM环境的初始化后,我们就可以利用Shell API进行各种库的操作了。这里,我们使用SHCreateLibrary函数创建了一个新的库对象,然后利用SHAddFolderPathToLibrary函数将硬盘上的各个路径添加到这个库中,也就是利用这个库对这些路径下的文件进行管理。然后,我们将这个新创建的库保存到FOLDERID_Libraries下,也就是在这个目录下创建一个新的库定义文件。最后,我们还需要进行必要的COM对象释放工作。通过这样的步骤,我们就可以在文件浏览器中看到我们新创建的库了。现在,这个“MyDownload”库管理的文件,跟我们的下载软件所管理的文件一一对应,这样用户在浏览访问下载的文件时,有一种亲切感。

      VS2010与Windows7共舞:对库进行编程(图三)

      图3,新创建的自定义库

      当然,库的创建只是最基本的操作。当我们完成对库的创建后,我们可以利用Shell API继续对库进行各种操作,比如设置库的图标,类型,设置库默认的保存路径,枚举库中的所有文件夹等。


    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->#include "stdafx.h"

    //

    #include <shobjidl.h>

    #include <objbase.h> // IID_PPV_ARGS macro

    #include <Knownfolders.h> //

    #include <Shlguid.h.>

    int _tmain(int argc, _TCHAR* argv[])

    {

        //

       CoInitialize(NULL);

        // 创建库

        //对库进行操作

        IShellLibrary *pslLibrary;

        // 加载已经存在的库,并对其进行管理

        HRESULT hr = SHLoadLibraryFromParsingName(L"C:\\Users\\Win7\\

        AppData\\Roaming\\Microsoft\\Windows\\Libraries\\

        MyDownload.library-ms",

        STGM_READWRITE, IID_PPV_ARGS(&pslLibrary));

        if(SUCCEEDED(hr))

        {

            // 设置库的图标

            hr = pslLibrary->SetIcon(L"C:\\Windows\\System32\\SHELL32.dll,-14");

            // 设置库的类型

            hr = pslLibrary->SetFolderType(FOLDERTYPEID_GenericLibrary);

            // 循环遍历库中的所有文件夹

            IShellItemArray *psiaFolders;

            hr = pslLibrary->GetFolders(LFF_STORAGEITEMS,

            IID_PPV_ARGS(&psiaFolders));

            IEnumShellItems *penumShellItems;

            psiaFolders->EnumItems(&penumShellItems);

            DWORD dwCount = 0;

            psiaFolders->GetCount(&dwCount);

            IShellItem *psiFolder;

           // 循环遍历库所管理的所有文件夹

           for(DWORD dwIndex = 0; dwIndex < dwCount; ++dwIndex )

                {

                     // 获得文件夹

                     psiaFolders->GetItemAt(dwIndex, &psiFolder );

                     WCHAR strFolderName[256] = L"";

                      LPWSTR *pName = (LPWSTR*)strFolderName;

                      // 获得文件夹的名字

                      hr = psiFolder->GetDisplayName(SIGDN_NORMALDISPLAY,

                     (LPWSTR*)pName);

                     if(SUCCEEDED(hr))

                     {

                     // 将文件夹的名字与“Tools”进行比较

                     // 也就是找到名为“Tools”的文件夹

                         if(wcscmp( *pName, L"Tools") == 0)

                         {

                         // 如果找到“Tools”文件夹,将其设置
                         // 为库的默认保存文件夹

                             hr = pslLibrary- >SetDefaultSaveFolder(

                             DSFT_PRIVATE,

                             psiFolder);

                          }

                      }

                  }

                  // 提交对库的修改

              pslLibrary->Commit();

              pslLibrary->Release();

              }

        }

        //

        ::CoUninitialize();

        return 0;

    }

       在这段代码中,我们首先利用SHLoadLibraryFromParsingName函数,从一个库定义文件中加载这个库并创建一个IShellLibrary对象,然后,我们就可以利用IShellLibrary对象提供的各种操作函数对库进行操作。在这里,我们首先利用SetIcon函数修改了库的图标,SetIcon函数接受一个字符串作为参数,指定库所使用的图标所在的资源 DLL名称和图标索引。然后,我们利用SetFolderType函数修改库的类型,SetFolderType函数可以接受已知文件夹的类型模板的 GUID作为输入参数,而这个 GUID所代表的文件夹模板定义了这个库可以是下列之一的类型:通用类型,图片,音乐,视频和文档等。 设置库的类型,可以更改库的 Windows 资源管理器视图,并启用搜索和专为库类型设计的视图选项。接下来,我们循环遍历库管理的所有文件夹,找到名为“Tools”的文件夹并将其设置为库的默认保存文件夹。默认情况下,当我们在通用文件保存对话框中选择一个库作为保存位置时,系统会使用库的第一个文件夹作为其保存的文件夹,通过修改库的默认文件夹,我们可以重定向库的默认保存位置。最后,我们调用Commit函数提交对库的修改,也就是将这些修改写入的库定义文件中,从而完成对库的操作。

      利用托管代码操作库

      在上文中,我们介绍了如何利用Shell API在非托管代码中对库进行操作。那么对于托管代码,该如何处理呢?不用担心,微软早为我们提供了相应的解决方案。在Microsoft Windows API Code Pack中,微软封装了很多Native API以提供给.NET程序使用。利用这个程序集,我们可以方便地利用其中封装的各种对象,实现各种本地API功能,使用起来甚至比直接使用API还方便简单。在这里,我们只对跟库相关的对象感兴趣。在Windows API Code Pack中的ShellLibrary对象封装了所有对库的操作,在托管代码中,我们只需要这个对象就可以对库进行操作了。

      为了演示托管代码对库的操作,我们创建一个Visual C#控制台应用程序,然后在项目中添加对Microsoft.WindowsApiCodePack.dll和Microsoft.WindowsApiCodePack.shell.dll的引用。现在,我们就可以使用ShellLibrary对象对库进行各种操作了:


    Code highlighting produced by Actipro CodeHighlighter (freeware)
    http://www.CodeHighlighter.com/

    -->using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    // 使用ShellLibrary所在的名字空间

    using Microsoft.WindowsAPICodePack.Shell;

    namespace LibraryDemoCS

    {

        class Program

        {

            static void Main(string[] args)

            {

                 // 定义库的名字和文件夹路径

                 string strLibName = "MyLib";

                 string strFolderPath = @"C:\";

                 // 创建库并添加文件夹

                 using (ShellLibrary library =new ShellLibrary( strLibName, true))

                 {

                      library.Add(strFolderPath);

                  }

                   // 加载已经存在的库对对其进行操作

                   using (ShellLibrary lib = ShellLibrary.Load("MyLib", false))

                   {

                        // 添加新的文件夹

                        lib.Add(@"D:\");

                         // 设置属性

                         lib.IsPinnedToNavigationPane = true;

                         string strDefSaveFolder = @"D:\";

                         // 设置默认的保存文件夹

                         lib.DefaultSaveFolder = strDefSaveFolder;

                         // 循环遍历库中的文件夹

                        // 找到并显示默认保存文件夹

                        foreach (ShellFolder folder in lib)

                        {

                            Console.WriteLine("\t\t{0} {1}",

                            folder.Name,

                            strDefSaveFolder == folder.ParsingName ? "DefSaveFolder" : "");

                          }

                      }
                      Console.Read();

                   }

               }

    }

      在这段代码中,我们简单地利用Windows API Code Pack中的ShellLibrary对象对库进行了操作,实现了库的创建,文件夹的添加,库的各种属性的设置和库所管理的文件夹的遍历等等。我们可以看到,实际上利用托管代码操作库,比非托管代码更加方便和简单。

  • 相关阅读:
    十三、Sleuth分布式请求链路追踪
    十二、SpringCloud Stream消息驱动
    十一、SpringCloud Bus 消息总线
    Linux命令(权限管理)
    Linux命令(文件管理)
    Linux的文件和目录
    Linux介绍及安装
    Docker
    Nginx
    13、SpringBoot整合Mybatis-Plus
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/1837751.html
Copyright © 2011-2022 走看看