Delphi编写Shell扩展
用delphi创建一个外壳扩展(Shell Extension)程序的基本步骤如下:
(1) 创建一个 ActiveX Library 工程,命名为“CloudUpload“
(2) 创建一个新的自动化对象(Automation Object)。 命名为“ TCloudUploadContext ”
TCloudUploadContext 类必须实现两个接口即:IShellExtInit 和 IContextMenu,
这样就可以在Windows Explorer 中集成该上下文菜单(Context Menu)。
{ IShellExtInit Methods }
{ Initialize the context menu if a files was selected}
function IShellExtInit.Initialize = ShellExtInitialize;
function ShellExtInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult; stdcall;
{ IContextMenu Methods }
{ Initializes the context menu and it decides which items appear in it,
based on the flags you pass }
function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,
uFlags: UINT): HResult; stdcall;
{ Execute the command, which will be the upload to Amazon or Azure}
function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
{ Set help string on the Explorer status bar when the menu item is selected }
function GetCommandString(idCmd: UINT_PTR; uFlags: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HResult; stdcall;
ShellExtInitialize 定义了是否在 Windows Explorer 中显示上下文菜单(Context Menu)。
在该例子中,上下文菜单(Context Menu)仅当一个文件被选中的时候才显示出来,否则不会显示。
在一文件被选中时, FFileName 变量将接收该文件的文件名。
function TCloudUploadContextMenu.ShellExtInitialize(pidlFolder: PItemIDList;
lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
var
DataFormat: TFormatEtc;
StrgMedium: TStgMedium;
Buffer: array [0 .. MAX_PATH] of Char;
begin
Result := E_FAIL;
{ Check if an object was defined }
if lpdobj = nil then
Exit;
{ Prepare to get information about the object }
DataFormat.cfFormat := CF_HDROP;
DataFormat.ptd := nil;
DataFormat.dwAspect := DVASPECT_CONTENT;
DataFormat.lindex := -1;
DataFormat.tymed := TYMED_HGLOBAL;
if lpdobj.GetData(DataFormat, StrgMedium) <> S_OK then
Exit;
{ The implementation now support only one file }
if DragQueryFile(StrgMedium.hGlobal, $FFFFFFFF, nil, 0) = 1 then
begin
SetLength(FFileName, MAX_PATH);
DragQueryFile(StrgMedium.hGlobal, 0, @Buffer, SizeOf(Buffer));
FFileName := Buffer;
Result := NOERROR;
end
else
begin
// Don't show the Menu if more then one file was selected
FFileName := EmptyStr;
Result := E_FAIL;
end;
{ http://msdn.microsoft.com/en-us/library/ms693491(v=vs.85).aspx }
ReleaseStgMedium(StrgMedium);
end;
在上下文件菜单句柄(context menu handler)在IShellExtInit接口中被初始化之后,
Windows系统使用 IContextMenu 接口去调用(call)上下文件菜单句柄中的其他方法。
在这种情形下,它将调用(call) QueryContextMenu, GetCommandString 和 InvokeCommand。
上下文件菜单选项(包括 Amazon S3 和 Microsoft Azure )将通过 QueryContextMenu 方法被创建。
function TCloudUploadContextMenu.QueryContextMenu(Menu: HMENU;
indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult;
var
CloudMenuItem: TMenuItemInfo;
MenuCaption: String;
SubMenu: HMENU;
uId: UINT;
begin
{ only adding one menu CloudMenuItem, so generate the result code accordingly }
Result := MakeResult(SEVERITY_SUCCESS, 0, 3);
{ store the menu CloudMenuItem index }
FMenuItemIndex := indexMenu;
{ specify what the menu says, depending on where it was spawned }
if (uFlags = CMF_NORMAL) then // from the desktop
MenuCaption := 'Send file from Desktop to the Cloud'
else if (uFlags and CMF_VERBSONLY) = CMF_VERBSONLY then // from a shortcut
MenuCaption := 'Send file from Shourtcut to the Cloud'
else if (uFlags and CMF_EXPLORE) = CMF_EXPLORE then // from explorer
MenuCaption := 'Send file from Explorer to the Cloud'
else
{ fail for any other value }
Result := E_FAIL;
if Result <> E_FAIL then
begin
SubMenu := CreatePopupMenu;
uId := idCmdFirst;
InsertMenu(SubMenu, AmazonIndex, MF_BYPOSITION, uId, TClouds[AmazonIndex]);
Inc(uId);
InsertMenu(SubMenu, AzureIndex, MF_BYPOSITION, uId, TClouds[AzureIndex]);
FillChar(CloudMenuItem, SizeOf(TMenuItemInfo), #0);
CloudMenuItem.cbSize := SizeOf(TMenuItemInfo);
CloudMenuItem.fMask := MIIM_SUBMENU or MIIM_STRING or MIIM_ID;
CloudMenuItem.fType := MFT_STRING;
CloudMenuItem.wID := FMenuItemIndex;
CloudMenuItem.hSubMenu := SubMenu;
CloudMenuItem.dwTypeData := PWideChar(MenuCaption);
CloudMenuItem.cch := Length(MenuCaption);
InsertMenuItem(Menu, indexMenu, True, CloudMenuItem);
end;
end;
在 Windows Explorer 中你用鼠标滑过该云菜单项(Cloud menu items )时会在状态栏中显示出瞬时帮助(提示)信息。 这个提示信息定义并在GetCommandString 方法中实现。
function TCloudUploadContextMenu.GetCommandString(idCmd: UINT_PTR; uFlags: UINT;
pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult;
begin
Result := E_INVALIDARG;
{ Set help string on the Explorer status bar when the menu item is selected }
if (idCmd in [AmazonIndex, AzureIndex]) and (uFlags = GCS_HELPTEXT) then
begin
StrLCopy(PWideChar(pszName), PWideChar('Copy the selected file to ' +
TClouds[idCmd]), cchMax);
Result := NOERROR;
end;
end;
当用户点击了一个云菜单项(Cloud menu items)中某一项时,InvokeCommand 方法将被调用(call)并且启动一个上传被选中的文件到目标云(Cloud)上的进程。
这样,我们就已经有了该文件名,基于 lpici 这个参数,我们能够分辨用户点击了哪个菜单项。
function TCloudUploadContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
Item: Word;
begin
Result := E_FAIL;
if HiWord(Integer(lpici.lpVerb)) <> 0 then
Exit;
{ if the index matches the index for the menu, show the cloud options }
Item := LoWord(Integer(lpici.lpVerb));
if Item in [AmazonIndex, AzureIndex] then
begin
try
Upload(lpici.HWND, Item, FFileName);
except
on E: Exception do
MessageBox(lpici.hwnd, PWideChar(E.Message), 'Cloud Upload', MB_ICONERROR);
end;
Result := NOERROR;
end;
end;
为确保当 CloudUpload 被加载时,该 COM对象(COM object)被创建,有必要创建一个类工厂的一个实例,特别是要创建一个该外壳扩展对象(the shell extension object)的一个实例,该工厂实例将在 initialization代码段中被创建。
initialization
TCloudUploadObjectFactory.Create(ComServer, TCloudUploadContextMenu, CLASS_CloudUploadContextMenu, ciMultiInstance, tmApartment);
end.
由于该类工厂将负责注册或反注册该DLL,当你使用 regsvr32.exe 的时候,ApproveShellExtension 和 UpdateRegistry 两个方法将被调用(invoked)。
注册 CloudUpload 外壳扩展应用
以管理员身份运行cmd
注册命令:
regsvr32 <PATH WHERE IS LOCATED THE DLL>CloudUpload.dll
反注册命令:
regsvr32 <PATH WHERE IS LOCATED THE DLL>CloudUpload.dll /u
原文地址:http://www.andreanolanusse.com/en/shell-extension-for-windows-32-bit-and-64-bit-with-delphi-xe2/
Delphi编写Shell扩展的更多相关文章
- 利用Delphi编写IE扩展
就是如何使IE扩展组件可以响应事件. 在自己的程序中使用过WebBrowser控件的朋友都知道,WebBrowser控件定义了诸如BeforeNavigate.DownloadComplete ...
- 启动VNC Shell扩展
下载source files - 18.3 Kb Introduction 我们使用RealVNC来远程控制我们的网络中的pc机,VNC是一个伟大的产品,但如果不记住计算机名称,它可以是乏味的,在网络 ...
- Windows Shell编程之如何编写为文件对象弹出信息框的Shell扩展
有关COM编程资料 转载:http://www.cnblogs.com/lzjsky/archive/2010/11/22/1884702.html 活动桌面引入一项新特性, 当你在某些特定对象上旋停 ...
- Linux下高效编写Shell——shell特殊字符汇总
Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...
- 利用Delphi编写Socket通信程序
一.Delphi与Socket 计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议.TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登 ...
- python编写shell脚本详细讲解
python编写shell脚本详细讲解 那,python可以做shell脚本吗? 首先介绍一个函数: os.system(command) 这个函数可以调用shell运行命令行command并且返回它 ...
- 使用golang 编写postgresql 扩展
postgresql 的扩展可以帮助我们做好多强大的事情,支持的开发语言有lua.perl.java.js.c 社区有人开发了一个可以基于golang开发pg 扩展的项目,使用起来很方便,同时为我 ...
- 编写Postgres扩展之五:代码组织和版本控制
原文:http://big-elephants.com/2015-11/writing-postgres-extensions-part-v/ 编译:Tacey Wong 在关于编写Postgres扩 ...
- 编写Postgres扩展之四:测试
原文:http://big-elephants.com/2015-11/writing-postgres-extensions-part-iv/ 编译:http://big-elephants.com ...
随机推荐
- webpack入门详解
webpack入门详解(基于webpack 3.5.4 2017-8-22) webpack常用命令: webpack --display-error-details //执行打包 webpa ...
- 4G模块*99#拨号上网
操作系统:win10 模块型号:quectel EC20 CE FAG 4G模块拨号步骤如下: 1. 打开网络和internet设置 2. 选择“拨号” 3. 选择“设置新连接” 4. 选择“拨号调至 ...
- Java GC2
虚拟机中共划分为3个代:年轻代,老年代,持久代:其中持久代主要存放Java类的类信息,与垃圾收集要收集的Java对象关系不大,年轻代和老年代的划分是对垃圾收集影响较大的 年轻代: HotSpot JV ...
- CentOS 关闭图形用户界面
1 centos 7以下版本 vim /etc/inittab :initdefault: #改为 :initdefault: 2. centos 7.x版本 rm -f /etc/systemd/s ...
- webpack实现scss编译配置
1.webpack.start.js: var webpack = require('webpack'); var SpritesmithPlugin = require('webpack-sprit ...
- urllib模块学习
一.urllib库 概念:urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urll ...
- Ddr2,ddr3,ddr4内存条的读写速率
理论极限值是可以计算的:1333MHz * 64bit(单通道,双通道则128bit) / 8(位到字节单位转换) = 10.664GB/s.这只是理论,实际发挥还要看内存控制器,实际上1333单条跑 ...
- SUI-mobile起步
减少不必要造轮子的过程,于是在APP项目中推进SUI Mobile的使用,主要目的是使用它的一些基本样式,以及各种封装好的组件,但并没有创建单页应用. 刚刚开始使用,使用之中遇到一个槽点,记录一下(主 ...
- centos7.5下安装teamview
centos7.5下安装teamview, 1 安装 wget https://download.teamviewer.com/download/linux/teamviewer-host.x86_6 ...
- web:频繁刷新浏览器的页面【小工具】
[目的] 频繁刷新某一浏览器页面,小测试一下加载性能,或者打开的文件是否及时关闭,会不会导致服务器奔溃 [小工具] 新建txt,输入以下内容,并保存为html的格式,然后在浏览器中打开,则会定时刷新指 ...