鸟食轩

 Microsoft .NET[C#] MVP 2003
随笔 - 424, 文章 - 231, 评论 - 5394, 引用 - 344
数据加载中……

用createEventObject来模拟事件参数

    原来在程序中模拟事件触发的时候,我写过一篇文章叫"在什么时候才会用到fireEvent方法呢?"。文章中说了我们怎么样来使用模拟事件的详细方法和步骤,不过当时忽略了fireEvent的一个Optional的参数oEventObject,它是做什么的呢?

    由于一次对事件的更精确的触发控制,才知道了为什么会需要createEventObject这个方法。原来觉得可以fireEvent,对于控制事件触发已经非常的方便和强大了,可是一次BT的控制,发现居然还必须自己控制事件参数event的值。我们知道当事件触发时,正常的window.event对象的众多属性基本都是readonly的。而使用fireEvent触发事件后,event对象的很多属性都是默认值(或空值),那么我们怎么修改它成为我们期望的值呢?这时createEventObject方法就派上用场了。

    调用document对象的createEventObject方法,我们会得到一个event的对象实例。这个是当然了,不过这个我们创建的event实例的属性大都是可写的,这样一来我们就完全可以定制一个具有我们希望属性参数的event对象。在使用它来作为fireEvent方法的参数,事件触发后的控制就完完全全的在我们自己的掌握之中了。看下面这个我整理并简化后,使用createEventObject方法配合fireEvent的事例:
<div id="divEvent" oncontextmenu="return false;" style="border: dotted 1px blue;
    width: 170px; height: 100px; padding: 10px"
 onmousedown="ShowContextMenu(this)">
</div>
Right click the above rectangle.
<script></script>
<script Language="javascript"></script>
<br />
<br />
<button onclick="RunEvent()">
    Run Event
</button>
<button onclick="FireEvent()">
    Fire Event
</button>
<br />
<br />
<button onclick="document.location.href=document.location.href">
    Refresh
</button>

    当我们在蓝色的区域内点击鼠标右键时,通过调用ShowContextMenu方法,会出现一个context menu。并且ShowContextMenu的逻辑依赖于event对象的属性值,当我么使用"Run Event"这个按钮时,由于event对象里是默认值,ShowContextMenu方法不能正确的执行。使用FireEvent方法,我们通过createEventObject调用,创建一个event对象,并赋与适当的属性值,我们就可以完全使用代码模拟出鼠标或键盘所触发的事件动作。

    当然,fireEvent和createEventObject方法都是IE实现的DOM提供的独家方法

posted on 2005-06-06 21:53 birdshome 阅读(3373) 评论(6)  编辑 收藏 所属分类: Jscript&Dhtml开发

评论

#1楼    回复  引用    

divEvent加上position:relative/absolute都有问题,该怎么办?
2005-06-07 09:28 | Derek [未注册用户]

#2楼 [楼主]   回复  引用  查看    

@Derek
为什么要给divEvent加上position:relative/absolute?! 出的什么问题呀?
2005-06-07 09:39 | birdshome      

#3楼    回复  引用    

如果将这样的定制右键菜单用在页面上,divEvent很可能需要定位,如果给divEvent加上了style="position:absolute"或relative来定位的话,弹出菜单的位置就不对了?我的环境:2000sp4+ie6.01(6.0.2800.1106),你试试看?
2005-06-08 08:17 | Derek [未注册用户]

#4楼    回复  引用  查看    

@Derek
谢谢你的回府,不过这个示例是我为了说明createEventObject方法的用法和用途而杜撰的,没有考虑别的问题,因为我不可能把我使用createEventObject的整个方案搬上来讲我用到了createEventObject,觉得它挺好的。那我就没法讲了:}
2005-06-08 11:20 | birdshome      

#5楼    回复  引用    

好用好用,谢谢。

我原来尝试用
VARIANT var;
var.vt = VT_DISPATCH;
pElemFrame->get_onmousedown(&var);
CComPtr<IDispatch> mousedown = var.pdispVal;
HRESULT hrtest = mousedown->Invoke(0, IID_NULL, 0, DISPATCH_METHOD, 0, 0, 0, 0);
出现INVALID_ARG,不知道为什么?
自己估计是DISPID的问题。

现在用你的方法解决了
CComPtr<IHTMLDocument4> pDoc4;
hr = pDoc3->QueryInterface(IID_IHTMLDocument4,(void**)&pDoc4);
if(hr==S_OK)
{
CComPtr<IHTMLEventObj> pEvent;
pDoc4->createEventObject(NULL, &pEvent);
CComQIPtr<IHTMLEventObj2, &IHTMLEventObj2> pEvent2(pEvent);
CComBSTR eventName = "onmousedown";
pEvent2->put_type(eventName);
pEvent2->put_button(2);
long x1, y1, x2, y2;
pElemFrame->get_offsetLeft(&x1);
pElemFrame->get_offsetTop(&y1);
pElemFrame->get_offsetWidth(&x2);
pElemFrame->get_offsetHeight(&y2);
pEvent2->put_offsetX(x1+(x2>>1));
pEvent2->put_offsetY(y1+(y2>>1));
CComQIPtr<IHTMLElement3, &IID_IHTMLElement3> pElemFrame3(pElemFrame);
VARIANT_BOOL result;
CComVariant vEvent = pEvent;
pElemFrame3->fireEvent(eventName, &vEvent, &result);
}

#6楼    回复  引用    

你有什么方法可以解决Firefox下的fireEvent问题么。
2007-05-07 15:31 | imt [未注册用户]