SHChangeNotifyRegister 监测文件改变

大海啊全是水 2010-09-26 11:25:03
我使用这个函数去监测文件和文件夹改变的时候 遇到个问题
在监测文件和文件夹重命名的时候,收到了两次文件和文件夹重命名的消息,不知道为什么会产生两次消息。
谁能给我讲讲是我代码的问题,还是本来就会收到两次消息,为什么会有这两次呢?我觉得应该有什么原因的。
我电脑是XP系统的。还有我担心其他的操作系统可能会不是这样的哈,如WIN7 VISTA这些
测试代码如下:

#include "stdafx.h"
#include "MonitorChanged.h"
#include <InitGuid.h>
#include <ShlObj.h>
#include <ShellAPI.h>

#define MAX_LOADSTRING 100
#define WM_MONITOR WM_USER+123
#define SHCNRF_ShellLevel 0x0002

// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
DWORD dwNotifyID=0;

typedef struct{
DWORD dwItem1;
DWORD dwItem2;
}SHNOTIFYSTRUCT;

// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;

// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MONITORCHANGED, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MONITORCHANGED));

// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

SHChangeNotifyDeregister(dwNotifyID);

return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MONITORCHANGED));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MONITORCHANGED);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // 将实例句柄存储在全局变量中

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

IShellFolder *m_lpsfDesktop;
SHGetDesktopFolder(&m_lpsfDesktop);

LPITEMIDLIST pidl;
m_lpsfDesktop->ParseDisplayName(NULL, NULL, _T("H:\\"), NULL, &pidl, NULL);
SHChangeNotifyEntry shcne;
shcne.pidl=pidl;
shcne.fRecursive=TRUE;
dwNotifyID=::SHChangeNotifyRegister(hWnd,SHCNRF_ShellLevel, SHCNE_RENAMEITEM|SHCNE_CREATE|SHCNE_DELETE|SHCNE_MKDIR|SHCNE_RMDIR|SHCNE_RENAMEFOLDER, WM_MONITOR,1,&shcne);

m_lpsfDesktop->Release();
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MONITOR:
{
TCHAR ch[MAX_PATH]={0};
TCHAR ch2[MAX_PATH]={0};
switch(lParam)
{
case SHCNE_RENAMEITEM: //收到两次消息
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem2),ch2);

OutputDebugStringW(_T("RENAME FILE:\nOLD PATH - "));
OutputDebugStringW(ch);
OutputDebugStringW(_T("\nNEW PATH - "));
OutputDebugStringW(ch2);
OutputDebugStringW(_T("\n"));

break;
case SHCNE_CREATE:
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
OutputDebugStringW(_T("CREATE FILE:\nPATH - "));
OutputDebugStringW(ch);
break;
case SHCNE_DELETE:
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
OutputDebugStringW(_T("DELETE FILE:\nPATH - "));
OutputDebugStringW(ch);
break;
case SHCNE_MKDIR:
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
OutputDebugStringW(_T("CREATE FOLDER:\nPATH - "));
OutputDebugStringW(ch);
break;
case SHCNE_RMDIR:
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
OutputDebugStringW(_T("DELETE FOLDER:\nPATH - "));
OutputDebugStringW(ch);
break;
case SHCNE_RENAMEFOLDER: //收到两次消息
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem1),ch);
::SHGetPathFromIDList((LPCITEMIDLIST)LongToPtr(((SHNOTIFYSTRUCT*)wParam)->dwItem2),ch2);
OutputDebugStringW(_T("RENAME FOLDER:\nOLD PATH - "));
OutputDebugStringW(ch);
OutputDebugStringW(_T("\nNEW PATH - "));
OutputDebugStringW(ch2);
OutputDebugStringW(_T("\n"));
break;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
...全文
255 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
大海啊全是水 2010-09-26
  • 打赏
  • 举报
回复
两次的值一样的,我开始以为第一次是文件重命名前发的 就是文件的old path还是有效路径。结果我在第一次去获取old path的GetFileAttributes属性时依然无效。
积木 2010-09-26
  • 打赏
  • 举报
回复
把两次事件的参数都打印出来看看,看看参数值是不是都一样?
赵4老师 2010-09-26
  • 打赏
  • 举报
回复

64,636

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧