由于客户需要,WebBrowser动态更改里面的html内容后,本来的网址 比如 http://www.qq.com ,
在更改源码后,WebBrowser的当前页面的url 变成了 about:blank 了。
我现在需要的 更改 WebBrowser 里的内容后 原来的页面 url 不要发生变化。
请问各位有什么好的方法么?

解决方案 »

  1.   

    可能是你更改前navigate了blank页面
      

  2.   

    更改html的时候在html最前面加上<base href="原Url">
      

  3.   


    没有效果,使用截取数据流的方式 更改了 源码后,测试当前页面的 url 还是 about:blank
      

  4.   

    我记得用流加载后,URL总是BLANK.
    用protocol协议应该可以解决楼主的问题.
      

  5.   


    应该不是吧.
    如果是防篡改,就该不允许直接修改内容.修改后的内容是无法再回写到原网页上让其他人看到的.
    我觉得可能是因为装载来源的原因.因为修改了源,它就不再是指向XXX.COM了,那是指向哪里呢?因为是直接修改的流,MS又搞不清,所以就当它是BLANK了.
    如果我的猜测是对的,用protocol应该是可以的.
      

  6.   


    如何用protocol?能举一个例子么?
    分不够可再加,谢谢。不过我觉的 更改流的方式不是 在数据流返回的过程中修改的,而是在数据返回后再使用流的方式修改。
    所以问题就出在这里。
    如果能够在数据没返回前,就直接修改流中的内容,应该行,但这可能涉及到网络封包了,不知道大家有什么好的方法。谢谢
      

  7.   

    说明:下面的是从流加载网页内容的例子.Protocols当然也允许从文件加载.不论哪种方式,都必须有个URL.这样,就可以满足你去掉about:blank的要求了.
    Protocols我以前用过,但你的要求现在没有测试,只是认为应该可以.
    ------------------------------------------------------------------------
    用IE支持的Asynchronous Pluggable Protocols实现直接从数据库取得信息显示在WebBrowser中作者 : xianjun
    标题 : 用IE支持的Asynchronous Pluggable Protocols实现直接从数据库取得信息显示在WebBrowser中 
    关键字: WebBrowser 数据库 Asynchronous Pluggable Protocols 
    分类 : 开发技巧 
    密级 : 公开 
    (评分: , 回复: 1, 阅读: 128) &raquo;&raquo; 
    实现了下面两个组件: TWebShower 及 TDBWebShower 
    后者可实现WebBrowser直接显示数据库中的html,图片等信息而不用生成临时文件。
    完整的代码及示例可从 http://xianjun.vicp.net/ 下载 WebShower.rar
    下面是组件的全部源代码:
    {***************************************************************
     *
     * Project Name: XJGTest -- WebShower
     * Typist:       XJG([email protected])
     * Purpose:      手工载入数据到WebBrowser
     *               http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/pluggable/pluggable.asp
     * Comment Time: 2003-5-3 11:54:50
     * History:      Create by xjg. 2003-5-3 11:54:50
     *
     ****************************************************************}unit WebShower;interfaceuses
      Classes, Windows, SysUtils, ActiveX, UrlMon;type
      TGetStreamEvent = procedure(const AUrl, AFile: string; const AStream: TMemoryStream;
        var AHandled: Boolean) of object;
      TWebShower = class(TComponent, IInternetProtocol)
      private
        { Private declarations }
        Factory: IClassFactory;
        InternetSession: IInternetSession;
        FNameSpace: string;
        FActive: Boolean;
        FOnGetStream: TGetStreamEvent;
        procedure SetNameSpace(const Value: string);
        procedure SetActive(const Value: Boolean);
      private
        FUrl: string;
        Written, TotalSize: Integer;
        ProtSink: IInternetProtocolSink;
        DataStream: IStream;
        function GetDataStream(var DataStream: IStream): Integer;
      protected
        // IInternetProtocol Methods
        function Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink;
          OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HRESULT; stdcall;
        function Continue(const ProtocolData: TProtocolData): HRESULT; stdcall;
        function Abort(hrReason: HRESULT; dwOptions: DWORD): HRESULT; stdcall;
        function Terminate(dwOptions: DWORD): HRESULT; stdcall;
        function Suspend: HRESULT; stdcall;
        function Resume: HRESULT; stdcall;
        function Read(pv: Pointer; cb: ULONG; out cbRead: ULONG): HRESULT; stdcall;
        function Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD;
          out libNewPosition: ULARGE_INTEGER): HRESULT; stdcall;
        function LockRequest(dwOptions: DWORD): HRESULT; stdcall;
        function UnlockRequest: HRESULT; stdcall;
      protected
        procedure GetWebContent(const AUrl, AFile: string; const AStream: TMemoryStream); virtual;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure Assign(Source: TPersistent); override;
      published
        property Active: Boolean read FActive write SetActive;
        property NameSpace: string read FNameSpace write SetNameSpace;
        property OnGetStream: TGetStreamEvent read FOnGetStream write FOnGetStream;
      end;  TWebShowerClass = class of TWebShower;var
      G_WSClass: TWebShowerClass = TWebShower;implementationuses
      AxCtrls, ComObj, ComServ;const
      IID_NSHandler: TGUID = '{A562A5BC-F3C8-4968-8FA8-996B45223990}';var
      G_WebShower: TWebShower;type
      TNSHandler = class(TComObject, IInternetProtocol)
      private
        FWebShower: TWebShower;
      protected
        // IInternetProtocol Methods
        function Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink;
          OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HRESULT; stdcall;
        function Continue(const ProtocolData: TProtocolData): HRESULT; stdcall;
        function Abort(hrReason: HRESULT; dwOptions: DWORD): HRESULT; stdcall;
        function Terminate(dwOptions: DWORD): HRESULT; stdcall;
        function Suspend: HRESULT; stdcall;
        function Resume: HRESULT; stdcall;
        function Read(pv: Pointer; cb: ULONG; out cbRead: ULONG): HRESULT; stdcall;
        function Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD;
          out libNewPosition: ULARGE_INTEGER): HRESULT; stdcall;
        function LockRequest(dwOptions: DWORD): HRESULT; stdcall;
        function UnlockRequest: HRESULT; stdcall;
      public
        destructor Destroy; override;
        procedure Initialize; override;
      end;  { TNSHandler }function TNSHandler.Start(szUrl: PWideChar; OIProtSink: IInternetProtocolSink;
      OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HRESULT; stdcall;
    begin
      Result := FWebShower.Start(szUrl, OIProtSink, OIBindInfo, grfPI, dwReserved);
    end;function TNSHandler.Read(pv: Pointer; cb: ULONG; out cbRead: ULONG): HRESULT;
    begin
      Result := FWebShower.Read(pv, cb, cbRead);
    end;function TNSHandler.Terminate(dwOptions: DWORD): HRESULT; stdcall;
    begin
      Result := FWebShower.Terminate(dwOptions);
    end;function TNSHandler.LockRequest(dwOptions: DWORD): HRESULT; stdcall;
    begin
      Result := FWebShower.LockRequest(dwOptions);
    end;function TNSHandler.UnlockRequest: HRESULT;
    begin
      Result := FWebShower.UnlockRequest;
    end;function TNSHandler.Continue(const ProtocolData: TProtocolData): HRESULT;
    begin
      Result := FWebShower.Continue(ProtocolData);
    end;function TNSHandler.Abort(hrReason: HRESULT; dwOptions: DWORD): HRESULT; stdcall;
    begin
      Result := FWebShower.Abort(hrReason, dwOptions);
    end;function TNSHandler.Suspend: HRESULT; stdcall;
    begin
      Result := FWebShower.Suspend;
    end;function TNSHandler.Resume: HRESULT; stdcall;
    begin
      Result := FWebShower.Resume;
    end;function TNSHandler.Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD;
      out libNewPosition: ULARGE_INTEGER): HRESULT;
    begin
      Result := FWebShower.Seek(dlibMove, dwOrigin, libNewPosition);
    end;destructor TNSHandler.Destroy;
    begin
      FWebShower.Free;
      inherited;
    end;procedure TNSHandler.Initialize;
    begin
      inherited;
      FWebShower := G_WSClass.Create(nil);
      FWebShower.Assign(G_WebShower);
    end;{ TWebShower }function TWebShower.Abort(hrReason: HRESULT; dwOptions: DWORD): HRESULT;
    begin
      Result := E_NOTIMPL;
    end;procedure TWebShower.Assign(Source: TPersistent);
    begin
      if Source is TWebShower then
      begin
        with TWebShower(Source) do
        begin
          Self.NameSpace := NameSpace;
          Self.OnGetStream := OnGetStream;
        end;
      end
      else
        inherited;
    end;
      

  8.   

    function TWebShower.Continue(const ProtocolData: TProtocolData): HRESULT;
    begin
      Result := S_OK;
    end;constructor TWebShower.Create(AOwner: TComponent);
    begin
      inherited;
      FNameSpace := 'test';
      if G_WebShower = nil then
        G_WebShower := Self;
    end;destructor TWebShower.Destroy;
    begin
      if Active then
        Active := False;
      if G_WebShower = Self then
        G_WebShower := nil;
      inherited;
    end;function TWebShower.GetDataStream(var DataStream: IStream): Integer;
    var
      F: TMemoryStream;
      Dummy: Int64;
      AFileName, AErrorMsg: string;
      AHandled: Boolean;
    begin
      F := TMemoryStream.Create;
      try
        try
          AFileName := Copy(FUrl, Pos(FNameSpace, FUrl) + Length(FNameSpace) + 1, Length(FUrl));
          AHandled := False;
          if Assigned(FOnGetStream) then
            FOnGetStream(FUrl, AFileName, F, AHandled);
          if not AHandled then
            GetWebContent(FUrl, AFileName, F);
        except
          on E: Exception do
          begin
            AErrorMsg := Format('<html><body><font style="font-size:11pt;color:red;bold">%s</font></body></html>',
              [E.Message]);
            F.Size := Length(AErrorMsg);
            Move(Pointer(AErrorMsg)^, F.Memory^, F.Size);
          end;
        end;
        CreateStreamOnHGlobal(0, True, DataStream);
        F.Position := 0;
        TOleStream.Create(DataStream).CopyFrom(F, F.Size);
        DataStream.Seek(0, STREAM_SEEK_SET, Dummy);
        Result := F.Size;
      finally
        F.Free;
      end;
    end;procedure TWebShower.GetWebContent(const AUrl, AFile: string;
      const AStream: TMemoryStream);
    begin
      //
    end;function TWebShower.LockRequest(dwOptions: DWORD): HRESULT;
    begin
      Result := S_OK;
    end;function TWebShower.Read(pv: Pointer; cb: ULONG;
      out cbRead: ULONG): HRESULT;
    begin
      if (totalSize = 0) or (DataStream = nil) then
      begin
        Result := S_FALSE;
        Exit;
      end;
      {Read Data from DataStream to Browser/URLMON }
      DataStream.Read(pv, cb, @cbRead);
      Inc(written, cbRead);
      if (written = totalSize) then
        Result := S_FALSE
      else
        Result := HRESULT(E_PENDING);
    end;function TWebShower.Resume: HRESULT;
    begin
      Result := E_NOTIMPL;
    end;function TWebShower.Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD;
      out libNewPosition: ULARGE_INTEGER): HRESULT;
    begin
      Result := E_NOTIMPL;
    end;procedure TWebShower.SetActive(const Value: Boolean);
    begin
      if FActive <> Value then
      begin
        if Value then
        begin
          CoGetClassObject(IID_NSHandler, CLSCTX_SERVER, nil, IClassFactory, Factory);
          CoInternetGetSession(0, InternetSession, 0);
          InternetSession.RegisterNameSpace(Factory, IID_NSHandler, 'http', 0, nil, 0);
        end
        else
          InternetSession.UnregisterNameSpace(Factory, 'http');
        FActive := Value;
      end;
    end;procedure TWebShower.SetNameSpace(const Value: string);
    begin
      FNameSpace := Value;
    end;function TWebShower.Start(szUrl: PWideChar;
      OIProtSink: IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI,
      dwReserved: DWORD): HRESULT;
    begin
      if Pos(Format('http://%s/', [LowerCase(FNameSpace)]), szUrl) <> 1 then
        Result := INET_E_USE_DEFAULT_PROTOCOLHANDLER
      else
      begin
        FUrl := SzUrl;
        written := 0;
        ProtSink := OIProtSink; //Get interface to Transaction handlers IInternetnetProtocolSink
        { Now get the data and load it in DataStream }
        TotalSize := GetDataStream(DataStream);
        {Inform Transaction handler that all data is ready }
        ProtSink.ReportData(BSCF_FIRSTDATANOTIFICATION or
          BSCF_LASTDATANOTIFICATION or BSCF_DATAFULLYAVAILABLE, TotalSize, TotalSize);
        { -> Here our Read Method is called by transaction handler}
        ProtSink.ReportResult(S_OK, S_OK, nil);
        { Report result to transaction handler. Our Terminate method will be called }
        Result := S_OK;
      end;
    end;function TWebShower.Suspend: HRESULT;
    begin
      Result := E_NOTIMPL;
    end;function TWebShower.Terminate(dwOptions: DWORD): HRESULT;
    begin
      if Assigned(DataStream) then
        DataStream._Release;
      if Assigned(Protsink) then
        Protsink._Release;
      Result := S_OK;
    end;function TWebShower.UnlockRequest: HRESULT;
    begin
      Result := S_OK;
    end;initialization
      TComObjectFactory.Create(ComServer, TNSHandler, IID_NSHandler,
        'NSHandler', 'NSHandler', ciMultiInstance, tmApartment);end.
    {***************************************************************
     *
     * Project Name: XJGTest -- DBWebShower
     * Typist:       XJG([email protected])
     * Purpose:      从数据库中载入数据到WebBrowser
     * Comment Time: 2003-5-3 14:25:17
     * History:      Create by xjg. 2003-5-3 14:25:17
     *
     ****************************************************************}unit DBWebShower;interfaceuses
      SysUtils, Classes, DB, WebShower;type
      TDBWebShower = class(TWebShower)
      private
        FDataSource: TDataSource;
        FFileNameField: string;
        FFileContentField: string;
        procedure SetDataSource(const Value: TDataSource);
        function PropertyIsReady: Boolean;
        procedure GetRecordContent(const AName: string; const AStream: TMemoryStream);
        procedure SetFileContentField(const Value: string);
        procedure SetFileNameField(const Value: string);
      protected
        procedure GetWebContent(const AUrl, AFile: string; const AStream: TMemoryStream); override;
        procedure Notification(AComponent: TComponent; Operation: TOperation); override;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        procedure Assign(Source: TPersistent); override;
      published
        property DataSource: TDataSource read FDataSource write SetDataSource;
        property FileNameField: string read FFileNameField write SetFileNameField;
        property FileContentField: string read FFileContentField write SetFileContentField;
      end;implementation{ TDBWebShower }procedure TDBWebShower.Assign(Source: TPersistent);
    begin
      if Source is TDBWebShower then
      begin
        inherited;
        with TDBWebShower(Source) do
        begin
          Self.DataSource := DataSource;
          Self.FileNameField := FileNameField;
          Self.FileContentField := FileContentField;
        end;
      end
      else
        inherited;
    end;constructor TDBWebShower.Create(AOwner: TComponent);
    begin
      inherited;
      G_WSClass := TDBWebShower;
    end;procedure TDBWebShower.GetRecordContent(const AName: string;
      const AStream: TMemoryStream);
    begin
      with FDataSource.DataSet do
      begin
        if Locate(FileNameField, AName, [loCaseInsensitive]) then
          TBlobField(FieldByName(FileContentField)).SaveToStream(AStream);
      end;
    end;procedure TDBWebShower.GetWebContent(const AUrl, AFile: string;
      const AStream: TMemoryStream);
    begin
      if PropertyIsReady then
        GetRecordContent(AFile, AStream);
    end;procedure TDBWebShower.Notification(AComponent: TComponent;
      Operation: TOperation);
    begin
      inherited;
      if Operation = opRemove then
        if AComponent = FDataSource then
          FDataSource := nil;
    end;function TDBWebShower.PropertyIsReady: Boolean;
    begin
      Result := Assigned(FDataSource) and Assigned(FDataSource.DataSet) and
        FDataSource.DataSet.Active;
    end;procedure TDBWebShower.SetDataSource(const Value: TDataSource);
    begin
      if FDataSource <> Value then
      begin
        FDataSource := Value;
        if Assigned(Value) then
          Value.FreeNotification(Self);
      end;
    end;procedure TDBWebShower.SetFileContentField(const Value: string);
    begin
      FFileContentField := Value;
    end;procedure TDBWebShower.SetFileNameField(const Value: string);
    begin
      FFileNameField := Value;
    end;end.
      

  9.   

    谢谢 iseekcode 的答复。
    我需要的是 在我访问了一个页面 如 www.163.com 后,更改/截取HTML源码后,webbrowser的页面属性 不要变成 blank,还保留 www.163.com 的效果,
    我看了 Asynchronous Pluggable Protocols 实现直接从数据库取得信息显示在WebBrowser中 ,好像也不能指定 我需要的的 url 不变的特征。
    哎,难啊,思路方向错了?
      

  10.   

    说白了,就是需要 在webbrowser 返回的数据里添加一段html代码后,webbrowser的页面属性还保持原来的页面属性不变,不知道我说明白了没?呵呵
      

  11.   

    我明白你的意思,protocols是可以自定义的,也就是说,在形式上,它可以写成http://test/page1.htm之类的,这样,就可以使URL不是BLANK了.
    但http://www.163.com这样的形式,在网络上是解析到一个页面,protocols能不能,我就不清楚了.
      

  12.   

    允许修改内容主要是为了某些实现上的方便。毕竟WebBrowser内部有太多的交互性,对这些交互做重重审核远比修改URL地址更为方便,并且也有利于其它扩充性功能的实现。
      

  13.   

    当打开 http://www.163.com 这样的形式的时候,protocols 是解析到 远程服务器了。此时返回的页面内容也是远程的内容,这又回到开始了,返回的内容又需要更改了……
      

  14.   

    用代理
    你也可以用HTML文档的IPersistMoniker从你自己的IMoniker实现载入数据。你需要模拟一个URL的IMoniker实现。关于URL Moniker,参考http://msdn.microsoft.com/en-us/library/aa741006(VS.85).aspx。