MFC CListCtrl есть события мыши? - PullRequest
       26

MFC CListCtrl есть события мыши?

1 голос
/ 13 октября 2011

Кажется, что CListCtrl не отправляет события мыши, если нет двойного щелчка.

Я попытался отправить пропущенное сообщение от обработчиков мыши, чтобы компенсировать это, но это вызывает другое нежелательное поведение. Затем я подумал, что могу послать сообщение в обработчик перемещения мыши, чтобы быть немного более точным, проверив состояние. Однако это ужасные хаки, и, помимо того, что они уродливы, они могут не работать должным образом для каждой возможной реализации производных элементов управления.

Если кто-нибудь знает, почему события «вверх» не принимаются, мне было бы любопытно. Что еще более важно как мне получить CListCtrl с использованием стиля LVS_OWNERDATA для отправки сообщений при наведении мыши, как и любой другой элемент управления?

РЕДАКТИРОВАТЬ: Мне известны LVN_BEGINDRAG, LVN_BEGINRDRAG и т. Д., Однако, чтобы использовать их, мне нужно было бы предотвратить переход WM_LBUTTONDOWN, WM_RBUTTONDOWN и WM_MOUSEMOVE в родительское окно или DragDropManager подключен к CWinAppEx / CMDIFrameWndEx, чтобы я мог сделать специальный одноразовый чехол для этого элемента управления для работы с существующей системой.

Это потому, что у меня есть центральный менеджер перетаскивания, который может уведомлять различные типы элементов управления, когда начинать операцию перетаскивания, когда заканчивать, отменять, изменять анимацию, передавать экранные объекты для источника и цели в пользовательских сообщениях и т. Д. Он должен быть достаточно гибким, чтобы иметь разные способы инициирования, а также различные действия в зависимости от элемента управления, входных данных, типа выбранных или целевых элементов, различных типов элементов управления, включая 3D, или даже различных приложений и т. Д.

Ответы [ 4 ]

2 голосов
/ 25 октября 2011

Для справки вот что у меня работает, но это постыдный хак.Если никто не может придумать ничего лучше, чем это, это действительно печально.

Заголовок:

#pragma once

// CListCtrlEx
class CListCtrlEx : public CListCtrl
{
    DECLARE_DYNAMIC(CListCtrlEx)

public:
    CListCtrlEx();
    virtual ~CListCtrlEx();

    bool IsSelected(int index);
    BOOL SelectDropTarget(int item);

protected:
    DECLARE_MESSAGE_MAP()

    afx_msg void OnStateChanged(NMHDR* pNMHDR, LRESULT* pResult);

    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);

private:
    bool m_lbDown;
    bool m_rbDown;
};

Реализация:

#include "stdafx.h"
#include "ListCtrlEx.h"

// CListCtrlEx
IMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)

CListCtrlEx::CListCtrlEx() : m_lbDown(false), m_rbDown(false)
{
}

CListCtrlEx::~CListCtrlEx()
{
}

BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
    ON_WM_LBUTTONDOWN()
    ON_WM_RBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_RBUTTONUP()
    ON_WM_MOUSEMOVE()

    ON_NOTIFY_REFLECT(LVN_ODSTATECHANGED, &CListCtrlEx::OnStateChanged)
END_MESSAGE_MAP()

// CListCtrlEx message handlers
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_lbDown = true;
    CListCtrl::OnLButtonDown(nFlags, point);
}

void CListCtrlEx::OnRButtonDown(UINT nFlags, CPoint point)
{
    m_rbDown = true;
    CListCtrl::OnRButtonDown(nFlags, point);
}

void CListCtrlEx::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_lbDown = false;
    CListCtrl::OnLButtonUp(nFlags, point);
}

void CListCtrlEx::OnRButtonUp(UINT nFlags, CPoint point)
{
    m_rbDown = false;
    CListCtrl::OnRButtonUp(nFlags, point);
}

void CListCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
{
    if (m_lbDown && ((nFlags & MK_LBUTTON) == 0))
    {
        PostMessage(WM_LBUTTONUP,
            MAKEWPARAM(LOWORD(nFlags), HIWORD(nFlags)),
            MAKELPARAM(point.x, point.y));
    }

    if (m_rbDown && ((nFlags & MK_RBUTTON) == 0))
    {
        PostMessage(WM_RBUTTONUP,
            MAKEWPARAM(LOWORD(nFlags), HIWORD(nFlags)),
            MAKELPARAM(point.x, point.y));
    }

    CListCtrl::OnMouseMove(nFlags, point);
}

bool CListCtrlEx::IsSelected(int index)
{
    return (GetItemState(index, LVIS_SELECTED) & LVIS_SELECTED) != 0;
}

// highlight drop targets sort of like CTreeCtrl
BOOL CListCtrlEx::SelectDropTarget(int item)
{
    static int prevHighlight(-1);
    if (item >= 0 && item < GetItemCount())
    {
        if (item != prevHighlight)
        {
            if (prevHighlight >= 0)
            {
                SetItemState(prevHighlight, 0, LVIS_DROPHILITED); // remove highlight from previous target
                RedrawItems(prevHighlight, prevHighlight);
            }

            prevHighlight = item;
            SetItemState(item, LVIS_DROPHILITED, LVIS_DROPHILITED); // highlight target
            RedrawItems(item, item);

            UpdateWindow();
            return TRUE;
        }
    }
    else
    {
        for (int i(0); i < GetItemCount(); ++i)
            SetItemState(i, 0, LVIS_DROPHILITED); // un-highlight all
        prevHighlight = -1;
    }

    return FALSE;
}

void CListCtrlEx::OnStateChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
// MSDN:
// If a list-view control has the LVS_OWNERDATA style,
// and the user selects a range of items by holding down the SHIFT key and clicking the mouse,
// LVN_ITEMCHANGED notification codes are not sent for each selected or deselected item.
// Instead, you will receive a single LVN_ODSTATECHANGED notification code,
// indicating that a range of items has changed state.

    NMLVODSTATECHANGE* pStateChanged = (NMLVODSTATECHANGE*)pNMHDR;

    // redraw newly selected items
    if (pStateChanged->uNewState == LVIS_SELECTED)
        RedrawItems(pStateChanged->iFrom, pStateChanged->iTo);
}
0 голосов
/ 25 октября 2011

Можете ли вы перейти по следующей ссылке и сообщить нам, если это сработало.

http://support.microsoft.com/kb/147842

Вы можете получить представление оттуда.

0 голосов
/ 25 октября 2011

Вам лучше всего ответит Стефан ....

Однако вы можете перехватить winproc CListCtrl (черт, в MFC вы можете просто создать подкласс CListCtrl, предоставить свой собственный виртуальный WindowProc () и пересылать / перехватывать любые сообщения мыши, которые вам нужны.

Просто используйте стандартный подкласс MFC - механику управления во время выполнения, чтобы «заменить» ваш класс стандартным CListCtrl в любом диалоговом окне или окне, которое вы пожелаете.

Полагаю, вы знаете, как это сделать?

0 голосов
/ 14 октября 2011

Вам не нужны эти события. Система управления предоставляет вам все необходимое.

Из вашего кода я понял, что вы хотите реализовать drag'n'drop элементов в элементе управления списком. Вместо того, чтобы взламывать что-то, что не сработает, и болтать с MS, сделайте это правильно:

Обработка уведомления LVN_BEGINDRAG для запуска операции перетаскивания.

...