Usando Delphi para escribir extensiones de shell de Windows
Los amigos que estén familiarizados con los principios de los sistemas operativos sabrán que un sistema operativo completo proporcionará un shell para facilitar a los usuarios comunes.
Utilice diversas funciones proporcionadas por el sistema operativo. El shell de Windows (aquí se refiere al sistema operativo Windows 95, Windows NT4.0 o superior) no sólo proporciona
No solo proporciona una interfaz gráfica GUI conveniente y hermosa, sino que también proporciona potentes funciones de extensión de shell. Es posible que vea estas extensiones de shell en muchos programas. Por ejemplo en tu
Si Winzip está instalado en el sistema, cuando haga clic derecho en una carpeta o archivo en el Explorador de Windows, el archivo Winzip aparecerá en el menú emergente.
menú abreviado. O la carpeta del sitio FTP que aparece en el Explorador de Windows en Bullet FTP.
Windows admite siete tipos de extensiones de shell (llamadas controladores) y sus funciones correspondientes se describen brevemente a continuación:
(1) Controladores de menú contextual: agregue menús contextuales a tipos específicos de objetos de archivo;
(2) Los controladores de arrastrar y soltar se utilizan para admitir la transmisión de datos OLE cuando los usuarios realizan operaciones de arrastrar y soltar en ciertos tipos de objetos de archivo;
(3) Los controladores de iconos se utilizan para proporcionar un icono único a un determinado objeto de archivo y también pueden especificar un icono para un determinado tipo de objeto de archivo;
(4) Los controladores de hojas de propiedades agregan páginas de propiedades a los objetos de archivo (es decir, haga clic con el botón derecho en el objeto de archivo o en el objeto de carpeta y seleccione Propiedades en el menú emergente
cuadro de diálogo que aparece después del elemento), las páginas de propiedades pueden ser compartidas por objetos de archivo del mismo tipo, o se puede asignar una página de propiedades única a un objeto de archivo;
(5) El sistema llamará a los controladores de gancho de copia cuando el objeto de carpeta o de impresora se copie, mueva, elimine o cambie de nombre a través de Windows.
Agregue controladores de gancho de copia para permitir o prohibir ciertas operaciones;
(6) El sistema llamará a los controladores de destino de colocación cuando un objeto se arrastra y se suelta sobre otro objeto;
(7) El sistema llamará a los controladores de objetos de datos cuando se arrastren, suelten, copien o peguen archivos.
Todas las extensiones de shell de Windows se basan en el modelo de componentes COM (Modelo de objetos componentes) y el shell accede a los objetos a través de interfaces.
Las extensiones de Shell están diseñadas como programas de servidor en proceso de 32 bits y brindan servicios al sistema operativo en forma de bibliotecas de enlaces dinámicos. Por tanto, si quieres utilizar Windows
Si se amplía la interfaz de usuario, es muy necesario tener algunos conocimientos sobre cómo escribir objetos COM. Debido a limitaciones de espacio, COM no se presentará aquí. Los lectores pueden consultarlo.
Según la biblioteca MSDN de Microsoft o los documentos de ayuda relacionados, una interfaz puede considerarse como una clase especial que contiene un conjunto de funciones y procedimientos que se pueden utilizar para operar un objeto.
Después de escribir sus extensiones de shell, debe registrarlas para que entren en vigor. Todas las extensiones de shell deben estar en el registro de Windows con la clave HKEY_CLASSES_ROOTCLSID
Regístrese a continuación. Debajo de esta clave, puede encontrar muchas claves con nombres como {0000002F-0000-0000-C000-000000000046}. Dichas claves son identificadores de clase únicos a nivel mundial.
Guía. Cada extensión de shell debe tener un identificador de clase único global, que es la forma en que Windows encuentra el controlador de extensión de shell.
La ubicación de la biblioteca de vínculos dinámicos de la extensión de shell en el sistema se registra en la subclave InProcServer32 bajo el identificador de clase. Las extensiones de Shell asociadas con un tipo de archivo se registran en
Debajo de la clave primaria shellex del tipo correspondiente. Si el sistema operativo Windows es Windows NT, la extensión del shell también debe estar en el registro.
Regístrese con la clave principal HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionShellExtensionsApproved.
Después de compilar el programa DLL de extensión de shell, puede usar regsvr32.exe proporcionado por el propio Windows para registrar el programa del servidor DLL. Si usa Delphi, también puede
Para registrarse, seleccione Registrar servidor ActiveX en el menú Ejecutar.
Primero, presentemos una aplicación de extensión de shell más utilizada: el menú contextual, que aparece cuando hace clic con el botón derecho en un archivo o carpeta en Windows.
Este menú se llama menú contextual. Para agregar dinámicamente elementos de menú a un menú contextual, puede escribir un controlador de menú contextual. Por ejemplo, todos
El software familiar, como WinZip y UltraEdit, agrega dinámicamente elementos de menú al menú escribiendo un controlador de menú contextual. Si está instalado en el sistema.
WinZip, luego, cuando haga clic derecho en un archivo (carpeta) llamado Windows, su menú contextual tendrá un elemento de menú llamado Agregar a Windows.zip.
El controlador del menú contextual que se implementará en este artículo es similar al menú contextual proporcionado por WinZip. Agregará un
Elemento del menú de operación de archivos, al hacer clic en él, el programa de interfaz abrirá una ventana de operación de archivos para realizar la copia, movimiento y otras operaciones de archivos.
El controlador del menú contextual de escritura debe implementar tres interfaces: IShellExtInit, IContextMenu y TComObjectFactory. Implementación de IShellExtInit
Inicialización de la interfaz, el objeto de interfaz IContextMenu implementa el menú contextual y la interfaz IComObjectFactory implementa la creación del objeto.
La implementación específica del programa se presenta a continuación. Primero, haga clic en el elemento Archivo|Nuevo del menú en Delphi, seleccione DLL en la ventana Nuevo elemento para crear un archivo de proyecto DLL.
Luego haga clic en el elemento Archivo|Nuevo del menú, seleccione Unidad en la ventana Nuevo elemento para crear un archivo de unidad, haga clic en el elemento Archivo|Nuevo del menú y seleccione Unidad en la ventana Nuevo elemento.
Seleccione Formulario para crear una nueva ventana. Guarde el archivo del proyecto como Contextmenu.dpr, Unit1 como Contextmenuhandle.pas y guarde el formulario como
OpWindow.pas.
La lista de programas de Contextmenu.dpr es la siguiente:
menú contextual de la biblioteca;
usos
servicio de comunicaciones,
identificador del menú contextual en 'contextmenuhandle.pas',
ventana operativa en 'opwindow.pas' {Form2};
exportaciones
DllGetClassObjeto,
DllCanDescargar ahora,
servidor dllregister,
DllUnregisterServer;
{$R *.TLB}
{$R*.RES}
comenzar
fin.
La lista de programas de Contextmenuhandle es la siguiente:
unidad ContextMenuHandle;
interfaz
utiliza Windows, ActiveX, ComObj, ShlObj, Clases;
tipo
TContextMenu = clase(TComObject,IShellExtInit,IContextMenu)
privado
FFileName: matriz[0..MAX_PATH] de Char;
protegido
función IShellExtInit.Initialize = SEIInitialize // Evitar advertencia del compilador
función SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResultado;
función QueryContextMenu(Menú: HMENU; indexMenu, idCmdFirst, idCmdLast,
uFlags: UINT): HResultado;
función InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
función GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HResult;
fin;
constante
Class_ContextMenu: TGUID = '{19741013-C829-11D1-8233-0020AF3E97A0}';
{El identificador único global (GUID) es un valor de 16 bytes (128 bytes) que identifica de forma única una interfaz}
var
Lista de archivos:TStringList;
implementación
utiliza ComServ, SysUtils, ShellApi, Registro, UnitForm;
función TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResultado;
var
Medio Stg: Medio TStg;
FormatoEtc: TFormatEtc;
Número de archivo,i:Entero;
comenzar
file://Si lpdobj es igual a Nil, esta llamada falla
si (lpdobj = nil) entonces comienza
Resultado := E_INVALIDARG;
Salida;
fin;
file:// primero inicializa y borra FileList para agregar archivos
ListaArchivos:=TStringList.Create;
Lista de archivos.Borrar;
file://Inicializar archivo en formato portapapeles
con FormatEtc comienza
cfFormato := CF_HDROP;
ptd := nulo;
dwaspect := DVASPECT_CONTENT;
índice := -1;
tymed := TYMED_HGLOBAL;
fin;
Resultado := lpdobj.GetData(FormatEtc, StgMedium);
si falla (resultado), salga;
file://Primera consulta del número de archivos seleccionados por el usuario
Número de archivo := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);
file:// lee en un bucle y guarda todos los archivos seleccionados por el usuario en FileList
para i:=0 a FileNumber-1 comience
DragQueryFile(StgMedium.hGlobal, i, FFileName, SizeOf(FFileName));
FileList.Add(FFileName);
Resultado := NOERROR;
fin;
LiberarStgMedio(StgMedio);
fin;
función TContextMenu.QueryContextMenu(Menú: HMENU; indexMenu, idCmdFirst,
idCmdLast, uFlags: UINT): HResult;
comenzar
Resultado := 0;
si ((uFlags y $0000000F) = CMF_NORMAL) o
((uFlags y CMF_EXPLORE) <> 0) luego comience
//Agregue un elemento de menú al menú contextual, el título del elemento de menú es Ver archivo de mapa de bits
InsertMenu(Menú, indexMenu, MF_STRING o MF_BYPOSITION, idCmdFirst,
PChar('operación de archivo'));
// Devuelve el número de elementos de menú agregados
Resultado := 1;
fin;
fin;
función TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
frmOP:TForm1;
comenzar
// Primero asegúrese de que el proceso sea llamado por el sistema y no por un programa
si (HiWord(Integer(lpici.lpVerb)) <> 0) entonces
comenzar
Resultado := E_FAIL;
Salida;
fin;
// Determinar la validez de los parámetros pasados.
si (LoWord(lpici.lpVerb) <> 0) entonces comienza
Resultado := E_INVALIDARG;
Salida;
fin;
file://Crear una ventana de operación de archivos
frmOP:=TForm1.Create(nil);
file://agrega una lista de todos los archivos a la lista en la ventana de operación de archivos
frmOP.ListBox1.Items := ListaDeArchivos;
Resultado := NOERROR;
fin;
función TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszNombre: LPSTR; cchMax: UINT): HRESULT;
comenzar
si (idCmd = 0) entonces comienza
si (uType = GCS_HELPTEXT) entonces
{Devuelve la información de ayuda de este elemento del menú. Esta información de ayuda se mostrará cuando el usuario mueva el mouse.
Aparece en la barra de estado al pasar a este elemento del menú. }
StrCopy(pszName, PChar('Al hacer clic en este elemento del menú se realizarán operaciones con el archivo'));
Resultado := NOERROR;
fin
demás
Resultado := E_INVALIDARG;
fin;
tipo
TContextMenuFactory = clase(TComObjectFactory)
público
procedimiento UpdateRegistry(Registro: booleano anulación);
fin;
procedimiento TContextMenuFactory.UpdateRegistry(Registro: booleano);
var
ID de clase: cadena;
comenzar
si se registra entonces comience
heredado UpdateRegistry (Registro);
ClassID := GUIDToString(Class_ContextMenu);
file://Al registrar un archivo de biblioteca de extensión, agregue la biblioteca al registro
CreateRegKey('*shellex', ', ');
CreateRegKey('*shellexContextMenuHandlers', ', ');
CreateRegKey('*shellexContextMenuHandlersFileOpreation', ', ClassID);
file://si el sistema operativo es Windows NT
si (Win32Platform = VER_PLATFORM_WIN32_NT) entonces
con TRegistry.Create do
intentar
Clave raíz := HKEY_LOCAL_MACHINE;
OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionShell Extensiones', Verdadero);
OpenKey('Aprobado', Verdadero);
WriteString(ClassID, 'Extensión del shell del menú contextual');
finalmente
Gratis;
fin;
fin
si no, empezar
DeleteRegKey('*shellexContextMenuHandlersFileOpreation');
heredado UpdateRegistry (Registro);
fin;
fin;
inicialización
TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,
', 'Extensión del Shell del menú contextual', ciMultiInstance,tmApartment);
fin.
Agregue un control TListBox y dos controles TButton a la ventana OpWindow. La lista de programas de OpWindows.pas es la siguiente:
ventana de operación de la unidad;
interfaz
usos
Windows, Mensajes, SysUtils, Clases, Gráficos, Controles, Formularios, Cuadros de diálogo,
ExtCtrls, StdCtrls, shlobj, shellapi, ActiveX;
tipo
TForm1 = clase(TForm)
ListBox1: TListBox;
Botón1: TBotón;
Botón2: TBotón;
procedimiento FormCreate(Remitente: TObject);
procedimiento FormClose(Remitente: TObject; var Acción: TCloseAction);
procedimiento Button1Click(Remitente: TObject);
procedimiento Button2Click(Remitente: TObject);
privado
{Declaraciones privadas}
público
Lista de archivos:TStringList;
{Declaraciones públicas}
fin;
var
Formulario1: TForm1;
implementación
{$R *.DFM}
procedimiento TForm1.FormCreate(Remitente: TObject);
comenzar
ListaArchivos:=TStringList.Create;
Button1.Caption :='Copiar archivo';
Button2.Caption :='Mover archivos';
Auto.Show;
fin;
procedimiento TForm1.FormClose(Remitente: TObject; var Acción: TCloseAction);
comenzar
Lista de archivos.Gratis;
fin;
procedimiento TForm1.Button1Click(Remitente: TObject);
var
sPath:cadena;
fsTemp:SHFILEOPSTRUCT;
yo: entero;
comenzar
sPath:=InputBox('Operación de archivo','Ruta de copia de entrada','c:windows');
si sPath<>'entonces comienza
fsTemp.Wnd:= Self.Handle;
archivo://establecer tipo de operación de archivo
fsTemp.wFunc :=FO_COPY;
file:// permite deshacer operaciones
fsTemp.fFlags :=FOF_ALLOWUNDO;
para i:=0 a ListBox1.Items.Count-1 comience
file://nombre de ruta completo del archivo fuente
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
archivo://ruta a copiar
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='Copiar archivo';
si SHFileOperation(fsTemp)<>0 entonces
ShowMessage('Error en la copia del archivo');
fin;
fin;
fin;
procedimiento TForm1.Button2Click (Remitente: TObject);
var
sPath:cadena;
fsTemp:SHFILEOPSTRUCT;
yo: entero;
comenzar
sPath:=InputBox('Operación de archivo','Ruta de movimiento de entrada','c:windows');
si sPath<>'entonces comienza
fsTemp.Wnd:= Self.Handle;
fsTemp.wFunc:=FO_MOVE;
fsTemp.fFlags :=FOF_ALLOWUNDO;
para i:=0 a ListBox1.Items.Count-1 comience
fsTemp.pFrom := PChar(ListBox1.Items.Strings[i]);
fsTemp.pTo := PChar(sPath);
fsTemp.lpszProgressTitle:='Mover archivos';
si SHFileOperation(fsTemp)<>0 entonces
ShowMessage('Error en la copia del archivo');
fin;
fin;
fin;
fin.
Haga clic en el elemento Proyecto | Construir ContextMenu en el menú y Delphi creará el archivo Contextmenu.dll. Este es el programa de menú contextual.
Utilice Regsvr32.exe para registrar el programa, luego haga clic derecho en uno o varios archivos en el Explorador de Windows y aparecerá en el menú contextual.
Hay un elemento de menú adicional para operaciones de archivos. Haga clic en este elemento y los nombres de todos los archivos que seleccionó aparecerán en la lista de la ventana emergente. Puede elegir el botón copiar archivo o.
El botón Mover archivo realiza operaciones con archivos.