CListCtrlex: A list of support for file drag and real-time monitors - use unprecedented API functions to achieve shell real-time

zhaozj2021-02-17  56

First, no matter when you created, delete or rename a folder / file in the Explorer window, or when you insert the mobile memory, Windows always updates all its views very quickly. Sometimes our program also requires such functions to make it updated quickly when users create, delete, rename, or other actions in the shell. Second, the principle has two undisclosed functions inside Windows (Note: These two functions have been published in the latest MSDN), named ShchanGenotifyregister and ShchanGenotifydedegegister, which can achieve the above functions. These two functions are located in Shell32.dll, which is exported by the serial number. That's why we can't find these two functions when we look at Shell32.dll with the Depends tool comes with the VC. The export number of the Shchangenotifyregister is 2; the export number of the ShchanGenotifydegegister is 4. ShchangenotifyRegister can add the specified window to the system's message monitor chain so that the window can receive a notification from the file system or shell. The corresponding one of the corresponding functions, ShchanGenotifydedegegister, is used to cancel the monitoring hook. The prototypes and related parameters of ShchangenNotifyregister are as follows: Ulong ShchanGenotifyRegister (HWND HWND, INT FSOURES, Long Fevents, Uint WMSG, INT CENTRIES, SHCHANGENTIENTRY * PFSNE); where: HWnd will receive a handle of the window that changes or notify the message. FSource Indicates the event type of the message will be one or more of the following values ​​(Note: These flags are not included in any header file, the user must define or directly use its corresponding value directly) shcnrf_interruptlevel0x0001 . Receive an interrupt level notification message from a file system. Shcnrf_shelllevel0x0002. Receive the shell level notification message from the shell. Shcnrf_recursIveInterrupt0x1000. Receive interrupt events of all subdirectories in the directory. This flag must be used with the shcnrf_interruptlevel flag. When using this flag, you must simultaneously set the FRECURSI member in the corresponding SHCHANGENTIETRYTry structure (this structure is directed by the last parameter PFSNE of the function) so that the notification message is recursive on the directory tree. Shcnrf_newdelivery0x8000. The received message uses shared memory. You must first call ShchanGenotification_lock, and then you can access the actual data, and then call the SHCHANGENOTIFICATION_UNLOCK function to release the memory. Fevents To capture events, all of its possible values ​​see the annotations of the ShchanGenotify function in MSDN. WMSG generates a message to the window after the corresponding event is generated. The number of members of the array pointing to Centriespfsne. PfsneshChangenotify The starting pointer of the architecture array. This structure carries the notification message, and its member must be set to 1, otherwise the SHCHANGENOTIFYREGISTER or SHCHANGENOTIFYDEREGISTER will not work normally (but according to me, if Centries is set to greater than 1 value, it is still registered, and I don't know what to ask.

If the function call is successful, return a constant registration mark number, otherwise it will return 0. At the same time, the system will add the HWND window to the operating monitor chain. When the file operation occurs, the system sends a WMSG specified message to the window of the HWnd ID, and we can add the processing function of the message in the program. Implement the monitoring of system operations. If you want to quit the program monitoring, you want to call another unapproved function ShchanGenotifydegegister to cancel the program monitoring. The prototype of this function is as follows: BOOL ShchanGenotifydegegister (Ulid); where ulid specifies the monitor registration mark number to be logged out, if the uninstall is successful, return true, otherwise returns false. Third, the example in the previous article, we derive a list of list controls for file drag and drop, but it still has a small shortcoming, that is, when the user drags and drops in one file, if the user is in the SHELL CLISTCTRLEX will not guarantee real-hours updates when moving, deleting, rename, etc. After discussion above, let us add real-time file monitoring capabilities for CListCtrlex. Before using these two functions, you must first declare their prototype, but also add some macros and structural definitions. We add in the original project ShellDef.h a header file, and then add the following statement: #define SHCNRF_InterruptLevel 0x0001 // Interrupt level notifications from the file system # define SHCNRF_ShellLevel 0x0002 // Shell-level notifications from the shell # define SHCNRF_RecursiveInterrupt 0x1000 // Interrupt events on the whole subtree # define SHCNRF_NewDelivery 0x8000 // Messages received use shared memorytypedef struct {LPCITEMIDLIST pidl; // Pointer to an item identifier list (PIDL) for which to receive notifications BOOL fRecursive; // Flag indicating whether to post notifications for children SHCHANGENOTINTRY;

Typedef struct {dword dwitem1; // dwitem1 contains the fresh pidl or name of the folder.} shNotifyInfo;

Typedef Ulong (WinAPI * Pfnshchangenotifyregister) (HWND HWND, INT FSOUR, INT CENTRIES, SHCHANGENTINTRY * PFSNE);

TypeDef Bool (Ulong Ulid) (Ulong Ulid); Declaration of these macros and functions, and parameter meanings, as described above. Below we want to add two function pointers and a ULONG type member variable to save the function address and return registration number. Next we add a public member function initialize for the CListCtrlex class, where we first load shell32.dll and initialization function pointer action, then call the registration function to register to the shell. When the user uses the CListCtrlex class we provide, the user should follow the CListCtrlex created to follow the invocation initialize function to ensure that the message monitoring hook is registered. Otherwise, the real-time monitoring function will be lost. The initialization function is as follows (there is a part involving the OLE initialization): Bool ClistCtrlex :: Initialize () {.......... // Load shell32.dll m_hshell32 = loadingLibrary ("shell32.dll"); if (m_hshell32 == null) {return FALSE;} // get the function address m_pfnDeregister = NULL; m_pfnRegister = NULL; m_pfnRegister = (pfnSHChangeNotifyRegister) GetProcAddress (m_hShell32, MAKEINTRESOURCE (2)); m_pfnDeregister = (pfnSHChangeNotifyDeregister) GetProcAddress (m_hShell32, MAKEINTRESOURCE (4)); if ( m_pfnregister == null || m_pfnderegister == null) {Return False;}

SHChangeNotifyEntry shEntry = {0}; shEntry.fRecursive = TRUE; shEntry.pidl = 0; m_ulNotifyId = 0; // Register Shell monitoring function m_ulNotifyId = m_pfnRegister (GetSafeHwnd (), SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, WM_USERDEF_FILECHANGED, // custom message 1, & SHENTRY); if (m_ulnotifyid == 0) {MessageBox ("Register Failed!", "Error", MB_OK | MB_ICONERROR); RETURN FALSE;} Return true;} Add a function in the CListCtrlex class. The function of this function is to solve the actual character path from the PIDL. CString CListCtrlEx :: GetPathFromPIDL (DWORD pidl) {char szPath [MAX_PATH]; CString strTemp = _T ( ""); if (SHGetPathFromIDList ((struct _ITEMIDLIST *) pidl, szPath)) {strTemp = szPath;} return strTemp;} Now Our program can receive a notification message from the shell or file system, as long as a function that processes a custom message can make our desired response action. It is stored in the LPARAM parameter that is currently generated, such as Shcne_create, which is stored in the WPARAM parameter is the ShNotifyInfo structure. Below is a skeleton code: LRESULT CListCtrlEx :: OnFileChanged (WPARAM wParam, LPARAM lParam) {CString strOriginal = _T ( ""); CString strCurrent = _T ( ""); SHNotifyInfo * pShellInfo = (SHNotifyInfo *) wParam; strOriginal = GetPathFromPIDL (pshellinfo-> dwitem1); if (Stroriginal.isempty ()) {Return NULL;}

Switch (lparam) {Case Shcne_create: Break;

Case Shcne_Delete: Break; Case Shcne_renameItem: Break;} Return Null;} I have concluded that we have completed the expansion of CListCtrlex, through these two unprecedable API functions, writing a folder / file monitor is no longer one Difficulties. Of course, the same function can also be implemented by writing a device driver, but this method is implemented, but the difficulty is large, the cycle is long, and there are many difficulties in development.

转载请注明原文地址:https://www.9cbs.com/read-29686.html

New Post(0)