Verwenden von Delphi zum Schreiben von Windows-Shell-Erweiterungen
Freunde, die mit den Prinzipien von Betriebssystemen vertraut sind, werden wissen, dass ein vollständiges Betriebssystem eine Shell bereitstellt, die normalen Benutzern die Arbeit erleichtert.
Nutzen Sie verschiedene Funktionen des Betriebssystems. Die Shell von Windows (hier bezieht sich auf das Betriebssystem Windows 95, Windows NT4.0 oder höher) bietet nicht nur
Es bietet nicht nur eine praktische und schöne grafische Benutzeroberfläche, sondern auch leistungsstarke Shell-Erweiterungsfunktionen. Diese Shell-Erweiterungen finden Sie möglicherweise in vielen Softwareprogrammen. Zum Beispiel in Ihrem
Wenn Winzip im System installiert ist und Sie im Windows Explorer mit der rechten Maustaste auf einen Ordner oder eine Datei klicken, wird die Winzip-Datei im Popup-Menü angezeigt.
Kurzmenü. Oder der FTP-Site-Ordner, der im Windows Explorer in Bullet FTP angezeigt wird.
Windows unterstützt sieben Arten von Shell-Erweiterungen (Handler genannt), und ihre entsprechenden Funktionen werden wie folgt kurz beschrieben:
(1)Kontextmenü-Handler: Fügen Sie kontextsensitive Menüs zu bestimmten Arten von Dateiobjekten hinzu;
(2) Drag-and-Drop-Handler werden zur Unterstützung der OLE-Datenübertragung verwendet, wenn Benutzer Drag-and-Drop-Vorgänge für bestimmte Arten von Dateiobjekten ausführen.
(3) Symbolhandler werden verwendet, um einem bestimmten Dateiobjekt ein eindeutiges Symbol bereitzustellen, und können auch ein Symbol für einen bestimmten Dateiobjekttyp angeben.
(4) PROperty-Sheet-Handler fügen Eigenschaftsseiten zu Dateiobjekten hinzu (d. h. klicken Sie mit der rechten Maustaste auf das Dateiobjekt oder Ordnerobjekt und wählen Sie im Popup-Menü „Eigenschaften“)
(Dialogfeld, das nach dem Element angezeigt wird), Eigenschaftsseiten können von Dateiobjekten desselben Typs gemeinsam genutzt werden, oder es kann einem Dateiobjekt eine eindeutige Eigenschaftenseite zugewiesen werden;
(5) Copy-Hook-Handler werden vom System aufgerufen, wenn das Ordnerobjekt oder Druckerobjekt über Windows kopiert, verschoben, gelöscht oder umbenannt wird
Fügen Sie Copy-Hook-Handler hinzu, um bestimmte Vorgänge zuzulassen oder zu verbieten.
(6) Drop-Target-Handler werden vom System aufgerufen, wenn ein Objekt per Drag & Drop auf ein anderes Objekt gezogen wird.
(7)Datenobjekt-Handler werden vom System aufgerufen, wenn Dateien gezogen, abgelegt, kopiert oder eingefügt werden.
Alle Shell-Erweiterungen von Windows basieren auf dem Komponentenmodell COM (Component Object Model) und die Shell greift über Schnittstellen auf Objekte zu.
Shell-Erweiterungen sind als 32-Bit-In-Process-Serverprogramme konzipiert und stellen Dienste für das Betriebssystem in Form von dynamischen Linkbibliotheken bereit. Daher, wenn Sie Windows verwenden möchten
Wenn die Benutzeroberfläche erweitert wird, sind Kenntnisse im Schreiben von COM-Objekten unbedingt erforderlich. Aus Platzgründen wird COM hier nicht vorgestellt
Laut der MSDN-Bibliothek von Microsoft oder zugehörigen Hilfedokumenten kann eine Schnittstelle als eine spezielle Klasse betrachtet werden, die eine Reihe von Funktionen und Prozeduren enthält, die zum Betrieb eines Objekts verwendet werden können.
Nachdem Sie Ihre Shell-Erweiterungen geschrieben haben, müssen Sie sie registrieren, damit sie wirksam werden. Alle Shell-Erweiterungen müssen in der Windows-Registrierung unter dem Schlüssel HKEY_CLASSES_ROOTCLSID vorhanden sein
Registrieren Sie sich unten. Unter diesem Schlüssel finden Sie viele Schlüssel mit Namen wie {0000002F-0000-0000-C000-000000000046}. Solche Schlüssel sind global eindeutige Klassenbezeichner.
Anleitung. Jede Shell-Erweiterung muss über eine global eindeutige Klassenkennung verfügen. Auf diese Weise findet Windows den Shell-Erweiterungshandler.
Der Speicherort der Dynamic Link Library der Shell-Erweiterung im System wird im Unterschlüssel InProcServer32 unter der Klassenkennung aufgezeichnet. Mit einem Dateityp verknüpfte Shell-Erweiterungen werden in registriert
Unter dem Shellex-Primärschlüssel des entsprechenden Typs. Wenn das Windows-Betriebssystem Windows NT ist, muss die Shell-Erweiterung auch in der Registrierung vorhanden sein.
Registrieren Sie sich unter dem Primärschlüssel HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionShellExtensionsApproved.
Nach dem Kompilieren des Shell-Erweiterungs-DLL-Programms können Sie regsvr32.exe verwenden, das von Windows selbst bereitgestellt wird, um das DLL-Serverprogramm zu registrieren. Wenn Sie Delphi verwenden, können Sie dies auch tun
Um sich zu registrieren, wählen Sie im Menü „Ausführen“ die Option „ActiveX-Server registrieren“.
Lassen Sie uns zunächst eine häufiger verwendete Shell-Erweiterungsanwendung vorstellen: das kontextsensitive Menü, das angezeigt wird, wenn Sie in Windows mit der rechten Maustaste auf eine Datei oder einen Ordner klicken.
Dieses Menü wird als kontextsensitives Menü bezeichnet. Um Menüelemente dynamisch zu einem kontextsensitiven Menü hinzuzufügen, können Sie einen Kontextmenü-Handler schreiben. Zum Beispiel jeder
Bekannte Software wie WinZip und UltraEdit fügt Menüelemente dynamisch zum Menü hinzu, indem sie einen Kontextmenü-Handler schreiben. Sofern im System installiert
Wenn Sie dann mit der rechten Maustaste auf eine Datei (Ordner) mit dem Namen Windows klicken, enthält das Kontextmenü von WinZip einen Menüpunkt mit dem Namen „Zu Windows.zip hinzufügen“.
Der in diesem Artikel zu implementierende Kontextmenü-Handler ähnelt dem von WinZip bereitgestellten Kontextmenü. Es wird ein hinzugefügt
Menüelement „Dateioperation“ Wenn Sie auf dieses Element klicken, öffnet das Schnittstellenprogramm ein Dateioperationsfenster, in dem Sie Vorgänge wie das Kopieren und Verschieben von Dateien ausführen können.
Der Schreibkontextmenü-Handler muss drei Schnittstellen implementieren: IShellExtInit, IContextMenu und TComObjectFactory. IShellExtInit-Implementierung
Bei der Initialisierung der Schnittstelle implementiert das IContextMenu-Schnittstellenobjekt das kontextsensitive Menü und die IComObjectFactory-Schnittstelle implementiert die Erstellung des Objekts.
Nachfolgend wird die konkrete Programmumsetzung vorgestellt. Klicken Sie zunächst im Delphi-Menü auf den Eintrag „Datei|Neu“ und wählen Sie im Fenster „Neuer Eintrag“ die Option „DLL“ aus, um eine DLL-Projektdatei zu erstellen.
Klicken Sie dann auf den Menüpunkt „Datei|Neu“, wählen Sie „Einheit“ im Fenster „Neues Element“ aus, um eine Unit-Datei zu erstellen, klicken Sie auf den Menüpunkt „Datei|Neu“ und wählen Sie im Fenster „Neues Element“ die Option „Einheit“.
Wählen Sie Formular aus, um ein neues Fenster zu erstellen. Speichern Sie die Projektdatei als Contextmenu.dpr, Unit1 als Contextmenuhandle.pas und speichern Sie das Formular unter
OpWindow.pas.
Die Programmliste von Contextmenu.dpr lautet wie folgt:
Kontextmenü der Bibliothek;
verwendet
ComServ,
contextmenuhandle in 'contextmenuhandle.pas',
opwindow in 'opwindow.pas' {Form2};
Exporte
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;
{$R *.TLB}
{$R *.RES}
beginnen
Ende.
Die Programmliste von Contextmenuhandle lautet wie folgt:
Unit ContextMenuHandle;
Schnittstelle
verwendet Windows, ActiveX, ComObj, ShlObj, Klassen;
Typ
TContextMenu = class(TComObject,IShellExtInit,IContextMenu)
Privat
FFileName: array[0..MAX_PATH] of Char;
geschützt
function IShellExtInit.Initialize = SEIInitialize; // Compiler-Warnung vermeiden
function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult;
Funktion QueryContextMenu(Menü: HMENU; indexMenu, idCmdFirst, idCmdLast,
uFlags: UINT): HResult;
function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HResult;
Ende;
const
Class_ContextMenu: TGUID = '{19741013-C829-11D1-8233-0020AF3E97A0}';
{Globally Unique Identifier (GUID) ist ein 16-Byte-Wert (128 Byte), der eine Schnittstelle eindeutig identifiziert}
var
FileList:TStringList;
Durchführung
verwendet ComServ, SysUtils, ShellApi, Registry, UnitForm;
function TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult;
var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
FileNumber,i:Integer;
beginnen
file://Wenn lpdobj gleich Null ist, schlägt dieser Aufruf fehl
if (lpdobj = nil) then beginne
Ergebnis := E_INVALIDARG;
Ausfahrt;
Ende;
file:// initialisiert und löscht zunächst FileList, um Dateien hinzuzufügen
FileList:=TStringList.Create;
FileList.Clear;
file://Datei im Zwischenablageformat initialisieren
mit FormatEtc beginnen
cfFormat := CF_HDROP;
ptd := null;
dwaspect := DVASPECT_CONTENT;
lindex := -1;
tymed := TYMED_HGLOBAL;
Ende;
Ergebnis := lpdobj.GetData(FormatEtc, StgMedium);
wenn fehlgeschlagen (Ergebnis), dann beenden;
file://Fragen Sie zunächst die Anzahl der vom Benutzer ausgewählten Dateien ab
FileNumber := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);
file:// liest in einer Schleife und speichert alle vom Benutzer ausgewählten Dateien in FileList
für i:=0 bis FileNumber-1 beginnen
DragQueryFile(StgMedium.hGlobal, i, FFileName, SizeOf(FFileName));
FileList.Add(FFileName);
Ergebnis := NOERROR;
Ende;
ReleaseStgMedium(StgMedium);
Ende;
Funktion TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
idCmdLast, uFlags: UINT): HResult;
beginnen
Ergebnis := 0;
if ((uFlags und $0000000F) = CMF_NORMAL) oder
((uFlags und CMF_EXPLORE) <> 0) dann beginnen
// Fügen Sie dem Kontextmenü einen Menüpunkt hinzu. Der Titel des Menüpunkts lautet „Bitmap-Datei anzeigen“.
InsertMenu(Menu, indexMenu, MF_STRING oder MF_BYPOSITION, idCmdFirst,
PChar('Dateioperation'));
// Gibt die Anzahl der hinzugefügten Menüelemente zurück
Ergebnis := 1;
Ende;
Ende;
function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
frmOP:TForm1;
beginnen
// Stellen Sie zunächst sicher, dass der Prozess vom System und nicht von einem Programm aufgerufen wird
if (HiWord(Integer(lpici.lpVerb)) <> 0) dann
beginnen
Ergebnis := E_FAIL;
Ausfahrt;
Ende;
// Bestimmen Sie die Gültigkeit der übergebenen Parameter
if (LoWord(lpici.lpVerb) <> 0) then begin
Ergebnis := E_INVALIDARG;
Ausfahrt;
Ende;
file://Erstellen Sie ein Dateioperationsfenster
frmOP:=TForm1.Create(nil);
file://fügt eine Liste aller Dateien zur Liste im Dateioperationsfenster hinzu
frmOP.ListBox1.Items := FileList;
Ergebnis := NOERROR;
Ende;
function TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HRESULT;
beginnen
if (idCmd = 0) dann beginnen
if (uType = GCS_HELPTEXT) dann
{Gibt die Hilfeinformationen dieses Menüelements zurück. Diese Hilfeinformationen werden angezeigt, wenn der Benutzer die Maus bewegt
Wird in der Statusleiste angezeigt, wenn Sie zu diesem Menüpunkt wechseln. }
StrCopy(pszName, PChar('Durch Klicken auf diesen Menüpunkt werden Dateivorgänge ausgeführt.'));
Ergebnis := NOERROR;
Ende
anders
Ergebnis := E_INVALIDARG;
Ende;
Typ
TContextMenuFactory = class(TComObjectFactory)
öffentlich
procedure UpdateRegistry(Register: Boolean);
Ende;
procedure TContextMenuFactory.UpdateRegistry(Register: Boolean);
var
Klassen-ID: string;
beginnen
Wenn Registrieren, dann beginnen
geerbt UpdateRegistry(Register);
ClassID := GUIDToString(Class_ContextMenu);
file://Fügen Sie beim Registrieren einer Erweiterungsbibliotheksdatei die Bibliothek zur Registrierung hinzu
CreateRegKey('*shellex', ', ');
CreateRegKey('*shellexContextMenuHandlers', ', ');
CreateRegKey('*shellexContextMenuHandlersFileOpreation', ', ClassID);
file://wenn das Betriebssystem Windows NT ist
if (Win32Platform = VER_PLATFORM_WIN32_NT) dann
mit TRegistry.Create tun
versuchen
RootKey := HKEY_LOCAL_MACHINE;
OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionShell Extensions', True);
OpenKey('Genehmigt', True);
WriteString(ClassID, 'Context Menu Shell Extension');
Endlich
Frei;
Ende;
Ende
sonst beginnen
DeleteRegKey('*shellexContextMenuHandlersFileOpreation');
geerbt UpdateRegistry(Register);
Ende;
Ende;
Initialisierung
TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,
', 'Kontextmenü-Shell-Erweiterung', ciMultiInstance,tmApartment);
Ende.
Fügen Sie dem OpWindow-Fenster ein TListBox-Steuerelement und zwei TButton-Steuerelemente hinzu. Die Programmliste von OpWindows.pas lautet wie folgt:
Einheit opwindow;
Schnittstelle
verwendet
Windows, Nachrichten, SysUtils, Klassen, Grafiken, Steuerelemente, Formulare, Dialoge,
ExtCtrls, StdCtrls,shlobj,shellapi,ActiveX;
Typ
TForm1 = Klasse(TForm)
ListBox1: TListBox;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
Privat
{Private Erklärungen}
öffentlich
FileList:TStringList;
{Öffentliche Erklärungen}
Ende;
var
Form1: TForm1;
Durchführung
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
beginnen
FileList:=TStringList.Create;
Button1.Caption :='Datei kopieren';
Button2.Caption :='Dateien verschieben';
Selbst.Show;
Ende;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
beginnen
FileList.Free;
Ende;
procedure TForm1.Button1Click(Sender: TObject);
var
sPath: string;
fsTemp:SHFILEOPSTRUCT;
i:Ganzzahl;
beginnen
sPath:=InputBox('Dateivorgang','Kopierpfad eingeben','c:windows');
if sPath<>'then begin
fsTemp.Wnd := Self.Handle;
file://Dateioperationstyp festlegen
fsTemp.wFunc :=FO_COPY;
file:// ermöglicht das Rückgängigmachen von Vorgängen
fsTemp.fFlags :=FOF_ALLOWUNDO;
für i:=0 bis ListBox1.Items.Count-1 beginnen
file://vollständiger Pfadname der Quelldatei
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
file://Pfad zum Kopieren
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='Datei kopieren';
wenn SHFileOperation(fsTemp)<>0 dann
ShowMessage('Dateikopie fehlgeschlagen');
Ende;
Ende;
Ende;
procedure TForm1.Button2Click(Sender: TObject);
var
sPath: string;
fsTemp:SHFILEOPSTRUCT;
i:Ganzzahl;
beginnen
sPath:=InputBox('Dateioperation','Eingabebewegungspfad','c:windows');
if sPath<>'then begin
fsTemp.Wnd := Self.Handle;
fsTemp.wFunc :=FO_MOVE;
fsTemp.fFlags :=FOF_ALLOWUNDO;
für i:=0 bis ListBox1.Items.Count-1 beginnen
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='Dateien verschieben';
wenn SHFileOperation(fsTemp)<>0 dann
ShowMessage('Dateikopie fehlgeschlagen');
Ende;
Ende;
Ende;
Ende.
Klicken Sie im Menü auf den Eintrag „Kontextmenü erstellen“ und Delphi erstellt die Datei „Contextmenu.dll“. Dies ist das kontextsensitive Menüprogramm.
Verwenden Sie Regsvr32.exe, um das Programm zu registrieren, klicken Sie dann mit der rechten Maustaste auf eine oder mehrere Dateien im Windows Explorer und es wird im Kontextmenü angezeigt.
Es gibt einen zusätzlichen Menüpunkt für Dateioperationen. Klicken Sie auf diesen Punkt und die Dateinamen aller von Ihnen ausgewählten Dateien werden in der Liste im Popup-Fenster aufgelistet. Sie können die Schaltfläche „Datei kopieren“ wählen
Mit der Schaltfläche „Datei verschieben“ werden Dateivorgänge ausgeführt.