核心代码已经完成,来做一下用户界面吧!仿照着“windows优化大师”我做了界面,左边我用的是TSpeedButton组件,右边是TNotePage组件。当用户点击一个TSpeedButton时,调用TNotePage.ActivePage := '页面的代号'就可以激活相应的配置界面。这个软件需要在后台运行,那么就让它在平时缩小到系统托盘吧!将程序缩小到系统托盘很容易做到,网上有很多这样的示例代码。我手头有一个控件cooltray4.3可以用来实现系统托盘的功能,我就懒得自己再去写代码了。
软件运行一切良好。不过一直令我耿耿于怀的就是网上那种防复制的网页:不管你怎么拖动鼠标,那些文字就是无法被选定。仔细想一想,既然文字能够在IE上显示就一定可以得到它们。在MSDN中找了半天,才找到解决方法。可以通过ShellWindows集合来代表属于shell 的当前打开的窗口的集合,而IE就是属于shell的一个应用程序。用CoShellWindows.Create得到当前打开的shell的接口(IShellWindows),调用接口的Count属性得到当前打开的shell的数量,然后遍历这些窗口,尝试从接口中取出IWebbrowser2接口(通过ShellWindow.Item(I) as IWebbrowser2这样的接口类型转换方式),如果结果不为nil说明这个窗口是IE窗口。之后只要调用IWebBrowser2接口的相应方法即可得到窗口中的文字、URL、标题等内容了。
示例代码如下:
{需要使用mshtml,SHdocvw两个单元}  
var
 ShellWindow : IShellWindows;
 WebBrowser : IWebBrowser2;
 I, ShellWindowCount: integer;
 HTMLdocument : IHTMLdocument2;
 URL, Title, Text:string;
begin
  ShellWindow := CoShellWindows.Create;
  ShellWindowCount := ShellWindow.Count;
  for I := 0 to ShellWindowCount-1 do
  begin
    WebBrowser := ShellWindow.Item(I) as IWebbrowser2;
    if WebBrowser <> nil then
        begin
            HTMLDocument := WebBrowser.Document as IHtmlDocument2;
            URL := URL;
            Title := HTMLDocument.title;
            Text := HTMLDocument.body.outerText ;
            ShowMessage(URL+Title+Text);
        end;
  end;
  ShellWindow := nil;
end;我们定义一个记录类型:
  TWebPageRecord = record
    URL: string;  file://保存网页的URL
    Title: string;//保存网页的标题
    Text: string; file://保存网页的文字
  end;然后定义一个TWebPageRecord类型的数组FWebPageRecordArray,大小定位20吧(我想一般人不会打开20个以上的IE吧):
Const  MAXPAGECOUNT = 20;
……
FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
在遍历IE窗口时,向数组中的元素的相应字段复制即可。
对这个复制防复制(好拗口呀:))网页的功能也封装成一个类吧!
type
  TWebCracker = class(TObject)
  private
    FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
    FWebPageCount: Integer;
  public
    procedure SnapShot;
    function GetWebText(AIndex:integer): string;
    function GetWebTitle(AIndex:integer): string;
    function GetWebURL(AIndex:integer): string;
    procedure Clear;
    procedure Refresh;
    function GetWebPageCount: Integer;
  end;
在用户界面中,可以通过调用TWebCracker.SnapShot;来对打开的IE窗口进行遍历,并保存到FWebPageRecordArray这个数组中。通过TWebCracker.GetWebPageCount方法可以得到FWebPageRecordArray中保存的页面的个数,通过GetWebText、GetWebTitle、GetWebURL就可以得到指定页面的文字、标题或是URL。
一切都已经搞定了!爽!通过编写这个小软件,我是收获颇丰呀!除了学到了上边这些技巧外,我还有一些小的经验,愿意与大家分享:
1、为用户着想,让用户舒服
用户是上帝嘛!以那个Ctrl+Alt+S热键来说吧:一般用户上网都是右手握鼠标,空下来的只有左手。小拇指按Ctrl,大拇指按Alt,食指刚好能按到S键,不费一点力气!
2、 良好的编码习惯
(1)不要出现魔术数
以TWebCracker定义的那个FWebPageRecordArray数组来说:
Const  MAXPAGECOUNT = 20;
……
FWebPageRecordArray : array [0..MAXPAGECOUNT-1] of TWebPageRecord;
别人一看MAXPAGECOUNT就知道是什么意思,而如果你写成:
FWebPageRecordArray : array [0..19] of TWebPageRecord;
估计除了你自己没有人能够知道19到底是什么意思。
(2)用sender的方式增强代码的健壮性
procedure TMainfrm.CBAutoRunClick(Sender: TObject);
Const
  SIGNINREGISTRY = 'WebSuction';
begin
  if (Sender as TCheckBox).Checked then  
     AddToAutoRun(Application.ExeName,SIGNINREGISTRY)
  else DelAutoRun(SIGNINREGISTRY);
end;
这样即使Checkbox1改了名字也不怕。
又如:
procedure TMainfrm.N1Click(Sender: TObject);
begin
  if (Sender as TMenuItem).Caption = '暂停(&S)' then
    begin
      (Sender as TMenuItem).Caption := '开始(&R)';
      FWebPageSaver.Pause;
    end
  else
    begin
      (Sender as TMenuItem).Caption := '暂停(&S)';
      FWebPageSaver.ReStart;
    end;
end;
(3)不要直接使用Tform2单元的全局Form2变量,那样就破坏了封装性
procedure TMainfrm.SBNextClick(Sender: TObject);
var
  LSelectedIndex : integer;
  FormDisplay : Tform2;
begin
  LSelectedIndex := LBWebPage.ItemIndex;
  if LSelectedIndex <> -1 then
  begin
    FormDisplay := Tform2.Create(self);
    FormDisplay.SetContent(FWebCracker.GetWebText(LSelectedIndex));
    FormDisplay.Show;
  end;
end;
在TForm2中定义 SetContent方法
procedure TWebCrackfrm.SetContent(AText:string);
begin
  Memo.Clear;
  Memo.Lines.Add(AText);
end;