// The callback function that hooks up and processes messages
// send to the list-box within the combobox
LRESULT CALLBACK 
CTTComboBox::HookListboxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	CListBox* pList = (CListBox*)CWnd::FromHandle(hWnd);
	CTTComboBox* pThisCombo = NULL;
	m_mapCombo.Lookup(hWnd, pThisCombo);

	if (message == WM_MOUSEMOVE)
	{
		WORD xPos, yPos;
		xPos = LOWORD(lParam);
		yPos = HIWORD(lParam);
		CPoint point(xPos, yPos); 
		CRect rcClient;
		::GetClientRect(hWnd, &rcClient);
		if (rcClient.PtInRect(point))
		{// Handle mouse move event that may show a tool-tip window...
			CTTComboBox::HandleListboxMouseMove(pList, wParam, point);
		}
		else
		{// However, the list-box may be captured thus we must know when the mouse cursor
		 // out of the area of the list-box, and send 'WM_MOUSELEAVE' notification.
			::SendMessage(hWnd, WM_MOUSELEAVE, wParam, lParam);
		}

		if (!m_isEnter)
		{// Tracking the mouse event which are hovering and leaving.
			OnTrackMouseEvent(hWnd, TME_HOVER|TME_LEAVE);
			m_isEnter = TRUE;
		}
	}
	else if (message == WM_MOUSELEAVE)
	{
		// When the mouse cursor has been left current window, the original select of the list-box 
		// to reset LB_ERR.
		m_OriginalSel = LB_ERR;
		m_isEnter = FALSE;	
		// The tool-tip window is hidden
		m_tipWnd.ShowWindow(SW_HIDE);
	}
	else if (message == WM_CAPTURECHANGED)
	{	// Ignore the mouse capture changed...
		return 1;
	}
	else if (message == WM_LBUTTONDOWN || 
			 message == WM_LBUTTONDBLCLK)
	{
		WORD xPos, yPos;
		xPos = LOWORD(lParam);
		yPos = HIWORD(lParam);
		CPoint point(xPos, yPos); 
		CRect rcClient;
		::GetClientRect(hWnd, &rcClient);
		if (rcClient.PtInRect(point))
		{
			BOOL bOutside;
			int curSel = pList->ItemFromPoint(point, bOutside);
			if (!bOutside && curSel != LB_ERR)
			{
				for (int i = 0; i < pThisCombo->m_arrDisabledItems.GetSize(); i++)
				{
					if ((UINT)curSel == pThisCombo->m_arrDisabledItems.GetAt(i))
					{
						return TRUE; // Don't process the message
					}
				}
			}
		}
	}
	else if (message == WM_SHOWWINDOW)
	{
		if (wParam == TRUE) // Show up!
		{
			pThisCombo->AlignListBoxWithCombo();
		}
	}

	// Get previous window procedure
	WNDPROC oldListWndProc;
	m_mapWndProc.Lookup(hWnd, oldListWndProc);
	// Call previous window procedure
	return ::CallWindowProc(oldListWndProc, hWnd, message, wParam, lParam);
}