윈도우 앱개발을 향하여

블로그 이미지
윈도우 10 스토어에 앱을 개발해 올리는 것을 목표로 하고 있습니다. 비전공자가 독학으로 시도하는 일이어서 얼마나 걸릴지 모르겠지만... 아무튼 목표는 그렇습니다!!
by 코딩하는 경제학도
  • Total hit
  • Today hit
  • Yesterday hit

Getting Information About the Contents of a Folder (MSDN 번역)


지난 Getting a Folder's ID에서는 namespace object의 PIDL(pointer to an item identifier list)를 구하는 두 가지 접근방법(approaches)을 알아보았다. 그렇다면 PIDL을 얻은 뒤 이것으로 무엇을 할 수 있을까? A related question is: What if neither approach works, or is suitable for your application? The answer to both questions requires taking a closer look at how the namespace is implemented. The key is the IShellFolder interface.


목차

Using the IShellFolder Interface 

Enumerating the Contents of a Folder

Determining Display Names and Other Properties 

Getting a Pointer to a Subfolder's IShellFolder Interface  

Determining an Object's Parent Folder



- Using the IShellFolder Interface


이전 설명에서 namespace 폴더들을 object로 언급했다. 맞는 말이다, namespace 폴더는 COM(Component Object Model) object로 대표되기 때문이다. 각 folder object는 다양한 업무에 사용되는 많은 인터페이스를 노출시킨다(expose). 어떤 인터페이스는 선택가능해서 모든 폴더들이 노출시키지는 않지만, 모든 폴더는 반드시 IShellFolder라는 fundamental한 인터페이스를 노출시켜야만 한다(따라서 언제나 접근가능하다). 


Folder object를 사용하기 위한 첫 단계는 해당 폴더 object의 IShellFolder 인터페이스의 포인터를 얻는 것이다. Object의 다른 인터페이스를 제공하는 함수들을(methods) IShellFolder가 가지고 있다. 그 중 몇가지는 여기서 소개될 것이다.


IShellFolder 인터페이스의 포인터를 얻기 위해선 반드시 SHGetDesktopFolder함수를 호출해야한다. 이 함수는 namespace root(Desktop)의 IShellFolder 인터페이스를 가리키는 포인터를 반환한다. 일단 Desktop의 IShellFolder 인터페이스를 얻으면 그 다음부터는 다양한 방법으로 진행할 수 있다.


만약 관심있는 폴더의 PIDL을 이미 가지고 있다면(SHGetFolderLocation함수를 호출해서 얻었다던가..), 그 폴더의 IShellFolder 인터페이스를 Desktop의 IShellFolder::BindToObject method를 호출하여 얻을 수 있다.

만약 관심있는 폴더가 파일 시스템 object이고 그 경로를 알고 있다면 Desktop의 IShellFolder::ParseDisplayName method를 호출하여 해당 폴더의 PIDL을 얻을 수도 있다. 

만약 위의 두 가지 방법을 모두 사용할 수 없다면 다른 IShellFolder method로 해당 namespace를 탐색할 수도 있다. (Navigating the Namespace 참조)



- Enumerating the Contents of a Folder


관심있는 폴더에 무엇이 포함되어 있는지 보기 위해서는 해당 폴더의 IShelFolder::EnumObjects method를 호출해야만 한다. 그러면 해당 폴더는 standard OLE enumeration object를 만들고 그것의 IEnumIDList 인터페이스를 반환한다. IEnumIDList 인터페이스는 Clone, Next, Reset, Skip 이라는 네 개의 인터페이스를 노출시키며 관심 폴더의 내용물을 열거하는데 사용된다. 그 과정은 다음과 같다.

  1. 해당 폴더의 IShellFolder::EnumObjects method를 호출하여 a pointer to an enumeration object's IEnumIDList interface를 얻는다.
  2. IEnumIDList::Next에 unallocated PIDL를 넘긴다. IEnumIDList::Next가 PIDL의 메모리를 할당한다. 그리고 IEnumIDList::Next가 반환하면 PIDL는 object's item ID와 terminating NULL characters를 담고있다(single-level PIDL, relative to the folder, not a fully qualified PIDL).
  3. IEnumIDList::Next가 내용물이 모두 열거되었음을 알리는 S_FALSE를 반환할 때까지 2단계를 반복한다.
  4. IEnumIDList::Release를 호출하여 enumeration object를 해제한다.
Note  It is important to keep track of whether you are working with a full or relative PIDL. Some functions and methods will accept either, but others will only take one or the other.


나머지 세 개의 IEnumIDList method(Reset, Skip, Clone)도 폴더의 내용물을 반복해서 열거할 때 유용하다. (They allow you to reset the enumeration, skip one or more objects, and make a copy of the enumeration object to preserve its state.)



- Determining Display Names and Other Properties


일단 폴더에 포함된 모든 PIDLs를 열거했다면 그것들이 어떤 종류의 object인지 알아낼 수도 있다. IShellFolder 인터페이스는 쓸모있는 메소드들을 많이 포함하고 있으며 그 중 몇가지를 여기서 소개한다.


One of the most useful properties is the object's display name. 해당 object의 PIDL를 IShellFolder::GetDisplayNameOf에 넘기면 object의 display name을 얻을 수 있다. 해당 object가 namespace의 부모폴더에 포함되어 있기 때문에 해당 object의 PIDL은 반드시 부모폴더와 연관되어 있다.


In addition to its display name, an object can have a number of attributes, such as whether it is a folder or whether it can be moved. You can retrieve an object's attributes by passing its PIDL to IShellFolder::GetAttributesOf. The complete list of attributes is quite large, so you should see the reference for details. Note that the PIDL that you pass to GetAttributesOf must be single-level. In particular, IShellFolder::GetAttributesOf will accept the PIDLs returned by IEnumIDList::Next. You can pass in an array of PIDLs, and GetAttributesOf will return those attributes that all objects in the array have in common.

If you have an object's fully qualified path or PIDL, SHGetFileInfo provides a simple way to retrieve information about an object that is sufficient for many purposes. SHGetFileInfo takes a fully qualified path or PIDL, and returns a variety of information about the object including:

  • The object's display name
  • The object's attributes
  • Handles to the object's icons
  • A handle to the system image list
  • The path of the file containing the object's icon


- Getting a Pointer to a Subfolder's IShellFolder Interface

You can determine whether your folder contains any subfolders by calling IShellFolder::GetAttributesOf and checking to see if the SFGAO_FOLDER flag is set. If an object is a folder, you can bind to it, which provides you with a pointer to its IShellFolder interface.

To bind to a subfolder, call the parent folder's IShellFolder::BindToObject method. This method takes the subfolder's PIDL and returns a pointer to its IShellFolder interface. Once you have this pointer, you can use the IShellFolder methods to enumerate the subfolders contents, determine their properties, and so on.


- Determining an Object's Parent Folder

If you have an object's PIDL, you may need a handle to one of the interfaces exposed by its parent folder. For example, if you want to determine the display name associated with a PIDL by using IShellFolder::GetDisplayNameOf, you must first retrieve the IShellFolder interface of the object's parent. It is possible to do this with the techniques discussed in the previous sections. However, a much simpler approach is to use the Shell function, SHBindToParent. This function takes the fully qualified PIDL of an object and returns a specified interface pointer on the parent folder. Optionally, it also returns the item's single-level PIDL for use in methods such as IShellFolder::GetAttributesOf.

The following sample console application retrieves the PIDL of the System special folder and returns its display name.


#include <shlobj.h>

#include <shlwapi.h>

#include <iostream.h>

#include <objbase.h>


int main()

{

    IShellFolder *psfParent = NULL;

    LPITEMIDLIST pidlSystem = NULL;

    LPCITEMIDLIST pidlRelative = NULL;

    STRRET strDispName;

    TCHAR szDisplayName[MAX_PATH];

    HRESULT hr;


    hr = SHGetFolderLocation(NULL, CSIDL_SYSTEM, NULL, NULL, &pidlSystem);


    hr = SHBindToParent(pidlSystem, IID_IShellFolder, (void **) &psfParent, &pidlRelative);


    if(SUCCEEDED(hr))

    {

        hr = psfParent->GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &strDispName);

        hr = StrRetToBuf(&strDispName, pidlSystem, szDisplayName, sizeof(szDisplayName));

        cout << "SHGDN_NORMAL - " <<szDisplayName << '\n';

    }


    psfParent->Release();

    CoTaskMemFree(pidlSystem);


    return 0;

}


The application first uses SHGetFolderLocation to retrieve the System folder's PIDL. It then calls SHBindToParent, which returns a pointer to the parent folder's IShellFolder interface, and the System folder's PIDL relative to its parent. It then uses the parent folder's IShellFolder::GetDisplayNameOf method to retrieve the display name of the System folder. Because GetDisplayNameOf returns a STRRET structure, StrRetToBuf is used to convert the display name into a normal string. After displaying the display name, the interface pointers are released and the System PIDL freed. Note that you must not free the relative PIDL returned by SHBindToParent.





AND

ARTICLE CATEGORY

분류 전체보기 (56)
Programming (45)
MSDN (4)
개발노트 (2)
reference (5)

RECENT ARTICLE

RECENT COMMENT

CALENDAR

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

ARCHIVE