WEB开发下面DIV层被OCX控件拦住问题的解决思想,以及结合EXTJS的解决方法

公司开发的WEB程序里面嵌入了一个大控件(ocx)。嵌入控件这种模式自然有它自身的好处,但是却有着一些致命的缺点......我个人认为能不用尽量不用,嵌入控件的WEB程序总觉得点不伦不类。
   牢骚发完了,言归正传。



   控件分为有窗口控件与无窗口控件,无窗口控件很好办

,如flash控件,可以通过添加wmode属性来解决挡住DIV层这个问题,添加的代码如下:
²        代码1-2 解决无窗口控件挡住DIV

<param name="wmode" value="opaque">









这种情况在使用DIV的网页里的测试如下







测试的代码是:

²        代码1-1 测试DIV与OCX控件

<div

   style="position: absolute; left: 120; top: 450; width: 400px; height: 200px; background: red; z-index: 7">

   <object classid="CLSID:4B5BEE59-EDD2-4082-A9F7-D65E1CA20FA7"width="100" height="100">

    </object>

     是第6层

</div>

<div

   style="position: absolute; left: 40; top: 500; width: 400px; height: 100px; background: Blue; z-index: 9">

       这是第7层

</div>

这是第7层

</div>

这种情况在EXTJS下边的测试情况如下图:







     相关测试代码请参考代码1-1

注:如果我们的控件是一个无窗口控件如flash控件,可以通过添加wmode属性来解决挡住DIV层这个问题,添加的代码如下:

²        代码1-2 解决无窗口控件挡住DIV

<param name="wmode" value="opaque">



Ø        如何解决这些问题

值得庆幸的是Html的iframe、frame可以挡住OCX控件——实际上iframe以及frame本身是一个有窗口元素,有窗口元素之间是可以互相遮挡的,而我们的Div又可以与iframe窗口互相遮挡。 现在的问题变成了如何先用iframe挡住OCX窗口再用DIV挡住iframe。



²        Code 2-1 用iframe遮挡OCX控件

<div

   style="position: absolute; left: 120; top: 450; width: 400px; height: 200px; background: red; z-index: 7">

   <object classid="CLSID:4B5BEE59-EDD2-4082-A9F7-D65E1CA20FA7"width="100" height="100">

    </object>

     是第6层

</div>

<div

   style="position: absolute; left: 40; top: 500; width: 400px; height: 100px; background: Blue; z-index: 9">

<iframe id='iframei' src="javascript:false" style="position:absolute; visibility:inherit; top:0px; left:0px;  height:'100%';width:'100%'; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';/">

</iframe>;

       这是第7层

</div>



其中代码”

<iframe id='iframei' src="javascript:false" style="position:absolute; visibility:inherit; top:0px; left:0px;  height:'100%';width:'100%'; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';/"></iframe>;”

就是创建一个与DIV等大的,透明的iframe框架。

实现的效果如下图:







现在我们已经解决了如何用DIV去遮挡OCX这个问题了。接下来我们要做的是如何去改造EXTJS类来让它们也可以挡住OCX控件。



    EXTJS中对控件参用了继承的方法来实现扩展,所以我们只许要实现对恰当的父类进行改造就可以了,这里我们选择Panel类。接下我们将会在panel类里面添加一个等大的,透明的iframe窗口。以后在使用创建的panel控件,以及继承自panel的控件(如:window)都可以实现遮挡住OCX控件了。——继承的优势再一次得到的很好的体现。

由于要修改EXTJS的原码,所以我们使用它的Debug版本。

    我们也许不想所有的panel以及其子孙下边都藏着一个iframe,所以这里我们添加一个属性来控制是否要添加一个iframe。实现如下



Ext.Panel = Ext.extend(Ext.Container, {

    

hasIframe: false,

……

下边我们就在实例化一个panel(或者其子孙)时添加一个iframe吧。

我选择了在panel渲染onRender时加入自己的代码:

onRender : function(ct, position) {

       Ext.Panel.superclass.onRender.call(this, ct, position);

var el = this.el, d = el.dom;

  // el 下边加入我们的iFrame

if (this.hasIframe)

{

var iframeid=this.id+"_iframe"

d.innerHTML+="<iframe id='"+iframeid+"' src=/"javascript:false/" style=/"position:absolute; visibility:inherit; top:0px; left:0px;  height:'100%';width:'100%'; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';/"></iframe>";

}

......

}

OK现在在创建panel或者其子孙时我们只要设置一个属性

hasIframe: true,

就可以实现遮挡住OCX控件的功能了。





问题到了这里仿佛已经得到了完美的解决,但是当我们尝试着去拖动,或者拖曳这些窗口时有时你会发现一起很怪的现向,例如窗口扩大后有一部分无法遮挡住OCX控件,无法在OCX控件上面进行拖曳或者移动。

这是为什么呢?

第一个问题:为什么窗口的一部分可以挡住OCX控件呢?我明明把底层的iframe高度设置成了100%了!设置100%的意思是跟它外层的容器(这里是DIV)大小是一样的。 通过方法把最终的代码alert出来后才发现默认情况下它外层容器的高度是不显示出来的——为什么要这样设计,我也不知道。最简单的方法就是明确地给外层容器设置调度,并在拖曳时再给它们设置高度(panel的大小是不可以改变的,它的子类例如window是可以的)。OK那就再费点现设置一下吧。

第一步在panel实例化时设置一下高度

onRender : function(ct, position) {

          ……

this.el.dom.style.height=this.height; //高度

第二步在 window拖曳时改变一下容器调度

    onResize : function(w, h) {

if(this.hasIframe) {

           this.el.dom.style.height=h; //拖动的时候重新设置了高度



第二个问题: 在拖动层的过程中发现OCX又冒出来了,而且经过OCX时拖动就失败了。这时为什么呢?EXT拖动层时不是把层里面的所有元件(Elements)一起拖动,它只是拖动了最外层的容器,拖动结束后再在新位置上重新绘制元件——多好的设计呀,可惜在这里遇到了问题。那好吧,在拖动时把我们iframe也一起拖动不就OK了?

我们为

startDrag : function() {

     ………

if (this.win.hasIframe)

    {

       var newiframe= Ext.getDom(this.win.id+'_newiframe');

       if (newiframe)

        {

         }

       else

         {

this.proxy.dom.innerHTML+="<iframe id='"+this.win.id+'_newiframe' +"' src=/"javascript:false/" style=/"position:absolute; visibility:inherit; top:0; left:0; width:100%; height:100%; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';/"></iframe>";

                   }

              }

到这里前算是把拖曳问题解决的差不多了,为什么说是差不多了呢?你在实现使用时就会发现有点问题了。

第三个问题:在拖曳经过OCX时就变的无效了

这里不想说原因,说说解决方法吧。没找到更好的解决方法,现在的做法是在拖曳时让底层的iframe临时扩大的全屏,拖完以后再还原回来。

   beforeResize : function() {

              ……

              //拖动之前 把它的底层iframe 扩展到最大

              if (this.hasIframe)

              {

                   var divIframe=Ext.getDom(this.id+'_iframe');

                   divIframe.style.top=-2000;

                    divIframe.style.left=-2000;

                   divIframe.style.height=4000;

                   divIframe.style.width=4000;

              }

            

           },

           handleResize : function(box) {

           ……

              if(this.hasIframe) {

               var divIframe= Ext.getDom(this.id+'_iframe');

               divIframe.style.height='100%';

               divIframe.style.width='100%';

               divIframe.style.top=0;

              divIframe.style.left=0;

               divIframe.style.position='absolute';

               this.el.dom.style.height=box.y; //拖动的时候重新设置了高度

       }

     

          },     



后记:

1)

使用类似方方法我们可以解决 EXJS里面尽乎所有的DIV被OCX拦住的问题——笔都解决了菜单,面板,窗口,消息框

2)

当然我们可以能过 Ext.DomHelper.append方法把我们的代码写的优雅一点...。。

Ext.DomHelper.append(this.el.dom, {
                                        tag : 'iframe',
                                       id: iframeid,
                                        style : "position:absolute; visibility:inherit; top:0; left:0; width:100%; height:100%; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)'",
                                        src : 'javascript:false'
                                      
                                    })

如果在EXTJS实现,只需要加上一句全局开关

  Ext.useShims =true

在创建各种window的时候加上一句全局开关Ext.useShims=true,给window加上属性shim=true(其实不用加,默认就是true)。
好了,只要一句Ext.useShims=true,就可以遮挡ActiveX了,原来这么简单,layer就是加shim,shadow的,这个shim我还以为是两端间隙,没想到是一个遮挡层。

所谓有现成的方法不用,就是傻蛋啊

猜你喜欢

转载自vondon.iteye.com/blog/1679574