Sometimes you would like to be notified about when specific changes occur,
e.g. when a new folder is created or when a file is renamed or when a share
is removed. There must be such notification funtionality available somewhere,
we can see that clearly in how the Windows Explorer refreshes itself
automatically without pushing the CPU because of steadily polling.
Perhaps you know the API "FindFirstChangeNotification", but this API only
tells us, *that* something happened. It doesn't tell us, *what* has
happended in detail. It's not really useless, but the wish for something
better keeps living. In winNT/2000 we can use "ReadDirectoryChangesW", but
that API is not supported in win9x, furthermore it only notifies us about
file/directory changes, not about share changes etc.
Recently I found infos about undocumented APIs, which do basically what I
was wishing for. Furthermore they work in all 32bit Windows versions. They
seem to be what the Explorer is using inside. However, they're not too
reliable. It might happen, that you get a "seShareAdded" notification,
although the share was removed in reality or such things. It also may happen
from time to time, that an event is missed. So don't rely on it. But it
works well for situations where it doesn't matter too much, when you miss an
event, e.g. when refreshing an Explorer like TListView.
Installing a shell event notification routine is very easy. Just write a
notification callback routine with the correct parameters, then pass it to
the function "RegisterShellEvent". That's it.
 |
type
TShellEvent = procedure (event: TShellEventType; const obj1, obj2: IShellObj; drive: char; value: cardinal);
TShellEventOO = procedure (event: TShellEventType; const obj1, obj2: IShellObj; drive: char; value: cardinal) of object;
function RegisterShellEvent (eventProc : TShellEvent;
root : string = '*';
watchSubtree : boolean = true;
eventTypes : TShellEventTypes = CShellEvents_All) : boolean; overload;
function RegisterShellEvent (eventProc : TShellEventOO;
root : string = '*';
watchSubtree : boolean = true;
eventTypes : TShellEventTypes = CShellEvents_All) : boolean; overload;
|
|
Uninstalling a notification routine is as easy:
 |
function UnregisterShellEvent (event: TShellEvent ) : boolean; overload;
function UnregisterShellEvent (event: TShellEventOO) : boolean; overload;
|
|
There are a lot of different notification events, you can choose about which
events you actually want to be informed. The enumeration type
"TShellEventType" contains a list of all possible events:
 |
type
TShellEventType = (seItemCreated, seItemRenamed, seItemChanged, seItemDeleted,
seDirCreated, seDirRenamed, seDirChanged, seDirDeleted,
seAttributesChanged,
seFreespaceChanged,
seDriveAdded, seDriveAddedGui, seDriveRemoved,
seMediaInserted, seMediaRemoved,
seShareAdded, seShareRemoved, seServerDisconnect,
seImageChanged, seAssociationChanged,
seThemeChanged, seOrderChanged, seMsiChanged, seMsiUninstalled
);
TShellEventTypes = set of TShellEventType;
const
CShellEvents_Disk = [seItemCreated .. seAttributesChanged ];
CShellEvents_Share = [seShareAdded .. seShareRemoved ];
CShellEvents_All = [low(TShellEventType) .. high(TShellEventType)];
|
|
Here comes a little example project, which logs file and directory changes
into a TMemo component:
 |
unit ShellEvents;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, madShell;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
-
procedure ShellEvent(event: TShellEventType; const obj1, obj2: IShellObj; drive: char; value: cardinal);
public
-
end;
var
Form1: TForm1;
implementation
*.
procedure TForm1.ShellEvent(event: TShellEventType; const obj1, obj2: IShellObj; drive: char; value: cardinal);
begin
case event of
seItemCreated, seDirCreated : Memo1.Lines.Add('Add: ' + obj1.Description);
seItemDeleted, seDirDeleted : Memo1.Lines.Add('Del: ' + obj1.Description);
seItemRenamed, seDirRenamed : Memo1.Lines.Add('Ren: ' + obj1.Description + ' -> ' + obj2.Description);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterShellEvent(ShellEvent);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnregisterShellEvent(ShellEvent);
end;
end.
|
|