主页 > 编程资料 > Delphi >
发布时间:2015-09-22 作者:网络 阅读:103次

 

无论是IE中的“图片另存为”还是QQ图片工具条,保存图片的时候都需要选择路径,文件名,然后再按保存。如果是一两张图片这样保存自然无所谓,但是如果长期需要做图片收集还是自己DIY一个菜单吧。
       如果你只是想了解用Delphi编写ActiveX或者IE 右键菜单的相关信息,注意每一步下面的Addition,那里有相关主题的更多信息。

正文:
       这个菜单实现的功能是:浏览网页时在图片上单击右键,弹出菜单中比平时多一项“自动保存图片”,单击后自动将图片保存到C:\Images\下面,文件名为默认的文件名,如果遇到重名情况,自动在原文件名后添加几个随机生成的字母,然后自动保存。
       实现方法简介:
            IE右键菜单项    ---------- 修改注册表,添加菜单入口
            响应菜单        ---------- VBScript脚本调用ActiveX Object
            主体:保存文件 ---------- Delphi ActiveX Library & Automation Object


Step by Step:
       1.添加IE右键菜单项
         开始菜单,运行,输入regedit,回车,依次展开
           HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt
         添加一个子键:自动保存图片&Z,修改默认值为:C:\Program Files\PicSaver\PicSaver.htm (这是稍后我们将要编写的脚本),在新建的子键下添加一个REG_DWORD类型的项Contexts,修改值为2。
         关闭注册表以保存
       
         此时,新打开的IE窗口在图片上单击右键,已经出现自动保存图片菜单。

         Addition:一个子键对应一个菜单项,默认值对应单击菜单时需要激活的脚本文件,Contexts是一个可选项。设置为不同的值表示仅在特定内容上单击右键才会出现这个项目。
                  Context IE 6.0典型值:
                      Context           Value

                      ---------------------------
                      Default                0x1
                      Images                0x2
                      Controls              0x4
                      Tables                0x8
                      Text selection     0x10
                      Anchor               0x20


                  添加菜单项更多信息参见MSDN:http://msdn2.microsoft.com/en-us/library/Aa753589.aspx

        2.编写VBScript脚本
            新建一个空文件,输入以下内容:

            保存为C:\Program Files\PicSaver\PicSaver.htm

         Addition: 这个脚本参考了FlashGet下载软件的脚本。其中external.menuArguments可以获得对应的页面内容, elementFromPoint方法返回一个object(事实上就是那个单击的图片),img.href属性取得object对应的URL地址。
                   PicSaver.AutoSave是下面将要编写的ActiveX (Automation Object),调用了对象的SaveImage方法。

                   脚本中使用HTML 的参考资料比较少,只有MSDN的内容

http://msdn2.microsoft.com/en-us/library/ms533050.aspx

                   这个信息是很全的,但是检索很不方便。
                   脚本中使用Automation Object的方法与使用Scripting.FileSystemObject的方法完全相同,创建对象,访问属性(properties)和方法(methods)都很简单。
                   Scripting.FileSystemObject是内置的处理文件的object,Scripting.FileSystemObject的使用方法见:http://msdn2.microsoft.com/en-us/library/6kxy1a51.aspx,一般的VBScript教程里面都有详细说明。

        3.编写Automation Object: PicSaver.AutoSave
          这是最重要的部分。网上范例用.Net来编写的比较多,本例中我使用Delphi来编写。
          选择用Delphi而不用C++, .Net的原因是:我现在用的机器上没有Virtual Studio,只有Delphi 7。寒。
          进入正题,先打开Delphi7,File->close all,工具栏,New Item,选择ActiveX->ActiveX Library,Save,Project name为PicSaver。
          New Item,选择ActiveX->Automation Object,CoClass Name为AutoSave,其余项目保留默认值。
          弹出PicSaver.tlb窗口(如果没有看到,View->Type Library可以打开这个窗口),Save,Unit name为AutoSave。
          在左侧可以看到IAutoSave(接口),右键单击,选择New->Method,取名字为SaveImage,单击Parameters选项卡修改参数,Name:urlstr,Type:BSTR, 单击窗口上的Refresh Implementation。Save。
          关闭PicSaver.tlb窗口,弹出代码编辑器。可以看到Delphi已经自动生成了刚才定义的方法:
procedure SaveImage(const urlstr: WideString); safecall;
          接下来是Coding,没有太多可说的,附上我的源代码。

<---------------------------------Delphi Code---------------------------------->
unit AutoSave;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, PicSaver_TLB, StdVcl;

type
TAutoSave
= class(TAutoObject, IAutoSave)
protected
procedure SaveImage(const urlstr: WideString); safecall;

end;

implementation

uses ComServ, UrlMon, SysUtils, Dialogs, StrUtils;

function DownloadFile(SourceFile, DestFile: string): Boolean;
begin
try
Result :
= UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0, nil) = 0;
except
Result :
= False;
end;
end;

function rPos(const substr, str: AnsiString): Integer;
begin
Result :
= length(str) - pos(AnsiReverseString(substr), AnsiReverseString(str)) + 1;
end;

function rename(filename: string): string;
var
i, p: integer;
randomchar: char;
name, ext:
string;
begin
p :
= rpos('.', filename);
name :
= copy(filename, 1, p - 1);
ext :
= copy(filename, p + 1, length(filename) - p);
result :
= name;
for i := 1 to 5 do
begin
randomchar :
= Chr(random(300) mod 26 + 65);
result :
= result + randomchar;
end;
result :
= result + '.' + ext;
end;

procedure TAutoSave.SaveImage(const urlstr: WideString);
const
PATH
= 'C:\Images';
var
url, DestFile, name, rname:
string;
len, p: integer;
begin
url :
= urlstr;
//parse file name and get destfile name
len :
= length(url);
p :
= rpos('/', url);
name :
= copy(url, p + 1, len - p);
rname :
= name;
while fileexists(PATH + rname) do
begin
rname :
= rename(name);
end;
name :
= rname;
DestFile :
= PATH + name;

if DownloadFile(url, DestFile) then
begin
//ShowMessage('保存成功!');
end
else
begin
ShowMessage(
'!!!!保存不成功!!!!');
end;
end;

initialization
TAutoObjectFactory.Create(ComServer, TAutoSave, Class_AutoSave,
ciMultiInstance, tmApartment);
end.

<-----------------------------End of Delphi Code-------------------------------->

          Save, Compile, Build。
          菜单:Run->Register ActiveX Server,弹出注册成功的提示。
          OK,整个工程完成。

         Addition: Delphi作为一款强大的IDE早已被众多程序员肯定。但是这次是我使用Delphi的最糟糕的经历。
                   因为“编写一个VBScript脚本里可以调用的object”相关的文档太难找了,开始的时候我选择了COM Object,编写一点问题都没有。但是VBScript CreateObject之后返回值根本不包含对象的引用。然后看到网上有很多例子都是使用ActiveX Control(控件),但是Delphi里面都是需要VCL Component来转换或者创建Active Form来实现,但是我需要的功能不是一个可视组件,只是需要一个方法和接口。之后又看到一些软件使用了BHO(Browser Helper Object),那个可以在页面加载时就开始运行,获取事件响应。BHO 也不符合我的要求。COM+好像与服务有关系,没有考虑。剩下的就只有Automation Object了,试一下居然OK了。
                   还有值得注意的是字符串参数一定要选BSTR,不能用LPSTR。如果选LPSTR,脚本运行的时候会出错,提示不支持的对象类型。
                   结论:右键菜单脚本调用object在Delphi中一定要选择Automation Object

        4.由于没有制作Setup安装程式,所以使用上需要注意:
          确保C:\Images存在
          Delphi 提示ActiveX DLL注册成功
          脚本文件存在,位置与注册表对应项一致


关键字词: