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 ...
随机推荐
- object视频播放
param name标签是在这个播放插件中嵌入的一些功能和播放参数: <param name="playcount" value="1"><! ...
- POJ3159 Candies
#include <iostream> #include <queue> #include <cstring> #define maxn 30005 #define ...
- Node JS 8 如何在浏览器上在线调试
0:为何专门针对Node8写这个 从nodejs8开始,node去掉了_debugger , 内部集成了inspect , 以往使用node-inspect实现的在线调试不再可用.node8开始要用新 ...
- ElasticSearch概述
ElasticSearch 产生背景 Lucene 定义 ElasticSearch 定义 ElasticSearch vs Lucene ElasticSearch vs Solr Elastic ...
- Java 9 - Java Number类
Java Number类 一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte.int.long.double等. 实例 int i = 5000; float gpa = 13.65 ...
- Python : 什么是*args和**kwargs[转载]
例子 def foo(*args, **kwargs):print 'args = ', argsprint 'kwargs = ', kwargsprint '------------------- ...
- General error: 24374 OCIStmtFetch: ORA-24374: define not done before fetch or execute and fetch
问题 $sql='insert into "test"("id") values(4)'; $res=$this->conn->query($sql ...
- (二)apache atlas配置和运行
上一篇文章,我们已经构建出了altas的安装包,所以我们继续使用安装包配置和运行atlas 首先解压atlas压缩包,授予bin目录下的执行权限 1.默认启动atlas cd atlas/bin/ p ...
- iOS oc 检测手机移动网络和wifi是否开启
利用Reachability的的一个方法currentReachabilityStatus 获取枚举类型值判断是否为2即可,不是2就不是WiFi. enum { // DDG Netwo ...
- uva-310-L--system-暴力枚举
题意:输入四个字符串a,b,w,z,经过一定的替换规则,问w或者w的子串中是否包含z. 替换规则如下.w中的字符a全部替换成a字符串,b字符全部替换成b字符串. 枚举过程, 根据替换规则对w进行替换, ...