1. 程式人生 > >duilib 滾動條不能拖動 問題處理

duilib 滾動條不能拖動 問題處理

遇到過很多次群裡朋友問:為什麼滾動條不能拖動,點選兩端的按鈕可以滾動,通過滑鼠滾輪也可以滾動,就是滑鼠拖動時拖不動?

這是個提問次數較高的問題。

下面的內容只針對可能的原因中的一個,也是最可能的原因。

因為通過滑鼠拖動滾動條,實際內部用到了定時器,具體有興趣的可以檢視duilib的原始碼。我們的程式在處理時常常也會用到WM_TIMER訊息,通過攔截WM_TIMER訊息來做一些定時器處理,不能拖動的原因很有可能就是我們攔截了定時器訊息之後,不管觸發這個訊息的定時器ID是多少,我們統統都不再繼續傳遞給duilib內部處理了。這樣就造成了無法拖動。

下面我們來簡單看下程式碼流程:

 

LRESULT CMainWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lRes = 0;
	BOOL bHandled = TRUE;

	switch( uMsg ) 
	{
	case WM_CREATE:				lRes = OnCreate(uMsg, wParam, lParam, bHandled);		break;
	case WM_NCHITTEST:			lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled);		break;
	case WM_SYSCOMMAND:			lRes = OnSysCommand(uMsg, wParam, lParam, bHandled);	break;
	case WM_TIMER:				lRes = OnTimer(uMsg, wParam, lParam, bHandled);			break;
	case WM_KEYDOWN:
		{
			if (wParam == VK_ESCAPE)
			{
				Close();
			}
			else
				bHandled = FALSE;
		}
	default:
		bHandled = FALSE;
	}
	if( bHandled ) return lRes;
	if( m_PM.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
	return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}

上面是一個常見的HandleMessage的過程(其他的訊息攔截函式類似),在這裡面我們攔截了WM_TIMER,這樣的話,如果不去設定bHandled的值,那他因為無法走default的處理而自然變為TRUE,這樣在switch的下面,可以看到:if(bHandled) return lRes;當bHandled為true時,本次處理就返回了,並沒有繼續給m_PM.MessageHandler和CWindowWnd::HandleMessage去繼續處理此訊息的機會,相當於WM_TIMER徹底攔截了,那麼其他在你這個HandleMessage之後才有機會處理訊息的地方,都因為無法收到此訊息而再無機會處理了。

 

此時該怎麼辦?

很簡單,針對定時器ID,根據需求攔截就行了。在OnTimer裡面,凡是自己用到的定時器ID,又不想讓它在其他地方也可能被處理,此時在將bHandled置為TRUE,其他時候都置為FALSE就好了。

 

LRESULT CMainWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	if (wParam == TIMER_ID_MYUSE)
	{
		//do
		OutputDebugString(_T("自己用的定時器"));
		bHandled = TRUE;
	}
	else
		bHandled = FALSE;
	return 0;
}

 

另一個原因:滾動條上層可能有其他控制元件,把滾動條蓋住了,上層控制元件不設定背景,介面上直接看不出來,但是會影響滑鼠的事件響應。