91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redrain duilib中事件委托存在的問題

發布時間:2020-07-29 15:57:15 來源:網絡 閱讀:1001 作者:watertoeast 欄目:開發技術

在Redrain duilib中,委托模式將事件發送與事件處理進行了解耦,并預定義了六個事件處理函數的原型,具體如下(對應源文件UIDelegate.h):

typedef bool (*FunVoid)(void* pParam,LPARAM lParam,WPARAM wParam);
typedef bool (*FunTEvent)(TEventUI* pTEventUI,LPARAM lParam,WPARAM wParam);
typedef bool (*FunTNotify)(TNotifyUI* pTNotifyUI,LPARAM lParam,WPARAM wParam);
typedef bool (T::*CMFunVoid)(void* pParam,P lParam,WPARAM wParam);
typedef bool (T::*CMFunTEvent)(TEventUI* pTEventUI,P lParam,WPARAM wParam);
typedef bool (T::*CMFunTNotify)(TNotifyUI* pTNotifyUI,P lParam,WPARAM wParam);


如果利用如下代碼給pCtrl控件的OnNotify添加一個委托函數:

pCtrl->OnNotify += MakeDelegate<CTestWnd, CTestWnd, LPARAM>(this, &CTestWnd::OnTest);

其中CTestWnd::OnTest的定義如下:

bool CTestWnd::OnTest(void *pParam, LPARAM lParam, WPARAM wParam)
{
    return true;
}


分析下起處理流程:

1、用戶操作導致pCtrl發送某個事件;

2、調用CPaintManagerUI::MessageHandler;

3、在CPaintManagerUI::MessageHandler函數內部調用pMsg->pSender->OnNotify(pMsg)。這里的pMsg->pSender是上面所說的pCtrl;

4、OnNotify是pCtrl的一個成員變量,對應的類是CEventSource,該類對()進行了操作符重載,第3步中pMsg->pSender->OnNotify(pMsg),實際調用的是:

	bool CEventSource::operator() (TNotifyUI* pTNotifyUI) 
	{
		for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
			CDelegateBase* pObject = m_aDelegates.GetAt(i);

			if( pObject && !pObject->Invoke(pTNotifyUI,pObject->GetLParam(),pObject->GetWParam()) ) return false;
		}
		return true;
	}

而不是bool CEventSource::operator() (void* param) 和bool CEventSource::operator() (TEventUI* pTEventUI)。因為pMsg的類型是TNotifyUI。

5、第4部中調用Invoke函數如下:

virtual bool Invoke(TNotifyUI* pTNotifyUI,LPARAM lParam = NULL,WPARAM wParam = NULL)
{
    O* pObject = (O*) GetObj();
    if(pObject && GetNotifyTypeName().IsEmpty())
        return (pObject->*m_pCMFunTNotify)(pTNotifyUI,(P)GetLParam(),GetWParam());
    else if(pObject && pTNotifyUI && pTNotifyUI->sType == GetNotifyTypeName())
        return (pObject->*m_pCMFunTNotify)(pTNotifyUI,(P)GetLParam(),GetWParam());
        
    return true;
};

他會調用pObject->*m_pCMFunTNotify。


問題來了,最開始我們調用

pCtrl->OnNotify += MakeDelegate<CTestWnd, CTestWnd, LPARAM>(this, &CTestWnd::OnTest);

MakeDelegate根據傳遞的參數以及CTestWnd::OnTest的函數原型,通過構成函數

CDelegate(O* pObj, CMFunVoid pCMFunVoid,P lParam = NULL,WPARAM wParam = NULL)
 : CDelegateBase(pObj, *(FunVoid*)&pCMFunVoid,(LPARAM)lParam,wParam)
 , m_pCMFunVoid(pCMFunVoid)
 ,m_pCMFunTEvent(NULL)
 ,m_pCMFunTNotify(NULL)
 {}

得到一個委托對象,并添加到pCtrl->OnNotify中。很顯然,構造的這個委托對象的m_pCMFunTNotify為NULL,而在第5步中卻調用了m_pCMFunTNotify,進而導致崩潰。


從上面的分析看,

typedef bool (*FunVoid)(void* pParam,LPARAM lParam,WPARAM wParam);
typedef bool (*FunTEvent)(TEventUI* pTEventUI,LPARAM lParam,WPARAM wParam);
typedef bool (T::*CMFunVoid)(void* pParam,P lParam,WPARAM wParam);
typedef bool (T::*CMFunTEvent)(TEventUI* pTEventUI,P lParam,WPARAM wParam);

是不能使用的,除非對相關代碼進行進一步修改。


另外,對菜單項不要使用委托模式。如果使用了,在菜單項對應的函數中彈出對話框時,會出現異常情況。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安顺市| 陵川县| 靖西县| 黄平县| 鄯善县| 博白县| 东光县| 修水县| 新竹市| 长丰县| 郯城县| 应城市| 蓬溪县| 双柏县| 永年县| 临城县| 鄂伦春自治旗| 永福县| 威信县| 丘北县| 北碚区| 湘乡市| 岳阳市| 淳安县| 抚顺市| 丹棱县| 全南县| 南郑县| 武宁县| 中西区| 章丘市| 萨嘎县| 吴桥县| 永州市| 镇巴县| 巴里| 昆明市| 门头沟区| 甘洛县| 扶风县| 大港区|