[C++] WinAPI: File Change Notification Sample Code
#include <Windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <assert.h>
#define WM_USER_MEDIACHANGED WM_USER+88
typedef struct {
DWORD dwItem1; // dwItem1 contains the previous PIDL or name of the folder.
DWORD dwItem2; // dwItem2 contains the new PIDL or name of the folder.
} SHNOTIFYSTRUCT;
void TRACE(LPCTSTR lpszFormat, ...)
{
TCHAR lpszBuffer[0x160];
va_list fmtList;
va_start(fmtList, lpszFormat);
_vstprintf_s(lpszBuffer, lpszFormat, fmtList);
va_end(fmtList);
::OutputDebugString(lpszBuffer);
}
ULONG g_ulSHChangeNotifyRegister = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass);
hwnd = CreateWindow(_T("Window Class Name"),
_T("Window Title Name"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
LPITEMIDLIST ppidl;
if (SHGetSpecialFolderLocation(hwnd, CSIDL_DESKTOP, &ppidl) == NOERROR)
{
SHChangeNotifyEntry shCNE;
shCNE.pidl = ppidl;
shCNE.fRecursive = TRUE;
// Returns a positive integer registration identifier (ID).
// Returns zero if out of memory or in response to invalid parameters.
g_ulSHChangeNotifyRegister = SHChangeNotifyRegister(hwnd, // Hwnd to receive notification
SHCNE_DISKEVENTS, // Event types of interest (sources)
SHCNE_UPDATEITEM, // Events of interest - use SHCNE_ALLEVENTS for all events
WM_USER_MEDIACHANGED, // Notification message to be sent upon the event
1, // Number of entries in the pfsne array
&shCNE); // Array of SHChangeNotifyEntry structures that
// contain the notifications. This array should
// always be set to one when calling SHChnageNotifyRegister
// or SHChangeNotifyDeregister will not work properly.
assert(g_ulSHChangeNotifyRegister != 0); // Shell notification failed
}
else
assert(FALSE); // Failed to get desktop location
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_USER_MEDIACHANGED:
{
TCHAR szPath[MAX_PATH];
SHNOTIFYSTRUCT *shns = (SHNOTIFYSTRUCT *)wParam;
switch (lParam)
{
case SHCNE_UPDATEITEM: //
{
SHGetPathFromIDList((struct _ITEMIDLIST *)shns->dwItem1, szPath);
if (_tcslen(szPath) != 0)
{
// Process strPath as required, for now a simple message box
MessageBox(hwnd, szPath, _T("Notify"), MB_OK);
TRACE(_T("%s\n"), szPath);
}
}
//case SHCNE_xxxx: Add other events processing here
}
}
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}