1

CListCtrlダブルクリックしない限り、マウスアップイベントを送信しないようです。

不足しているメッセージをマウス ダウン ハンドラーから送信して補おうとしましたが、他の望ましくない動作が発生します。次に、マウス移動ハンドラー内でメッセージを送信して、状態を確認することでもう少し正確にできると考えました。ただし、これらは恐ろしいハックであり、醜いことは別として、派生コントロールのすべての可能な実装に対して適切に機能しない可能性があります。

マウスアップイベントが受信されない理由を誰かが知っているなら、私は興味があります. さらに重要なことは、スタイルを使用して、他のすべてのコントロールのようにマウスアップ メッセージを送信するにはどうすればよいですか?CListCtrlLVS_OWNERDATA

編集: 、 などを認識していLVN_BEGINDRAGますがLVN_BEGINRDRAG、これらを使用するにはWM_LBUTTONDOWN、 、WM_RBUTTONDOWN、およびWM_MOUSEMOVEが親ウィンドウに移動したり/にDragDropManagerフックされたりするのを防ぐ必要があるため、このコントロールが既存のシステム。CWinAppExCMDIFrameWndEx

これは、ドラッグ操作を開始するタイミング、アニメーションを終了するタイミング、キャンセルするタイミング、アニメーションを変更するタイミング、カスタム メッセージでソースとターゲットの表示オブジェクトを渡すタイミングなど、さまざまなタイプのコントロールに通知できる中央のドラッグ アンド ドロップ マネージャーがあるためです。コントロール、入力、選択または対象となるアイテムの種類、3D を含むさまざまなコントロールの種類、さらにはさまざまなアプリケーションなどに応じて、さまざまな開始方法やさまざまなアクションを実行できる柔軟性を備えている必要があります。

4

4 に答える 4

2

参考までに、これは私が持っているものですが、それは恥ずべきハックです。これよりも優れたものを誰も思いつかないとしたら、それは本当に悲しいことです。

ヘッダ:

#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);
}
于 2011-10-25T15:25:32.923 に答える
0

それらのイベントは必要ありません。コントロールは、必要なものすべてを提供します。

あなたのコードから、リスト コントロールに項目のドラッグ アンド ドロップを実装したいと考えています。とにかくうまくいかないものと悪口のMSを一緒にハッキングする代わりに、代わりに正しい方法でそれを行います:

LVN_BEGINDRAG通知を処理して、ドラッグ操作を開始します。

于 2011-10-14T15:55:15.600 に答える
-1

ステファンの答えが最も役立つかもしれません....

ただし、CListCtrl の winproc をフックすることはできます (地獄、MFC では、CListCtrl をサブクラス化し、独自の仮想 WindowProc() を提供して、必要なマウス メッセージを転送/傍受することができます。

実行時に標準の MFC サブクラスのコントロール メカニズムを使用して、任意のダイアログまたはウィンドウで標準の CListCtrl のクラスを「置換」します。

その方法を知っていると思いますか?

于 2011-10-25T15:28:34.610 に答える