uLib  User mode C/C++ extended API library for Win32 programmers.
SysImgList.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Access the system image lists (the hard-core way).
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //
7 // [Ref] http://www.catch22.net/tuts/system-image-list
8 //
9 // NOTE: Direct use of ImageList_Draw results in superior speed,
10 // far outperforming both ImageList_GetIcon/DrawIconEx and IImageList::Draw.
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 
13 #include <uLib/SysImgList.h>
14 
15 HIMAGELIST SysImgList::hSmall = NULL;
16 HIMAGELIST SysImgList::hLarge = NULL;
17 
18 HMODULE SysImgList::_hShell32 = NULL;
19 
20 BOOL (WINAPI *SysImgList::Shell_GetImageLists)( HIMAGELIST* pimlLarge, HIMAGELIST* pimSmall )
21  = NULL; // @71
22 
23 BOOL (WINAPI *SysImgList::FileIconInit)( BOOL bFullInit )
24  = NULL; // @660
25 
27 {
28  memset( &Info, 0, sizeof(Info) );
29 
30  if (!_hShell32) _hShell32 = LoadLibrary( _T("Shell32.dll") );
31  // Note: Do not unload Shell32, or the lists will be /gone/.
32  if (_hShell32)
33  {
35  (FARPROC&) Shell_GetImageLists = GetProcAddress( _hShell32, (LPCSTR)71 );
36 
37  if (!FileIconInit)
38  (FARPROC&) FileIconInit = GetProcAddress( _hShell32, (LPCSTR)660 );
39  }
40  if (!(hSmall && hLarge))
41  {
42  // I've been told that calling FileIconInit(true) causes the image lists to be
43  // fully populated for this process whereas SHGetFileInfo gets a "holey" list.
44  // However, empirical tests on Win7 indicate the lists are identical.
45 
46  if (FileIconInit) FileIconInit( true );
48 
49  // Note: Shell_GetImageLists is flagged as potentially retiring.
50  // If that comes to be (God forbid), a kludge alternate is:
51  // CSTR Omni = _T("C:\\"); // Omnipresent?
52  // SHFILEINFO sfi = {0};
53  // UINT Flg = SHGFI_SYSICONINDEX;
54  // hLarge = (HIMAGELIST) SHGetFileInfo( Omni, 0, &sfi, sizeof(sfi), Flg );
55  // Flg |= SHGFI_SMALLICON;
56  // hSmall = (HIMAGELIST) SHGetFileInfo( Omni, 0, &sfi, sizeof(sfi), Flg );
57  }
58 }
59 
61 {
62  // Both lists appear to have the same nr of images.
63  return ImageList_GetImageCount( hSmall );
64 }
65 
66 HICON SysImgList::GetSmallIcon( UINT Ix )
67 {
68  return ImageList_GetIcon( hSmall, Ix, ILD_NORMAL ); // ILD_TRANSPARENT
69 }
70 
71 HICON SysImgList::GetLargeIcon( UINT Ix )
72 {
73  return ImageList_GetIcon( hLarge, Ix, ILD_NORMAL ); // ILD_TRANSPARENT
74 }
75 
76 int SysImgList::GetFiletypeIconIndex( CSTR dotExt, bool Small )
77 {
78  int Ix, Flg = SHGFI_SYSICONINDEX| SHGFI_USEFILEATTRIBUTES;
79  if (Small) Flg |= SHGFI_SMALLICON;
80 
81  // SHGetFileInfo returns the imagelist handle. However, we already have
82  // both of those, so we'll just use it as a boolean success indicator.
83 
84  HIMAGELIST hIml = (HIMAGELIST)
85  SHGetFileInfo( dotExt, FILE_ATTRIBUTE_NORMAL, &Info, sizeof(Info), Flg );
86  if (hIml) Ix = Info.iIcon;
87  else Ix = I_NOIMAGE;
88  return Ix;
89 }
90 
91 int SysImgList::GetFileIconIndex( CSTR FName, bool Small )
92 {
93  int Ix, Flg = SHGFI_SYSICONINDEX;
94  HIMAGELIST hIml = (HIMAGELIST)
95  SHGetFileInfo( FName, FILE_ATTRIBUTE_NORMAL, &Info, sizeof(Info), Flg );
96  if (hIml) Ix = Info.iIcon;
97  else Ix = I_NOIMAGE;
98  return Ix;
99 }
100 
101 bool SysImgList::ReplaceIcon( UINT Ix, HINSTANCE hInst, CSTR Id )
102 {
103  HICON hIco = LoadIcon( hInst, Id );
104  if (hIco) ImageList_ReplaceIcon( hLarge, Ix, hIco );
105  hIco = LoadSmallIcon( hInst, Id );
106  if (hIco) ImageList_ReplaceIcon( hSmall, Ix, hIco );
107  return (hIco != NULL);
108 }
109 
110 #if !SYSIMG_USE_COMIFACE
111 // FIXME: Adding icons directly seems to clash with Shell's internal ops.
112 // It appears the sysimg list uses an internal count separate from that
113 // of the HIMAGELIST itself. (If so, an unwise design.)
114 
115 int SysImgList::AddIcon( HINSTANCE hInst, CSTR Id )
116 {
117  int ix = ImageList_AddIcon( hLarge, LoadIcon( hInstance, Id ));
118  ix = ImageList_AddIcon( hSmall, LoadSmallIcon( hInstance, Id ));
119  return ix;
120 }
121 
122 #else // Use IImageList (seems to comply w sysimg list internals).
123 
124 int SysImgList::AddIcon( HINSTANCE hInst, CSTR Id )
125 {
126  IImageList* pIml;
127  int imgIx = -1;
128 
129  // Using IImageList seems to be the only reliable way of adding icons.
130  // So forego the hard-core and use IImagelist to add the resource icon
131  // to both our small and large image lists.
132 
133  bool inited = ShellFuncInitialized();
134  if (!inited) InitShellFunc();
135 
136  if (SUCCEEDED( SHGetImageList( SHIL_LARGE, IID_IImageList, (void**)&pIml )))
137  {
138  pIml->ReplaceIcon( -1, LoadIcon( hInst, Id ), &imgIx );
139  pIml->Release();
140  }
141  if (SUCCEEDED( SHGetImageList( SHIL_SMALL, IID_IImageList, (void**)&pIml )))
142  {
143  pIml->ReplaceIcon( -1, LoadSmallIcon( hInst, Id ), &imgIx );
144  pIml->Release();
145  }
146 
147  if (!inited) DoneShellFunc();
148  return imgIx;
149 }
150 #endif
151 
152 // EOF
HICON WINAPI LoadSmallIcon(HINSTANCE hInst, CSTR Id)
Definition: UserUtil.cpp:628
static HIMAGELIST hSmall
Definition: SysImgList.h:74
#define CSTR
Definition: Common.h:329
static BOOL WINAPI Shell_GetImageLists(HIMAGELIST *pimlLarge, HIMAGELIST *pimSmall)
bool InitShellFunc(bool useOle=false, DWORD coFlag=COINIT_APARTMENTTHREADED)
Definition: ShellUtil.cpp:37
HIMAGELIST * pimSmall
Definition: SysImgList.cpp:21
int GetFiletypeIconIndex(CSTR dotExt, bool Small)
Definition: SysImgList.cpp:76
bool ShellFuncInitialized()
Definition: ShellUtil.cpp:24
#define I_NOIMAGE
Equivalent to I_IMAGENONE.
Definition: SysImgList.h:61
static HMODULE _hShell32
Definition: SysImgList.h:116
HICON GetLargeIcon(UINT Ix)
Definition: SysImgList.cpp:71
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
SHFILEINFO Info
Definition: SysImgList.h:77
static BOOL WINAPI FileIconInit(BOOL bFullInit)
UINT Count()
Definition: SysImgList.cpp:60
int AddIcon(HINSTANCE hInst, CSTR Id)
Definition: SysImgList.cpp:115
HINSTANCE hInstance
Definition: Common.cpp:10
bool ReplaceIcon(UINT Ix, HINSTANCE hInst, CSTR Id)
Definition: SysImgList.cpp:101
int GetFileIconIndex(CSTR FName, bool Small)
Definition: SysImgList.cpp:91
void DoneShellFunc()
Definition: ShellUtil.cpp:64
HICON GetSmallIcon(UINT Ix)
Definition: SysImgList.cpp:66
static HIMAGELIST hLarge
Definition: SysImgList.h:75