c#内嵌浏览器,c语言写浏览器

  c#内嵌浏览器,c语言写浏览器

  C (1)中嵌入的ie浏览器概述——ie边框和上下文菜单

  最近在项目中使用html作为接口,做了一些关于在wxwidget中嵌入浏览器的细节。mfc基本类似。由于wxwidget已经做了一个包wxie,所以在开发过程中也遇到了很多问题。这里有一个总结:

  Ie边框和上下文菜单

  一般嵌入程序的浏览器页面都会有灰色边框,放在程序里很难看。目前网上比较流行的添加css的方式是:

  正文{

  边框:0;

  }

  但是这种方法的缺点是必须删除页面头部的dtd声明。网上的错误提法类似于下面的链接:http://www.faceker.com/200801/webbrowser-no-border.html说到这里,就把头改成:

  !DOCTYPEHTMLPUBLIC -//W3C//dtdhtml 4.01 transitional//EN

  但是,目前很多页面使用的是较新的css。这个改了之后,页面就不能正常显示了。让网页美工改风格?有点难。

  后来我继续查阅资料,找到了一个更好的方法,就是重载IDocHostUIHandler接口,其中实现了以下几个部分:

  HRESULTSTDMETHODCALLTYPEFrameSite:get hostinfo(DOCHOSTUIINFO * pInfo)

  {

  pInfo-CB size=sizeof(DOCHOSTUIINFO);

  pInfo-dw flags=DOCHOSTUIFLAG _ NO 3d border DOCHOSTUIFLAG _ SCROLL _ NO;

  pInfo-dwDoubleClick=DOCHOSTUIDBLCLK _ DEFAULT;

  returnS _ OK

  }

  DOCHOSTUIFLAG_NO3DBORDER表示不生成边框,DOCHOSTUIFLAG_SCROLL_NO表示不生成滚动条。

  这样就可以完美解决边框和滚动条的问题,不需要依靠页面调整。让设计师爱用什么就用什么。

  另一种是禁用右键菜单。网上也有很多方式,但是用这个界面就可以轻松实现:

  HRESULTSTDMETHODCALLTYPEFrameSite:ShowContextMenu(DWORDdwID,POINT*ppt,

  IUnknown*pcmdtReserved,IDispatch*pdispReserved)

  {

  HRESULTresult=S _ FALSE//DontInterfere

  BOOLhandled=FALSE

  开关(m_contextMenuMode)

  {

  casekDefaultMenuSupport:

  打破;

  casekNoContextMenu:

  result=S _ OK

  已处理=真;

  打破;

  casekTextSelectionOnly:

  如果(dwID!=上下文菜单文本选择)

  {

  result=S _ OK

  已处理=真;

  }

  打破;

  casekAllowAllButViewSource:

  if(dwID==上下文菜单默认值)

  {

  //result=ModifyContextMenu(dwID,ppt,pcmdtReserved);

  已处理=真;

  }

  打破;

  casekCustomMenuSupport:

  if(dwID==上下文菜单默认值)

  {

  //result=CustomContextMenu(ppt,pcmdtReserved);

  已处理=真;

  }

  打破;

  }

  如果(!已处理)

  {

  result=S _ FALSE

  }

  返回结果;

  }

  这里不仅可以控制右键菜单显示,m_contextMenuMode=knocontext菜单,还可以自定义菜单显示,m _ context菜单模式=其他值。因为还不需要自定义菜单,所以这里没有实现。

  如果使用wxie,只需将这个接口添加到FrameSite类中,不关注的接口会直接返回S_FALSE或E _ NOTIMPL

  如果使用sdk或mfc,可以调用IOleObject的SetClientSite方法来设置继承IOleClientSite和IDocHostUIHandler的接口。

  嵌入式ie浏览器概述C(2)-双向通信

  第一步解决边框和上下文菜单的问题,第二步解决C程序和html页面的交互问题。初步的想法是用C更新页面内容来完成c-html通信,通过BeforeNavigate2接口拦截页面的url地址来完成html- c通信。然而,这种方法有以下缺点:

  (1)C-HTML的问题在于导致了C代码的复杂性,需要通过C代码来完成页面的生成。如果修改页面,会产生大量的工作量。虽然使用了模板的方法来解决问题,但是还是比较繁琐,而且在频繁交流的时候会导致页面频繁刷新,产生其他问题。

  (2)HTML-C的问题是不方便传递参数,解析参数,获取返回值,在脚本中调用。

  为了解决这些问题,谷歌之后找到了解决问题的办法:

  (1) c-html,可以通过调用页面脚本方法实现。调用方法如下:

  wxVariantwxIEHtmlWin:ExecScript(const wx string fun,conststd:vector wxString params)

  {

  wxVariantresult(false);

  如果(!m _网络浏览器。Ok())

  返回结果;

  //getdocumentdispatchinterface

  IDispatch * iDisp=NULL

  HRESULThr=m _ webBrowser-get _ Document(iDisp);

  如果(hr!=S_OK)

  返回结果;

  //QueryforDocumentInterface

  wxAutoOleInterface ihtml document 2 HD(IID _ ihtml document 2,iDisp);

  iDisp-Release();

  如果(!高清. Ok())

  返回结果;

  IDispatch * spScript

  HR=HD-get _ Script(sp脚本);

  如果(失败(小时))

  返回结果;

  BSTRbstrMember=wxConvertStringToOle(fun);

  DISPIDdispid=NULL

  HR=sp script-GetIDsOfNames(IID _ NULL,bstrMember,1,

  LOCALE_SYSTEM_DEFAULT,dispid);

  如果(失败(小时))

  {

  返回结果;

  }

  //放置参数

  DISPPARAMSdispparams

  memset( dispparams,0,sizeofdisparams);

  显示参数。货物=参数。size();

  显示参数。rg varg=新变量[显示参数。货物];

  显示参数。cname dargs=0;

  for(inti=0;我参数。size();我)

  {

  CComBSTRbstr=wxConvertStringToOle(params[params。size()-1-I]);

  //回读

  bstr .CopyTo( dispparams.rgvarg[i]).bstr val);

  dispparams.rgvarg[i].VT=VT _ BSTR;

  }

  excepinfo

  memset( excepInfo,0,sizeofexcepInfo);

  变量

  UINTnArgErr=(UINT)-1;//initializetoinvalidarg

  //调用JavaScriptfunction函数

  hr=spScript- Invoke(dispid,IID_NULL,0,

  调度方法,调度参数,

  varRet,excepInfo,narg err);

  删除[]个显示参数。rg varg

  如果(失败(小时))

  {

  返回结果;

  }

  wxconvertoletovant(varRet,result);

  返回结果;

  }

  这个方法实现了C对页面脚本调用,而且参数个数可以任意。比如页面脚本是:

  functionfun(a,b,c)

  {

  }

  C中的调用方法是:

  STD:vector wx字符串参数;

  参数。push _ back( a );

  参数。push _ back( b );

  参数。push _ back( c );

  xxx- ExecScripts(fun ,params);

  还可以获得脚本返回的结果。

  (2) html- c语言语言通过脚本的窗口。外部方法,首先,在前文提到过的IDocHostUIHandler接口中,实现方法:

  HRESULTSTDMETHODCALLTYPEFrameSite:get external(IDispatch * * PP分派)

  {

  IDispatch * pDisp=m _ window-get external();

  中频(pDisp)

  {

  pDisp-AddRef();

  * ppDispatch=pDisp

  }

  退货_确定

  }

  其中m _ window-get外部();

  返回的是自定义的一个自动化接口接口类:

  /*

  * IDispimp .H

  *IDispatch

  *

  *版权所有(c)1995-1999年微软公司,保留所有权利

  */

  #ifndef_IDISPIMP_H_

  #define_IDISPIMP_H_

  #包含oaidl.h

  classCustomFunction

  类cimpidispatch:publicIDispatch

  {

  受保护:

  ULONGm _ cRef

  公共:

  CImpIDispatch(void);

  ~ CImpIDispatch(void);

  stdmethodpqueryinterface(ref iid,void * *);

  STDMETHODIMP _(ULONG)AddRef(void);

  STDMETHODIMP _(ULONG)Release(void);

  //IDispatch

  stdmethodmpgettypeinfocount(UINT * pctinfo);

  stdmethodmpgettypeinfo(/*[in]*/UINTiTInfo,

  /*[in]*/LCIDlcid,

  /*[out]*/ITypeInfo * * ppTInfo);

  STDMETHODIMPGetIDsOfNames(

  /*[in]*/REFIIDriid,

  /*[size _ is][in]*/LPOLESTR * rgszNames,

  /*[in]*/UINTcNames,

  /*[in]*/LCIDlcid,

  /*[size _ is][out]*/DISPID * rg DISPID);

  STDMETHODIMPInvoke(

  /*[in]*/DISPIDdispIdMember,

  /*[in]*/REFIIDriid,

  /*[in]*/LCIDlcid,

  /*[in]*/word标志,

  /*[out][in]*/disp params * pdisp params,

  /*[out]*/VARIANT*pVarResult,

  /*[out]*/excel info * pExcepInfo,

  /*[out]*/UINT * puArgErr);

  voidsetCustomFunction(自定义函数* fun){ m _ fun=fun;}

  私人:

  自定义功能* m _ fun

  };

  #endif//_IDISPIMP_H_主要实现以下两个方法:

  wx string cszCB _ custom function=wxT( CB _ custom function );

  #定义DISPID _ CB _函数3

  stdmethodcimpdispatch:GetIDsOfNames(

  /*[in]*/REFIIDriid,

  /*[size _ is][in]*/OLECHAR * * rgszNames,

  /*[in]*/UINTcNames,

  /*[in]*/LCIDlcid,

  /*[size _ is][out]*/DISPID * rgDispId)

  {

  HRESULThr

  尤因蒂

  //assumesmedegreeofsccess

  hr=NOERROR

  for(I=0;i cNamesi ){

  wxStringcszName=rgszNames[I];

  if(csz name==cszCB _ custom函数)

  {

  rg DISPID[I]=DISPID _ CB _ custom函数;

  }

  否则{

  //oneormorearenunknownsosetthereturncode相应地

  HR=ResultFromScode(DISP _ E _未知名称);

  rg DISPID[I]=DISPID _ UNKNOWN;

  }

  }

  returnhr

  }

  stdmethodmpsimpidispatch:Invoke(

  /*[in]*/DISPIDdispIdMember,

  /*[in]*/REFIID/*riid*/,

  /*[in]*/LCID/*lcid*/,

  /*[in]*/word标志,

  /*[out][in]*/disp params * pdisp params,

  /*[out]*/VARIANT*pVarResult,

  /*[out]*/excel info */* pExcepInfo */,

  /*[out]*/UINT*puArgErr)

  {

  if(DISPID成员==DISPID _ CB _ custom函数)

  {

  if(wFlags DISPATCH_PROPERTYGET)

  {

  if(pVarResult!=空)

  {

  variant init(pVarResult);

  v _ VT(pVarResult)=VT _ BOOL;

  v _ BOOL(pVarResult)=true;

  }

  }

  if(wFlags DISPATCH_METHOD)

  {

  //argumentscomeinreverseorder

  //forsomereason

  如果(!m_fun)返回_ OK

  wxStringarg1,arg2

  if(pDispParams- cArgs 1)返回_ FALSE

  wxStringcmd=pdisp params-rg varg[pdisp params-cArgs-1]。bstrVal

  STD:vector wx string args;

  if(pDispParams- cArgs 1)

  {

  for(inti=pDispParams-cArgs-2;I=0;我-)

  args . push _ back(pdisp params-rg varg[I])。bstr val);

  }

  wxStringre=m_fun- execute(cmd,args);

  if(pVarResult!=空)

  {

  variant init(pVarResult);

  v _ VT(pVarResult)=VT _ BSTR;

  wxVariantwVar(re);

  VariantToMSWVariant(wVar,* pVarResult);

  }

  }

  }

  returnS _ OK

  }

  CustomFunction定义如下:

  #pragmaonce

  #包含wx/wx.h

  #包含矢量

  classCustomFunction

  {

  公共:

  自定义功能(无效)

  {

  }

  virtual~CustomFunction(void)

  {

  }

  virtualwxstring execute(const wxString cmd,const STD:vector wxString args)=0;

  };然后,只要在自己的类中继承这个接口,就可以收到脚本的调用请求。

  在脚本中编写函数:

  窗户。_callFun=function()

  {

  var fun= window . external . CB _ custom function(;

  for(I=0;一.论据长度;我)

  {

  如果(我!=0)

  fun=fun ,;

  fun=fun / arguments[I]/ ;

  }

  fun=fun )’;

  //警戒(好玩);

  return(eval(fun));

  }

  然后写在它被调用的地方:

  _callFun(fun , param1 , param2 ,);

  可以调用C的函数,得到返回值,这样就解决了HTML-C的通讯问题。

  解决了双向沟通之后,页面就不需要刷新了。Web设计人员和C程序员只要分别定义通信接口和实现接口方法,就可以完成接口功能。

  C (3)内嵌ie浏览器总结WXIE的bug解决和最终效果显示

  要解决前两个问题,我心里想:太好了。解决了这两个问题,下一步做界面就容易多了。不像以前,直接用mfc或者第三方库,真的很难做出好看的效果。嗯,编译运行,发现效果不错。然而,当我意识到里面的脚本时,我发现不对劲,没有响应键盘消息。并在页面文本框中按tab键,光标不是运行到下一个文本框,而是丢失。之前也有这种现象,只是我忙着解决之前的问题,没有注意到。一切都结束了。你不能放弃你以前所有的工作吧?这是个大问题。

  Google聊了很久,问了一个朋友,还是不知道为什么。因为wxIE和嵌入式浏览器本身都是比较偏的问题,确实很难找到答案。

  每片乌云都有一线光明。最后在google上找到了类似的问题,得到的答案是这是wxIE的bug,已经在wxPython的项目中解决了。下载编译后,试着运行一下,就搞定了。

  但是要和之前的修改合并,在合并的过程中又发现了一个问题。上一篇文章提到,通过IOleObject接口设置IDocHostUIHandler方法,我就是从这个方法开始的。合并结果后,键盘消息被找到或没有响应。

  时间久了,发现wxIE已经实现了IOleClientSite接口。我自己设置了接口,替换了wxIE的,导致结果异常。经过一番调整,终于正常了。

  自此,C程序与html接口的基础工作告一段落。下面是界面作品和页面脚本。我希望我们不要再遇到任何问题。

  我在这里把这些问题记录下来,以备将来参考,也希望其他朋友不要再遇到我同样的烦恼。

  剪下如下界面图:

  这是一个对话框。完成前面的基础工作后,只要设计师设计好页面,我们几分钟就可以继承到C中,然后再花点时间写界面和脚本。和原来的mfc界面相比,不知道节省了多少时间。这个界面比较简单,但是只要是能设计的,我们都可以集成。

  感兴趣的朋友也不妨试试这个接口方法。

  C (4)嵌入式ie浏览器概述——对话框拖动

  这个问题我之前忘记写了,就是对话框的拖动。就像我上图所示的对话框一样,一般的windows对话框都可以通过拖动标题栏来移动,但是我们这里没有任何原创的标题栏,只有html页面。怎么拖呢?似乎有一些麻烦。

  苦苦思索后,我想到了一个办法,通过前台接口给C发送指令,让C移动窗口,计算页面上的拖动距离。把html页面拖进去相对简单。在C中移动意味着调用MoveWindow。因为之前的通讯方式比较灵活,所以实现这个功能并没有花太多时间。但是运行的时候就不太对了,拖拽过程中拖尾现象太明显了。可能C一直调用MoveWindow重绘,效率很低。这就麻烦了。这时我突然想到,普通对话框被拖动的时候,是一个虚拟的盒子移动到了那里,而原来的对话框并没有移动。放开鼠标后,对话框就移动了。你能做到吗?但windows如何实现这种方法的细节不得而知。怎么做?

  谷歌还是不错的。经过一番搜索,我找到了答案:

  voidTooltipDlg:move win(const STD:vector wx string args)

  {

  if(args.size() 2)返回;

  longx,y;

  参数[0]。托龙(x);

  args[1]。托龙(y);

  intix,iy;

  IX=x;

  iy=y;

  ClientToScreen( ix,iy);

  * SendMessage((HWND)this-GetHWND()、WM_NCMOUSEMOVE、HTCAPTION、MAKELPARAM(ix,iy));

  }

  搞定,简单,真没想到这么简单。运行后发现真的和windows的对话框运动一模一样,太棒了。

  今天全力总结了前几天的工作,收工真的有点累。但是这些东西真的是非常规的方法,很难找到解决问题的方法。先记录到这里吧,免得以后找不到。以前有很多知识是用了又丢的。也希望能给有类似疑问的朋友一点帮助。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: