Отслеживание событий мыши на полосе прокрутки - PullRequest
1 голос
/ 09 июля 2020

У меня есть компонент, который является подклассом диалогового окна, и я обрабатываю события мыши внутри компонента. Я пытаюсь добиться изменения видимости полосы прокрутки в зависимости от событий мыши (т.е. полоса прокрутки появляется только тогда, когда мышь наводит указатель мыши на область). Я обрабатываю TrackMouseEvent в сообщении WM_MOUSEMOVE и использую ShowScrollBar для WM_MOUSEHOVER и WM_MOUSELEAVE соответственно.

Он работает, как ожидалось, за исключением случаев, когда мышь наводит курсор на полосу прокрутки. Он постоянно отправляет сообщения WM_MOUSEHOVER и WM_MOUSELEAVE, и вся область мигает, как будто перерисовывается каждую секунду.

Я не уверен в поведении ShowScrollbar вместе с TrackMouseEvent. Может ли кто-нибудь помочь мне найти способ решить эту проблему?

Мое приложение разработано под Win32 без MF C, и вот небольшой фрагмент моего кода.

// gets called once on initialize
void CUDComment::InitScrollRange(int cyWindow)
{
    int nTotal = _getTotalItemHeight();
    int nRangeY = nTotal - cyWindow + _getItemHeight();
    if( nRangeY < 0 ) nRangeY = 0;

    if( m_nVerPos >= nRangeY )
    {
        m_nVerPos = nRangeY;
    }

    DWORD dwScrollState = 0;
    // Hide scrollbar when the content is just one line
    if( nTotal > cyWindow )
    {
        dwScrollState = 1;
        m_bShowScroll = TRUE;
    }
    else
    {
        if( m_bShowScroll )
        {
            dwScrollState = 2;
            m_bShowScroll = FALSE;
        }
    }

    if( dwScrollState > 0 )
    {
        SCROLLINFO siVer;

        siVer.cbSize = sizeof(SCROLLINFO);
        siVer.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
        siVer.nMin = 0;

        if( dwScrollState == 2 )
        {
            siVer.nMax = 0;
            siVer.nPage = 0;
            siVer.nPos = 0;
        }
        else
        {
            siVer.nMax = nRangeY;
            siVer.nPage = min(nRangeY, (int)_getItemHeight());
            siVer.nPos = m_nVerPos;
        }

        SetScrollInfo(m_hWnd, SB_VERT, &siVer, TRUE);
    }
}

void CUDComment::OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    if( !m_bTracking )
    {
        TRACKMOUSEEVENT tme;

        tme.cbSize = sizeof(tme);
        tme.hwndTrack = m_hWnd;
        tme.dwFlags = TME_LEAVE | TME_HOVER;
        tme.dwHoverTime = 500;

        m_bTracking = TrackMouseEvent(&tme);
    }
}

void CUDComment::OnMouseHover(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    ShowScrollBar(m_hWnd, SB_VERT, TRUE);
}

void CUDComment::OnMouseLeave(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    m_bTracking = FALSE;
    ShowScrollBar(m_hWnd, SB_VERT, FALSE);
}

1 Ответ

0 голосов
/ 10 августа 2020

Я попробовал метод Джонатана, но он не совсем сработал, когда я установил триггер TME_LEAVE и TME_NONCLIENT для TrackMouseEvent. Я не мог заставить мышь захватить неклиентскую область. Я просто вычислил размер полосы прокрутки (GetSystemMetrics(SM_CXVSCROLL)) и ее координаты , а затем проигнорировал сообщение о выходе, когда моя мышь наводит курсор на область полосы прокрутки. Таким образом, я в основном создал случай исключения при обработке моего сообщения WM_MOUSELEAVE.

Общие коды выглядят одинаково, за исключением моей функции OnMouseLeave.

void CUDComment::OnMouseLeave(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    POINT ptCurrent;

    GetCursorPos(&ptCurrent);
    ScreenToClient(hWnd, &ptCurrent);

    if (!PtInRect(&m_rcScrollbar, ptCurrent))
    {
        ShowScrollBar(hWnd, SB_VERT, FALSE);
        m_bTracking = FALSE;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...