Aunque egostar me aconsejó no traducir el código desde el C al delphi, por la razón de que delphi tiene un componente que abarca esas utilidades, lo he hecho por un motivo. La implementación que realizo es sencilla y se basa sólo en la API de Windows, con lo que su utilidad se hará patente en aquellos programas en que por los motivos que sean, queramos utilizar API pura sin librerías de clase alguna.
La filosofía es sencilla. Debemos dar a una ventana de nuestra aplicación de la capacidad de recibir y responder a los mensajes que se envían al Shell y sus extensiones al producirse cambios. Esas notificaciones se envían mediante la API SHChangeNotify. Los mensajes que a los que debemos responder los encontramos también aquí. Con esa misma API, podemos notificar al Shell de los cambios que nos parezcan oportunos.
El código que nos habilita para recibir los mensajes está en una unit:
unit ShellMonitor; interface uses Windows, Messages, Shlobj; function StartNotification(hWnd: THandle; Msg: integer): DWORD; procedure EndNotification(NotifyRegister: DWORD); implementation type PCIDLIST_ABSOLUTE = ^ITEMIDLIST; SHChangeNotifyEntry = record pidl: PCIDLIST_ABSOLUTE; fRecursive: boolean; end; PSHChangeNotifyEntry = ^SHChangeNotifyEntry; const SHCNRF_INTERRUPT_LEVEL = $0001; SHCNRF_SHELL_LEVEL = $0002; function SHChangeNotifyRegister(hwnd: THandle; fSources, fEvents, wMsg, cEntries: integer; pshcne: PSHChangeNotifyEntry): ULONG; stdcall; external 'shell32.dll' name 'SHChangeNotifyRegister'; function SHChangeNotifyDeregister(ulID: integer): boolean; stdcall; external 'shell32.dll' name 'SHChangeNotifyDeregister'; function StartNotification(hWnd: THandle; Msg: integer): DWORD; var shCNE: SHChangeNotifyEntry; Events: DWORD; begin shCNE.pidl := nil; shCNE.fRecursive := TRUE; // Eventos que se van a registrar Events := SHCNE_MEDIAINSERTED or SHCNE_MEDIAREMOVED or SHCNE_DRIVEADD or SHCNE_DRIVEREMOVED or SHCNE_UPDATEDIR or SHCNE_UPDATEITEM or SHCNE_RENAMEFOLDER or SHCNE_RENAMEITEM or SHCNE_MKDIR or SHCNE_RMDIR or SHCNE_CREATE or SHCNE_DELETE; Result := SHChangeNotifyRegister(hWnd, SHCNRF_INTERRUPT_LEVEL or SHCNRF_SHELL_LEVEL, Events, Msg, 1, @shCNE); end; procedure EndNotification(NotifyRegister: DWORD); begin if (NotifyRegister <> 0) then SHChangeNotifyDeregister(NotifyRegister); end; end.
StartNotification habilita a la ventana dada por hWnd a la recepción del mensaje Msg, que será el que el Sistema nos enviará al producirse alguno de los eventos que hemos registrado. EndNotification deshabilita la recepción.
Ahora voy a poner un ejemplo hecho con la VCL tradicional para mostrar cómo localizar y responder a los eventos deseados. Esto podría trasladarse a un programa sin VCL. Muestro la función de respuesta al mensaje:
procedure TForm1.WMShellChanged(var Msg: TMessage); var i: integer; ppidl: PPITEMIDLIST; Path: array [0..MAX_PATH] of CHAR; begin ppidl:= PPITEMIDLIST(Msg.WParam); SHGetPathFromIDList(ppidl^, Path); if Path[0] = #0 then exit; case Msg.LParam and $7FFFFFF of SHCNE_UPDATEDIR: Memo1.Lines.Add('Contenido de la carpeta cambiado: ' + String(Path)); SHCNE_MKDIR: Memo1.Lines.Add('Carpeta creada: ' + String(Path)); SHCNE_RMDIR: Memo1.Lines.Add('Carpeta borrada: ' + String(Path)); SHCNE_CREATE: Memo1.Lines.Add('Archivo nuevo: ' + String(Path)); SHCNE_DELETE: Memo1.Lines.Add('Archivo borrado: ' + String(Path)); SHCNE_RENAMEFOLDER: begin i:=1; lstrcpy(Path, ' a '); SHGetPathFromIDList(PAPITEMIDLIST(ppidl)[i], Path + lstrlen(Path)); Memo1.Lines.Add('Carpata renombrada: ' + String(Path)); end; SHCNE_RENAMEITEM: begin i:=1; lstrcat(Path, ' a '); SHGetPathFromIDList(PAPITEMIDLIST(ppidl)[i], Path + lstrlen(Path)); Memo1.Lines.Add('Archivo renombrado: ' + String(Path)); end; SHCNE_DRIVEADD: Memo1.Lines.Add('Disco insertado: ' + String(Path)); SHCNE_DRIVEREMOVED: Memo1.Lines.Add('Disco retirado: ' + String(Path)); SHCNE_UPDATEITEM: // La desconexión del cable de red viene por aquí. Memo1.Lines.Add(Path); end; end;
Subo un archivo con la unit ShellMonitor y una aplicación de ejemplo.
PD: Vuelvo a subir el archivo por problemas en las descargas.
Espero que sea de utilidad.
Saludos.