在UI系统中,当我们在窗口上点击鼠标,移动鼠标,输入数据的时候,是如何来得到那个对应的 UI对象的呢?
在CEGUI中,system中记录了当前活动的rootwindow modalTarget wndWidthMouse的相关窗口。当我们操作键盘的时候,首先会通过getKeyboardTargetWindow去system中得到当前能接受键盘输入的对象,然后调用该对象的onKey***就完成了。getKeyboardTargetWindow是通过查找rootWindow的活动孩子来返回相应对象,这里优先级被设置成了如果d_modalTarget存在的话就直接到了那里去了。window 的getActiveChild函数是通过在d_drawList里面的window执行递归调用getActiveChild,最终找到那个对象(在CEGUI中他先渲染的是d_drawList前面的窗口,所以这里是从尾部开始查找,因为后渲染的窗口会在上层)。对于一个window是否被设置成active,是可以由我们来设置的,不过通常是通过鼠标的点击来设置。当某个window收到onMouseButtonDown消息的时候(injectMouseButtonDown产生)他会调用moveToFront_impl(true)函数,在这个函数中就会调用onActivated(args)函数,args参数中otherWindow值:如果没有父窗口则直接0且调用完onActivated后就返回。如果有parent则调用parent的moveToFront(递归),这样就从顶层的parent起执行下面的内容了:找到该window的活动窗口,没有好说 直接跳过,有的话则则用args.window = activedWnd去调用onActivated,这样就可以完成对点击到的那个对象的所有父对象都调用一次onActivated,并对之前的窗口调用了onDeactivated函数了,且最后调用的才是自己的onActivated。window的onActivated函数就把该窗口的d_active属性设置成true了。前面有个问题是,如何才知道在收到injectMouseButtonDown的时候调用哪个window的onMouseButtonDown呢,那就用到一个函数getTargetWindow,该函数通过鼠标的位置来得到该窗口。
getTargetWindow首先是看window里的d_captureWindow(一个静态变量)是否有值,没有的话就调用activeSheet的getTargetChildAtPosition函数来根据鼠标的positon来找出要找的窗口。如果有值的话就要进一步看该窗口是否分发,是的话就也需要调用它的getTargetChildAtPositon函数来找。他是通过递归调用每个孩子节点的getTargetChildAtPostion来找到想要的那个窗口,而getTargetChildAtPosition函数主要是通过测试相应的孩子是否与鼠标接触,函数为isHist参数为鼠标位置。Window的isHit函数通过将position与自己的hitTestRect进行运算(看点是否在该矩形内)从而得到结果。