ICategoryProvider::EnumCategories()

ICategoryProvider::EnumCategories()

Post by Timo Kun » Tue, 27 Aug 2002 23:43:58



Hi!

I'm trying to get all categories Windows-Explorer (of Windows XP)
displays for "My Computer" in report-view. These should be
"Harddisks", "Others" and so on. I use
IShellFolder::CreateViewObject() to get a ICategoryProvider and then
call ICategoryProvider::EnumCategories(), which gives me a valid
IEnumGUID. So far so good. Now, when I call IEnumGUID::Next(), I
should get at least 1 Categorizer-GUID, but I don't. The return-value
is 1 and nothing happens. Why? Is this interface buggy or am I too
stupid to use it? Has anyone any idea?

Thanks in advance!

---
www.TimoSoft-Software.de

 
 
 

ICategoryProvider::EnumCategories()

Post by Ed Sproull [MS » Wed, 28 Aug 2002 06:39:11


Could you please post the code you are using?

Thanks, Ed.

--

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. ? 2001 Microsoft Corporation. All rights
reserved


Quote:> Hi!

> I'm trying to get all categories Windows-Explorer (of Windows XP)
> displays for "My Computer" in report-view. These should be
> "Harddisks", "Others" and so on. I use
> IShellFolder::CreateViewObject() to get a ICategoryProvider and then
> call ICategoryProvider::EnumCategories(), which gives me a valid
> IEnumGUID. So far so good. Now, when I call IEnumGUID::Next(), I
> should get at least 1 Categorizer-GUID, but I don't. The return-value
> is 1 and nothing happens. Why? Is this interface buggy or am I too
> stupid to use it? Has anyone any idea?

> Thanks in advance!

> ---
> www.TimoSoft-Software.de


 
 
 

ICategoryProvider::EnumCategories()

Post by Jim Barr » Wed, 28 Aug 2002 07:26:48



> I'm trying to get all categories Windows-Explorer (of Windows XP)
> displays for "My Computer" in report-view. These should be
> "Harddisks", "Others" and so on. I use
> IShellFolder::CreateViewObject() to get a ICategoryProvider and then
> call ICategoryProvider::EnumCategories(), which gives me a valid
> IEnumGUID. So far so good. Now, when I call IEnumGUID::Next(), I
> should get at least 1 Categorizer-GUID, but I don't. The return-value
> is 1 and nothing happens. Why?

That's what I get too. The enumerator returns S_FALSE indicating that
there are no more items. Perhaps it means that no categories are
supported beyond the predefined (and undocumented) ones such as
DriveSizeCategorizer, DriveTypeCategorizer, FreeSpaceCategorizer,
TimeCategorizer, SizeCategorizer, AlphabeticalCategorizer and
MergedCategorizer. To be honest, the documentation is so awful that I
cannot even tell if ICategoryProvider is intended for the purpose for
which you are trying to use it.

- Jim

 
 
 

ICategoryProvider::EnumCategories()

Post by Jim Barr » Wed, 28 Aug 2002 07:47:53



> Could you please post the code you are using?

How about something like this...

#include <ShlObj.h>
#include <ComDef.h>

// These don't exist in ComDef.h yet
_COM_SMARTPTR_TYPEDEF(ICategoryProvider, __uuidof(ICategoryProvider));
_COM_SMARTPTR_TYPEDEF(ICategorizer, __uuidof(ICategorizer));

// Bind to "My Computer"
IShellFolderPtr desktop;
SHGetDesktopFolder(&desktop);
LPITEMIDLIST idlist = 0;
desktop->ParseDisplayName(0, 0,
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0, &idlist, 0);
IShellFolderPtr folder;
desktop->BindToObject(idlist, 0, IID_IShellFolder, (void**)&folder);

// Get the ICategoryProvider interface
ICategoryProviderPtr cp = view;
folder->CreateViewObject(0, IID_ICategoryProvider, (void**)&cp);
if (cp)
{
  // Enumerate the categories
  IEnumGUIDPtr e;
  if (SUCCEEDED(cp->EnumCategories(&e)))
  {
    GUID guid;
    while (S_OK == eg->Next(1, &guid, 0))
    {
      // 'Next' immediately returns S_FALSE so we never get to here
    }
  }

  // Get the default category
  GUID guid = {0};
  SHCOLUMNID cid = {0};
  cp->GetDefaultCategory(&guid, &cid);
  // 'guid' is now {3E373E22-DA99-4CB7-A886-754EAE984CB4}

  // Try to get the default categorizer
  ICategorizerPtr cat;
  cp->CreateCategory(&guid, IID_ICategorizer, (void**)&cat);
  // returns REGDB_E_CLASSNOTREG

Quote:}

To describe the documentation as scant would be putting it mildly.

- Jim

 
 
 

ICategoryProvider::EnumCategories()

Post by Timo Kun » Thu, 29 Aug 2002 01:25:08



Quote:> Could you please post the code you are using?

> Thanks, Ed.

Well, in VB it looks like this (IShFolder2 is a valid IShellFolder2 of
"My Computer"):

Dim ICatProvider As IVBCategoryProvider
Dim IEnum As IVBEnumGUID
Dim CatGUIDs(0) As UUID
Dim Copied As Long

If Not (IShFolder2 Is Nothing) Then
  IShFolder2.CreateViewObject 0, IID_ICategoryProvider, ICatProvider
  If Not (ICatProvider Is Nothing) Then
    If ICatProvider.EnumCategories(IEnum) = S_OK Then
      If Not (IEnum Is Nothing) Then
        Debug.Print IEnum.Next(1, VarPtr(CatGUIDs(0)), Copied)    '
"1"
        Debug.Print Copied     ' "0"
      End If
    End If
  End If
End If

The definitions of UUID and IID_ICategoryProvider are definitly
correct. The interfaces IVBShellFolder/IVBShellFolder2,
IVBCategoryProvider and IVBEnumGUID are imported via a self-written
tlb and are working perfect (except IVBEnumGUID). My odl-definition of
IVBEnumGUID is:

[
  uuid(0002E000-0000-0000-C000-000000000046),
  version(1.0),
  helpstring("IEnumGUID-Interface for Visual Basic (by TimoSoft)"),
  odl
]
interface IVBEnumGUID : IVBUnknown     // IVBUnknown works perfect
{
  long _stdcall Next([in] long Count, [out] long *pData, [in, out]
long *Copied);

  long _stdcall Skip([in] long Count);

  long _stdcall Reset();

  long _stdcall Clone([out] IVBEnumGUID **pReturn);

Quote:}

I also had this issue with VC++, but deleted the code, so I can't post
it.
 
 
 

ICategoryProvider::EnumCategories()

Post by Ed Sproull [MS » Fri, 30 Aug 2002 08:55:30


First let me state that the IShellFolder is not required to support the
ICategoryProvider interface and may return it for use in other ways than
what you are trying to use it for.

The categories that you are seeing in DefView for My Computer are based on
the type of the drive.  These can be enumerated but it will take a
combination of the CategoryProvider, and IShellFolder2 to do it.

Here is an example;

Also we are working to update the documents.  Thanks for bringing it to our
attention.  Ed.

IMalloc* pIMalloc = NULL;
 if (FAILED(CoGetMalloc(1, &pIMalloc)))
 {
  MessageBox(NULL, TEXT("Failed to CoGetMalloc"), TEXT("ERROR"), MB_OK);
  return 0;
 }

 IShellFolder* pRegistryFolder = NULL;
 IShellFolder* pDesktopFolder = NULL;
 if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder)))
 {
  //Get My Computer
  LPITEMIDLIST pidl = NULL;
  if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl)))
  {
   //Bind to the IShellFolder2 object
   IShellFolder2* pMCFolder = NULL;
   if (SUCCEEDED(pDesktopFolder->BindToObject(pidl, NULL, IID_IShellFolder2,
(void**)&pMCFolder)))
   {
    SHCOLUMNID scid;
    //Make sure column 1 is the type on your machine.
    //Get the SCID for the type column.
    if (SUCCEEDED(pMCFolder->MapColumnToSCID(1, &scid)))
    {
     //Get CategoryProvider
     ICategoryProvider* pICatPro;
     if (SUCCEEDED(pMCFolder->CreateViewObject(NULL, IID_ICategoryProvider,
(void**)&pICatPro)))
     {
      //Get the GUID representing the category for the SCID.
      GUID guid = {0};
      if (S_OK == pICatPro->GetCategoryForSCID(&scid, &guid))
      {
       //Create the categorizer.
       ICategorizer* pCat = NULL;
       if (SUCCEEDED(pICatPro->CreateCategory(&guid, IID_ICategorizer,
(void**)&pCat)))
       {
        //Now that we have a categorizer we can give it a pidl and
        //get back a the category.

        //Get the enumerator.
        IEnumIDList* pEnumIdList;
        if (SUCCEEDED(pMCFolder->EnumObjects(NULL, SHCONTF_FOLDERS,
&pEnumIdList)))
        {
         LPITEMIDLIST pidl;
         while (NOERROR == pEnumIdList->Next(1, &pidl, NULL))
         {
          //Get the category ID for the item.
          DWORD dwCatID = NULL;
          if (SUCCEEDED(pCat->GetCategory(1, (LPCITEMIDLIST*)&pidl,
&dwCatID)))
          {
           //Now get the info and show it.
           CATEGORY_INFO ci;
           pCat->GetCategoryInfo(dwCatID, &ci);

           MessageBoxW(NULL, ci.wszName, L"Category Name", MB_OK);

           pIMalloc->Free(pidl);
          }
         }
         pEnumIdList->Release();
        }
        pCat->Release();
       }
      }
      pICatPro->Release();
     }
     pMCFolder->Release();
    }
   }
   pIMalloc->Free(pidl);
  }
  pDesktopFolder->Release();
 }
 pIMalloc->Release();

--

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. ? 2001 Microsoft Corporation. All rights
reserved


Quote:> Hi!

> I'm trying to get all categories Windows-Explorer (of Windows XP)
> displays for "My Computer" in report-view. These should be
> "Harddisks", "Others" and so on. I use
> IShellFolder::CreateViewObject() to get a ICategoryProvider and then
> call ICategoryProvider::EnumCategories(), which gives me a valid
> IEnumGUID. So far so good. Now, when I call IEnumGUID::Next(), I
> should get at least 1 Categorizer-GUID, but I don't. The return-value
> is 1 and nothing happens. Why? Is this interface buggy or am I too
> stupid to use it? Has anyone any idea?

> Thanks in advance!

> ---
> www.TimoSoft-Software.de

 
 
 

ICategoryProvider::EnumCategories()

Post by Timo Kun » Fri, 30 Aug 2002 23:46:44


Well, this works, but what's up with
ICategoryProvider::EnumCategories()? This is what I actually asked
for. Okay, my first posting was full of errors. I mixed categorizers
and categories, so it's my fault.
Could you please give a sample how to do this?

Thanks anyway!

 
 
 

ICategoryProvider::EnumCategories()

Post by Ed Sproull [MS » Sat, 31 Aug 2002 02:59:40


To clarify what the docs don't say:  The enumerator will only enumerate
categories that are not based on SCIDS and thus unique to the namespace.
The Categorizers that are used in DefView and are based on columns/SCIDS.

The Control Panel is an example of one that does work the way you expected.

Sorry for the confusion, Ed.

--

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. ? 2001 Microsoft Corporation. All rights
reserved


Quote:> Well, this works, but what's up with
> ICategoryProvider::EnumCategories()? This is what I actually asked
> for. Okay, my first posting was full of errors. I mixed categorizers
> and categories, so it's my fault.
> Could you please give a sample how to do this?

> Thanks anyway!

 
 
 

1. Need help on ICategoryProvider/ICategorizer!

Hi!

I'm writing an activex-control called ExplorerListView which can be
used to browse the shell. It should have the same features as the
listview of Windows-Explorer has. Windows XP introduced a new feature
for listviews: Grouping. Windows-Explorer uses this feature for the
content of "My Computer", where drives will be catagorized by their
type.
I want to implement this feature. I know that I can use
ICategoryProvider to get a categorizer and then use ICategorizer to
get the categorys for a folder, so I used those interfaces. But there
are a lot of problems:
1.) How do I get an ICategoryProvider from an IShellFolder? Currently,
I'm using CreateViewObject, which works in most cases, but I don't
know whether this is the right way.
2.) ICategoryProvider sometimes tells me to use the
standard-categorizer. What does it mean? How do I get the ICategorizer
in those cases?
3.) To find all available categorys I enum all subitems of
IShellFolder and call ICategorizer::GetCategory for each item (this
method doesn't work with multiple items in 1 call). I think this is
the correct way, but it only finds 1 or 2 categorys instead of up to
4. What could be the reason?

Thanks in advance!

---
www.TimoSoft-Software.de

2. Programming sound card

3. ICategoryProvider::GetDefaultCategory()

4. FS: PCI Token Ring for Sun Ultra 5, 10, Axi

5. JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

6. Sysprep creates different names for a computer in the domain

7. IEEE1394: REQUEST_SET_LOCAL_HOST_PROPERTIES

8. Hard copying to restore registry files, no registry backup. HELP!

9. ANDATE TUTTI A FARE IN CULO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

10. D85A51FDB61B09B8 8697DD3B98E669B20D358F5AA1B5AE2F 3F86501F9CAB6034F1D4C83D10BE2FF110A1CDF4D3A1C7EB 005453BC6B7593E0 A6B3B04A9E1FE3A6 8534EFA5146054A726E2609F323589D1 76AFFA7E5918EB5A0F191C181886E60B

11. 6FA70DCDEF1902FA 000402A47153A895E3BEE6EF2968B994 3F86501F9CAB6034F1D4C83D10BE2FF110A1CDF4D3A1C7EB 3028C7E32FBDA980 A6B3B04A9E1FE3A6 8534EFA5146054A726E2609F323589D1 5448484F55576DBF83EE0D9A6E8C268B