【cocos2d-x3.2遊戲開發】 模態對話方塊攔截所有事件,cocos2d-x3.2模態
開發基礎:Cocos2dx 3.2
開發目標:1.實現模態對話方塊,無論彈出多少層都可以攔截事件。 2.ScrollView上有按鈕,可以點擊按鈕滑動,響應事件並且不影響模態對話方塊的事件攔截。
實現方法:
1.Cocos2dx 2版本中,我們會設定DlgLayer事件的優先順序為-128,這樣會攔截底層的按鈕事件(-128),但是問題是會攔截當前層的按鈕事件(-128),需要將DlgLayer上的點擊事件手動傳入對話方塊上的按鈕處理。
3.0版本中已經不再使用了,這種方法有很大的局限性,尤其在介面比較多,比較複雜的情況下,傳遞事件是一種比較挫的做法。直接排除。
2.Cocos2dx 3.X版本中,因為改變了事件的規則,幾乎所有的控制項的事件處理都按SceneGraphPriority走的,甚至連Cocos2dx 2.X版本的Menu的-128也更改為0了。
做法: 直接彈出一個DlgLayer(CCColorLayer), 封裝一個事件吞噬(onTouchBegan, onTouchEnded...), 事件優先順序為addEventListenerWithSceneGraphPriority,即0
因為所有層的攔截事件優先順序為0,就會先處理最上方的事件,即彈出的對話方塊事件。
特殊情況:
彈出的對話方塊上有ScrollView,ScrollView上有按鈕,最常見的問題就是
1.點擊按鈕能觸發事件,但是點擊按鈕無法滑動ScrollView。
解決辦法:把按鈕優先順序設定為1(當前ScrollView的優先順序為0),這樣就能點著按鈕滑動了。
但是產生新問題,按鈕能滑動,卻不能點擊了,因為DlgLayer的優先順序為0,會攔截掉按鈕的事件。
2.有一個特殊的API,setSwallowTouches,在為一個控制項封裝點擊事件的時候,可以將setSwallowTouches(false)。
這就意味著按鈕能夠響應點擊事件,但是因為沒有吞噬事件,就可以把按鈕的事件傳給ScrollView,ScrollView也可以滑動。
DlgLayer 優先順序 0
ScrollView 優先順序 0
Button 優先順序 0
根據ZOrder的順序,先觸發Button,然後是ScrollView,最後是DlgLayer
3. 3.0版本不建議修改priority,因為你無法得知需要彈出多少層對話方塊,就無法確定每個對話方塊的priority
eventdispatcher事件分發規則
添加監聽的方法addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority
1.SceneGraphPriority
和Node節點綁定的所有事件的優先順序為0,
添加監聽器後,事件監聽列表內部的排序為 "<0, scene graph (0 priority), >0"
2.FixedPriority
用來自己定製優先順序,一般設定"<0 或 >0"
3. 響應事件的優先順序,數值越小,越先響應,-1 0 1這個順序
內部事件處理順序:
1.優先順序為負數的事件
2.優先順序為0(scene graph)的事件,相同的優先順序會根據Node的z順序高的(繪製於頂部的)節點將優於z順序低的節點。這將保證了諸如觸碰事件的自頂向下傳播。
3.優先順序為整數的事件
最後附帶一個lua版封裝的TouchableSprite
一個可點擊的圖片,可以在ScrollView上點擊滑動,響應事件。
--[[ 可點擊的圖片,可以設定響應的優先順序。 比如ScrollView上的按鈕,可以用TouchableSprite實現。將TouchableSprite設定為不吞噬訊息即可。 ~~~lua -- 點擊點擊事件 local function equip_touch_began_listener(sender, touch, event) end -- 點擊結束事件 local function equip_touch_ended_listener(sender, touch, event) if scroll_view:isTouchMoved() then return end -- 可以添加容錯點擊,如5個像素內。 local start_pt = touch:getStartLocation() local end_pt = touch:getLocation() if checkint(start_pt.x) == checkint(end_pt.x) and checkint(start_pt.y) == checkint(end_pt.y) then print(sender.id_) print("Ready to equip......") end end -- 添加到ScrollView上可點擊的圖片 local sp = TouchableSprite.new("data/equip.png", equip_touch_began_listener, equip_touch_ended_listener, false) sp.id_ = 9999 scroll_view:addChild(sp) ~~~lua]]local TouchableSprite = class("TouchableSprite", function(pic_path) return display.newSprite(pic_path) end)TouchableSprite.__index = TouchableSpriteTouchableSprite.listener_ = nilTouchableSprite.swallowTouch_ = trueTouchableSprite.fixedPriority_ = 0TouchableSprite.useNodePriority_ = falseTouchableSprite.removeListenerOnTouchEnded_ = falseTouchableSprite.touch_began_listener_ = nilTouchableSprite.touch_ended_listener_ = nil--[[構造一個可響應點擊事件的TouchableSprite。~~~lua -- 監聽器有三個參數,第一個參數是自己 local function touch_began_listener(sender, touch, event) end local function touch_ended_listener(sender, touch, event) local start_pt = touch:getStartLocation() local end_pt = touch:getLocation() if checkint(start_pt.x) == checkint(end_pt.x) and checkint(start_pt.y) == checkint(end_pt.y) then print(sender.id_) print("Ready to equip......") end end local sp = TouchableSprite.new("data/equip.png", equip_touch_began_listener, equip_touch_ended_listener) sp:setTexture("data/equip1.png") sp:setPriority(1) parent:addChild(sp) ~~~lua@param string pic_path 傳入圖片路徑.可為空白,後通過:setTexture("pic_path")重新設定@param touch_began_listener 點擊開始事件的監聽器。為空白時不響應。 監聽器有三個參數,第一個參數是可點擊圖片自己@param touch_ended_listener 點擊結束時事件監聽器。為空白時不響應。 監聽器有三個參數,第一個參數是可點擊圖片自己@param swallow_touch 是否吞噬事件 true 事件不再向下傳遞 false 響應完事件後,繼續向下傳遞]]function TouchableSprite:ctor(pic_path, touch_began_listener, touch_ended_listener, swallow_touch) self.touch_began_listener_ = touch_began_listener self.touch_ended_listener_ = touch_ended_listener self.swallowTouch_ = swallow_touch local function onNodeEvent(event) if event == "enter" then self:onEnter() elseif event == "exit" then self:onExit() end end self:registerScriptHandler(onNodeEvent)endfunction TouchableSprite:setTouchBeganListener(touch_began_listener) self.touch_began_listener_ = touch_began_listenerendfunction TouchableSprite:setTouchEndedListener(touch_ended_listener) self.touch_ended_listener_ = touch_ended_listenerendfunction TouchableSprite:onEnter() local eventDispatcher = self:getEventDispatcher() local function onTouchBegan(touch, event) local locationInNode = self:convertToNodeSpace(touch:getLocation()) local s = self:getContentSize() local rect = cc.rect(0, 0, s.width, s.height) if cc.rectContainsPoint(rect, locationInNode) then if self.touch_began_listener_ then self:touch_began_listener_(self,touch, event) end return true end return false end local function onTouchMoved(touch, event) end local function onTouchEnded(touch, event) print("onTouchEnded.......") if self.touch_ended_listener_ then self:touch_ended_listener_(self, touch, event) end if self.removeListenerOnTouchEnded_ then eventDispatcher:removeEventListener(self.listener_) end end local listener = cc.EventListenerTouchOneByOne:create() self.listener_ = listener listener:setSwallowTouches(self.swallowTouch_) listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) if 0 == self.fixedPriority_ then eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) else eventDispatcher:addEventListenerWithFixedPriority(listener,self.fixedPriority_) endendfunction TouchableSprite:setSwalllowTouch(swallow) self.swallowTouch_ = swallowendfunction TouchableSprite:onExit() local eventDispatcher = self:getEventDispatcher() eventDispatcher:removeEventListener(self.listener_)endfunction TouchableSprite:setPriority(fixedPriority) self.fixedPriority_ = fixedPriority self.useNodePriority_ = falseendfunction TouchableSprite:removeListenerOnTouchEnded(toRemove) self.removeListenerOnTouchEnded_ = toRemoveendfunction TouchableSprite:setPriorityWithNode(useNodePriority) self.fixedPriority_ = 0 self.useNodePriority_ = useNodePriorityendreturn TouchableSprite
Cocos2dx 2.x版本的模態對話方塊:【COCOS2DX-遊戲開發之二】 模態對話方塊
MFC中響應非模態對話方塊的滑鼠移動事件的運行異常
應該是你對話方塊在初始化的時候你就捕獲其滑鼠資訊,對其進行操作導致其發生斷言警告。
你應該在對話方塊初始化完成後再做你的操作。另外因你是響應滑鼠資訊,那你的對話方塊肯定是可見狀態的,所以就用下面這條語句進行判斷。
if (::IsWindowVisible(m_hWnd))
{
//你的處理代碼。
}
else
{
//滑鼠預設響應資訊。
}
UG二次開發中可以否調用非模態的MFC對話方塊?
這個問題也討論過很多次了,以前的貼有很多的啊 先建立對話方塊,程式中直接調用下面的子程式即可 void DisplayDialog() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); MyDialog * dlg=new MyDialog(); if(dlg!=NULL) { BOOL ret=dlg->Create(IDD_DIALOG1); if(!ret) AfxMessageBox("Failed create modaless dialog!"); dlg->ShowWindow(SW_SHOW); } }