이전에 설명했듯이 SHLoadInProc를 사용해서 침략을 할경우는 먼저 이것을 로딩해주는 프로그램이 존재해야했다.

하지만 BHO를 이용해서 하면 우리가 만든 객체를 레지스트리에 등록해주고 나면 끝이다.
탐색기나 인터넷 익스프롤러의 인스턴스가 생성될때마다 레지스트리의 BHO 부분을 읽어서 객체를 로딩하고 인스턴스가 소멸될때 로딩한 객체도 소멸된다.

먼저 ATL Wirzard로 DLL 골격을 만든다.

그리고, 메뉴에서 Insert -> New ATL Object를 선택한다.

그리고 Simple Object를 선택한후 NewFolder로 심플 오브젝트를 만들고 샘플의 소스를 삽입한다.

일단 이러한 인련의 과정을 거쳐서 객체를 생성한다.

나머지는 소스를 참고하고..
실제 구동에서 Windows NT 환경과 Windows 9X 환경에서도
동작은 동일하지만..
문자열의 처리가 틀리므로..
9x 계열에서는 ANSI로
NT 계열에서는 Unicode 형태로 선택해야 한다.

그리고, 끝으로 RGS 파일을 수정하여 다음과 같은 스크립트를 추가해야 해서 마무리한다.
아래의 스크립트는 BHO를 등록하는 과정이다.

HKLM
{
SOFTWARE
{
Microsoft
{
Windows
{
CurrentVersion
{
Explorer
{
'Browser Helper Objects'
{
{FAFC718E-632B-11D6-B5D3-0050BF79AAF5}
}
}
}
}
}
}
}

VOID SHChangeNotify(
LONG wEventId,
UINT uFlags,
LPCVOID dwItem1,
LPCVOID dwItem2
);

wEventId ===========================================>
SHCNE_ALLEVENTS All events have occurred.
SHCNE_ASSOCCHANGED A file type association has changed. SHCNF_IDLIST must be specified in the uFlags parameter. dwItem1 and dwItem2 are not used and must be NULL.
SHCNE_ATTRIBUTES The attributes of an item or folder have changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item or folder that has changed. dwItem2 is not used and should be NULL.
SHCNE_CREATE A nonfolder item has been created. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that was created. dwItem2 is not used and should be NULL.
SHCNE_DELETE A nonfolder item has been deleted. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that was deleted. dwItem2 is not used and should be NULL.
SHCNE_DRIVEADD A drive has been added. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was added. dwItem2 is not used and should be NULL.
SHCNE_DRIVEADDGUI A drive has been added and the shell should create a new window for the drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was added. dwItem2 is not used and should be NULL.
SHCNE_DRIVEREMOVED A drive has been removed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that was removed. dwItem2 is not used and should be NULL.
SHCNE_EXTENDED_EVENT Not currently used.
SHCNE_FREESPACE The amount of free space on a drive has changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive on which the free space changed. dwItem2 is not used and should be NULL.
SHCNE_MEDIAINSERTED Storage media has been inserted into a drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive that contains the new media. dwItem2 is not used and should be NULL.
SHCNE_MEDIAREMOVED Storage media has been removed from a drive. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the root of the drive from which the media was removed. dwItem2 is not used and should be NULL.
SHCNE_MKDIR A folder has been created. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that was created. dwItem2 is not used and should be NULL.
SHCNE_NETSHARE A folder on the local computer is being shared via the network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that is being shared. dwItem2 is not used and should be NULL.
SHCNE_NETUNSHARE A folder on the local computer is no longer being shared via the network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that is no longer being shared. dwItem2 is not used and should be NULL.
SHCNE_RENAMEFOLDER The name of a folder has changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the previous PIDL or name of the folder. dwItem2 contains the new PIDL or name of the folder.
SHCNE_RENAMEITEM The name of a nonfolder item has changed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the previous PIDL or name of the item. dwItem2 contains the new PIDL or name of the item.
SHCNE_RMDIR A folder has been removed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that was removed. dwItem2 is not used and should be NULL.
SHCNE_SERVERDISCONNECT The computer has disconnected from a server. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the server from which the computer was disconnected. dwItem2 is not used and should be NULL.
SHCNE_UPDATEDIR The contents of an existing folder have changed, but the folder still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the folder that has changed. dwItem2 is not used and should be NULL. If a folder has been created, deleted, or renamed, use SHCNE_MKDIR, SHCNE_RMDIR, or SHCNE_RENAMEFOLDER, respectively, instead.
SHCNE_UPDATEIMAGE An image in the system image list has changed. SHCNF_DWORD must be specified in uFlags. dwItem1 contains the index in the system image list that has changed. dwItem2 is not used and should be NULL.
SHCNE_UPDATEITEM An existing nonfolder item has changed, but the item still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1 contains the item that has changed. dwItem2 is not used and should be NULL. If a nonfolder item has been created, deleted, or renamed, use SHCNE_CREATE, SHCNE_DELETE, or SHCNE_RENAMEITEM, respectively, instead.

The following values specify combinations of other events: SHCNE_DISKEVENTS Specifies a combination of all of the disk event identifiers.
SHCNE_GLOBALEVENT Specifies a combination of all of the global event identifiers.


The following value modifies other event values and cannot be used alone: SHCNE_INTERRUPT The specified event occurred as a result of a system interrupt.


uFlags ===========================================>
Flags that indicate the meaning of the dwItem1 and dwItem2 parameters. The uFlags parameter must be one of the following values: SHCNF_DWORD The dwItem1 and dwItem2 parameters are DWORD values.
SHCNF_IDLIST dwItem1 and dwItem2 are the addresses of ITEMIDLIST structures that represent the item(s) affected by the change. Each ITEMIDLIST must be relative to the desktop folder.
SHCNF_PATH dwItem1 and dwItem2 are the addresses of NULL-terminated strings that contain the full path names of the items affected by the change.
SHCNF_PRINTER dwItem1 and dwItem2 are the addresses of NULL-terminated strings that represent the friendly names of the printer(s) affected by the change.

The following flags modify other data-type flags and cannot be used by themselves: SHCNF_FLUSH The function should not return until the notification has been delivered to all affected components.
SHCNF_FLUSHNOWAIT The function should begin delivering notifications to all affected components but should return as soon as the notification process has begun.


dwItem1 ===========================================>
First event-dependent value.


dwItem2 ===========================================>
Second event-dependent value.

1. 위의 내용은 함수에 대한 프로토와 인자에 대한 설명이다.

시스템에 관한 것이 변경되면 탐색기는 스스로 그들 중 일부를 감지할 수 있다. 하지만 프로그램에서 변경한 것들은 다른 곳으로부터 통지를 받아야 한다.

조금 전에 다룬 내용과는 약간 반대되는 개념이기도 하다.
FindXXXChangeNotification() 함수들은 통지를 받아오는 역활이지만 SHChangeNotify()는 시스템에 사용자가 변경한 내용을 알려주는 역활이기 때문이다.

2. SHChangeNotify() 함수의 역활은 무엇인가?

위의 설명에서 처럼 어떤 객체(파일 시스템 혹은 그 이상의 다른 시스템)에 대하여 프로그램이 변경을 가하였을 경우 탐색기가 인지하도록 할 필요가 있다.
이러한 일련의 동작을 제대로 구성하지 않는 다면 사용자를 무시한 나만의 프로그램이 되지는 않을까?

어쨋든 좋다. 내가 시스템에서 파일시스템의 변화를 얻어 오듯 우리도 그들(시스템)에게 이러한 정보를 알려주는 것이 안정된 시스템 구성이라 할 수 있겠다.

예제는 아주 간단하므로 그냥 한 줄의 예제로 넘어간다.

SHChangeNotify(SHCNE_CREATE, SHCNF_IDLIST, pidl, NULL);
이전의 상황을 종합해보자.

실제적인 소스에 대한 주석은 더이상 달지 않는다.
이전의 내용에 다 설명이 되어있고, 소스 자체가 겨우 50줄 정도의 간단한 내용이기 때문이기도 하다.

실제로 동작을 시켜보면 여러가지 이상한 점을 발경할 수 있는데, 새로 폴더를 만든다든가 파일을 삭제한다든가 할경우 생각보다 많은 이벤트가 발생한다는 점이다.

이러한 것은 첨에 폴더를 만들고, 이름을 바꾸고등등의 이벤트를 가정하더라도 너무 많다.

파일을 삭제할 경우는 2번의 이벤트가 발생하는데 Shift+Del로 지울경우는 한번만 발생한다.
이유는 파일을 휴지통으로 옮길때 한번, 원본을 삭제할 때 한번 등등..
이러한 세부적인 내용은 윈98에서는 알길이 없다.
단지 이벤트가 발생한다는 정도만 알수 있다.

이후에 ICopyHook 라는 쉘 익스텐션을 이용하여 좀더 색다를 접근을 해볼것이지만 이것또한 Win98에서는 근본적인 해결책은 되지 못한다.

하지만 우리가 바라는 내용은 Windows NT 이상버전에서는 현실적으로 가능한 이야기다.

FindFirstChangeNotification 함수와 비슷한 함수인
ReadDirectoryChangeW()라는 함수가 있다.
이 함수는 발생한 사건에 대하여 야기시킨 발생자와 그에 관한 구체적인 정보로 버퍼를 채운다는 차이가 있다.

이에 관한 부분은 이후에 다루기로 한다.
. 통지객체

통지객체는 커널객체로, 이를 통하여 여러분의 스레드를 동기화할 수 있다. 개념을 설졍하자면 객체 하나를 생성하고 어던 벼화가 생길 경우에 스레드를 깨울 것인가 나타내는 속성들을 그 객체에 부여한다. 그리고 나서 여러분의 스레드를 멈추게하고, 객체의 통지를 기다리는 것이다. 원한다면 통지 객체를 파일시스템에 생기는 변화를 감지할 때 자동으로 신호 상태(signal)가 되는 아주특별하게 고안된 이벤트로 생각할 수 있다.

2. 통지객체의 내용

FindFirstChangeNotification()
FindNextChangeNotification()
FindCloseChangeNotification()

이렇게 3가지로 나누어지고 1번째는 생성 2번째는 변화가 감지되면 그 이벤트를 받는 역활을 하고 3번째는 생성된 객체를 해지한다.

물론 윈98에서는 이벤트로 받을 수 있는 정보가 한정적이기는 하지만 생각외로 요긴하게 쓰일 경우가 많다.


3. FindFirstChangeNotification() 함수

HANDLE FindFirstChangeNotification(
LPCTSTR lpPathName, // 감시할 경로
BOOL bWatchSubtree, // 서브 경로 감시 여부
DWORD dwNotifyFilter // 감시할 옵션
);

감시할 옵션으로는
FILE_NOTIFY_CHANGE_FILE_NAME 파일 이름 변경
FILE_NOTIFY_CHANGE_DIR_NAME 경로 이름 변경
FILE_NOTIFY_CHANGE_ATTRIBUTES 속성 변경 폴더/파일
FILE_NOTIFY_CHANGE_SIZE 파일 사이즈 변경
FILE_NOTIFY_CHANGE_LAST_WRITE 마지막 수정시간 변경 디렉토리/파일
FILE_NOTIFY_CHANGE_SECURITY 보안설정 변경 디렉토리/파일

위의 함수로 생성된 핸들을 루프안에서 WaitForSingleObject()를 이용하여 대기하다가
시그널이 들어오면..
FindNextChangeNotification() 를 이용하여 정보를 찾아낸다.

4. FindNextChangeNotification() 함수

BOOL FindNextChangeNotification(
HANDLE hChangeHandle // handle to change notification
);

간단한 예제를 들어보자...

while(g_bContinue)
{
WaitForSingleObject(hNotify, INFINITE);
PostMessage(ci.hwnd, WM_EX_CHANGENOTIFICATION, 0, 0);

FindNextChangeNotification(hNotify);
}
위에서 보다시피 루프안에는 루프를 끝낼 만한 이벤트가 없다. while문 안에 있는 부울린값 g_bContinue는 전역 변수로서 위 코드를 실행하는 스레드의 외부 에서 정해진다.
다시 말해 이 코드조작은 두개의 스레드가 있음을 암시하고 있다.

그리고, 마지막으로 감시를 중단할 경우는
BOOL FindCloseChangeNotification(
HANDLE hChangeHandle // handle to change notification
);
를 이용하여 감시를 해제할 수 있다.
이전에 g_bContinue를 FALSE상태로 바꾸고 위의 함수를 호출하는 형태로 해제가 가능하다.

그렇다면 위의 간단한 예제는 아래와 같이 변경되면 조금더 쓸모있는 코드가 될 수 있다.

while(g_bContinue)
{
WaitForSingleObject(hNotify, INFINITE);
if(!g_bContinue)
break;

PostMessage(ci.hwnd, WM_EX_CHANGENOTIFICATION, 0, 0);
FindNextChangeNotification(hNotify);
}
이건 아주 간단한 팁이지만 잘못사용하면..
가끔 망하는(?) 수가 있다..

HWND hwnd = FindWindow("Shell_TrayWnd", NULL);

if(IsWindow(hwnd))
{
if(IsVisible(hwnd))
ShowWindow(hwnd, SW_HIDE);
else
ShowWindow(hwnd, SW_SHOW);
}
A CSIDL is used in conjunction with one of four shell functions, SHGetFolderLocation, SHGetFolderPath, SHGetSpecialFolderLocation, and SHGetSpecialFolderPath, to retrieve a special folder's pathname or item ID list (PIDL).

If a special folder does not exist, you can force its creation by using the following special CSIDL:

CSIDL_FLAG_CREATE
Version 5.0. Combine this CSIDL with any of the CSIDLs listed below to force the creation of the associated folder.
The remaining CSIDLs correspond to either file system folders or virtual folders. Where the CSIDL identifies a file system folder, a commonly used path is given as an example. Other paths may be used. Some CSIDLs can be mapped to an equivalent %VariableName% environment variable. CSIDLs are more reliable, however, and should be used if possible.

CSIDL_ADMINTOOLS
Version 5.0. File system directory that is used to store administrative tools for an individual user. The Microsoft Management Console will save customized consoles to this directory, and it will roam with the user.
CSIDL_ALTSTARTUP
File system directory that corresponds to the user's nonlocalized Startup program group.
CSIDL_APPDATA
Version 4.71. File system directory that serves as a common repository for application-specific data. A typical path is C:\Documents and Settings\username\Application Data. This CSIDL is supported by the redistributable ShFolder.dll for systems that do not have the Internet Explorer 4.0 integrated shell installed.
CSIDL_BITBUCKET
Virtual folder containing the objects in the user's Recycle Bin.
CSIDL_COMMON_ADMINTOOLS
Version 5.0. File system directory containing containing administrative tools for all users of the computer.
CSIDL_COMMON_ALTSTARTUP
File system directory that corresponds to the nonlocalized Startup program group for all users. Valid only for Windows NT® systems.
CSIDL_COMMON_APPDATA
Version 5.0. Application data for all users. A typical path is C:\Documents and Settings\All Users\Application Data.
CSIDL_COMMON_DESKTOPDIRECTORY
File system directory that contains files and folders that appear on the desktop for all users. A typical path is C:\Documents and Settings\All Users\Desktop. Valid only for Windows NT® systems.
CSIDL_COMMON_DOCUMENTS
File system directory that contains documents that are common to all users. Typical paths are C:\Documents and Settings\All Users\Documents. Valid for Windows NT® systems and Windows 95 and Windows 98 systems with Shfolder.dll installed.
CSIDL_COMMON_FAVORITES
File system directory that serves as a common repository for all users' favorite items. Valid only for Windows NT® systems.
CSIDL_COMMON_PROGRAMS
File system directory that contains the directories for the common program groups that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs. Valid only for Windows NT® systems.
CSIDL_COMMON_STARTMENU
File system directory that contains the programs and folders that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu. Valid only for Windows NT® systems.
CSIDL_COMMON_STARTUP
File system directory that contains the programs that appear in the Startup folder for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs\Startup. Valid only for Windows NT® systems.
CSIDL_COMMON_TEMPLATES
File system directory that contains the templates that are available to all users. A typical path is C:\Documents and Settings\All Users\Templates. Valid only for Windows NT® systems.
CSIDL_CONTROLS
Virtual folder containing icons for the Control Panel applications.
CSIDL_COOKIES
File system directory that serves as a common repository for Internet cookies. A typical path is C:\Documents and Settings\username\Cookies.
CSIDL_DESKTOP
Windows Desktop—virtual folder that is the root of the namespace.
CSIDL_DESKTOPDIRECTORY
File system directory used to physically store file objects on the desktop (not to be confused with the desktop folder itself). A typical path is C:\Documents and Settings\username\Desktop
CSIDL_DRIVES
My Computer—virtual folder containing everything on the local computer: storage devices, printers, and Control Panel. The folder may also contain mapped network drives.
CSIDL_FAVORITES
File system directory that serves as a common repository for the user's favorite items. A typical path is C:\Documents and Settings\username\Favorites.
CSIDL_FONTS
Virtual folder containing fonts. A typical path is C:\WINNT\Fonts.
CSIDL_HISTORY
File system directory that serves as a common repository for Internet history items.
CSIDL_INTERNET
Virtual folder representing the Internet.
CSIDL_INTERNET_CACHE
Version 4.72. File system directory that serves as a common repository for temporary Internet files. A typical path is C:\Documents and Settings\username\Temporary Internet Files.
CSIDL_LOCAL_APPDATA
Version 5.0. File system directory that serves as a data repository for local (non-roaming) applications. A typical path is C:\Documents and Settings\username\Local Settings\Application Data.
CSIDL_MYPICTURES
Version 5.0. My Pictures folder. A typical path is C:\Documents and Settings\username\My Documents\My Pictures.
CSIDL_NETHOOD
A file system folder containing the link objects that may exist in the My Network Places virtual folder. It is not the same as CSIDL_NETWORK, which represents the network namespace root. A typical path is C:\Documents and Settings\username\NetHood.
CSIDL_NETWORK
Network Neighborhood—virtual folder representing the root of the network namespace hierarchy.
CSIDL_PERSONAL
File system directory that serves as a common repository for documents. A typical path is C:\Documents and Settings\username\My Documents.
CSIDL_PRINTERS
Virtual folder containing installed printers.
CSIDL_PRINTHOOD
File system directory that contains the link objects that may exist in the Printers virtual folder. A typical path is C:\Documents and Settings\username\PrintHood.
CSIDL_PROFILE
Version 5.0. User's profile folder.
CSIDL_PROGRAM_FILES
Version 5.0. Program Files folder. A typical path is C:\Program Files.
CSIDL_PROGRAM_FILES_COMMON
Version 5.0. A folder for components that are shared across applications. A typical path is C:\Program Files\Common. Valid only for Windows NT® and Windows® 2000 systems.
CSIDL_PROGRAMS
File system directory that contains the user's program groups (which are also file system directories). A typical path is C:\Documents and Settings\username\Start Menu\Programs.
CSIDL_RECENT
File system directory that contains the user's most recently used documents. A typical path is C:\Documents and Settings\username\Recent. To create a shortcut in this folder, use SHAddToRecentDocs. In addition to creating the shortcut, this function updates the shell's list of recent documents and adds the shortcut to the Documents submenu of the Start menu.
CSIDL_SENDTO
File system directory that contains Send To menu items. A typical path is C:\Documents and Settings\username\SendTo.
CSIDL_STARTMENU
File system directory containing Start menu items. A typical path is C:\Documents and Settings\username\Start Menu.
CSIDL_STARTUP
File system directory that corresponds to the user's Startup program group. The system starts these programs whenever any user logs onto Windows NT® or starts Windows® 95. A typical path is C:\Documents and Settings\username\Start Menu\Programs\Startup.
CSIDL_SYSTEM
Version 5.0. System folder. A typical path is C:\WINNT\SYSTEM32.
CSIDL_TEMPLATES
File system directory that serves as a common repository for document templates.
CSIDL_WINDOWS
Version 5.0. Windows directory or SYSROOT. This corresponds to the %windir% or %SYSTEMROOT% environment variables. A typical path is C:\WINNT.
위의 두 함수는 상당히 유사하다.

BOOL SHGetSpecialFolderPath(
HWND hwndOwner,
LPTSTR lpszPath,
int nFolder,
BOOL fCreate
);

HRESULT SHGetSpecialFolderLocation(
HWND hwndOwner,
int nFolder,
LPITEMIDLIST *ppidl
);

두개의 함수가 물리적인(?) 경로를 반환하거나
혹은
경로를 PIDL로 반환 한다.

차이점은 SHGetSpecialFolderPath 함수에서 4번째 인자를
TRUE로 줄경우.. 찾고자 하는 경로가 없으면 그 경로를 생성한다는 점이다.
올리기올려짐: 토 8월 12, 2006 12:28 am    주제: [쉘 #005] SHPathToPidl 함수 인용과 함께 답변 글 편집/삭제 글 삭제 글 올린이의 IP 주소 보기

이 함수는 일반 폴더 경로를 PIDL로 변환해준다.

HRESULT SHPathToPidl(LPCTSTR szPath, LPITEMIDLIST* ppidl)
{
LPSHELLFOLDER pShellFolder = NULL;
OLECHAR wszPath[MAX_PATH] = {0};
ULONG nCharParesd = 0;

HRESULT hr = SHGetDesktopFolder(&pShellFolder);
if(FAILED(hr))
return hr;

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharParesd, ppidl, NULL);
pShellFolder->Release();

return hr;
}
HRESULT SHGetDesktopFolder(IShellFolder **ppshf);

함수 설명
Retrieves the IShellFolder interface for the desktop folder, which is the root of the shell's namespace.

파라미터 ppshf
Address that receives an IShellFolder interface pointer for the desktop folder. The calling application is responsible for eventually freeing the interface by calling its Release method.

리턴값
Returns NOERROR if successful, or an OLE-defined error result otherwise.

위의 함수를 사용하여 우리가 얻을 수 있는 값은 바탕화면의
IShellFolder 인터페이스이다.

위의 함수를 이용하여 SHPathToPidl이라는 함수를 아래에 구현하였다.

이 함수를 이용하여 우리가 원하는 IShellFolder 인터페이스를 구하여 메서드인 ParseDisplayName() 함수를 이용하여 필요한 경로를 PIDL로 변경 가능하고..
또한 위에서 구해진 인터페이스를 통하여 앞으로 공부해나갈 네임스페이스 익스텐션들을 구현할 수 있다.
위의 함수는 원래 존재하는 함수가 아니고,
우리가 이러저러한 방법으로 시스템 이미지리스트의 인덱스를
알고 있다면 간단한 방법으로 그 아이콘을 찾을 수 있다.

HICON SHGetSystemIcon(int iIconIndex)
{
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));

HIMAGELIST himl = reinterpret_cast
(SHGetFileInfo("*.*", 0, &sfi, sizeof(SHFILEINFO),
SHGFI_ICON | SHGFI_SYSICONINDEX));

HICON hIcon = ImageList_ExtractIcon(0, himl, iIconIndex);

return hIcon;
}

+ Recent posts