Listview 在我的子类过程中未收到WM_LBUTTONUP

Listview 在我的子类过程中未收到WM_LBUTTONUP,listview,winapi,mouseevent,Listview,Winapi,Mouseevent,我试图捕捉用户在单击listview后释放鼠标左键的事件 在下面的代码中,我需要双击以获得beep。所需的行为是在用户释放鼠标左键时立即收到嘟嘟声 代码比文字更能说明问题,下面是一个最小的例子: #include <windows.h> #include <windowsx.h> // various listview macros etc #include <CommCtrl.h> #include <stdio.h> // swp

我试图捕捉用户在单击listview后释放鼠标左键的事件

在下面的代码中,我需要双击以获得beep。所需的行为是在用户释放鼠标左键时立即收到嘟嘟声

代码比文字更能说明问题,下面是一个最小的例子:

#include <windows.h>
#include <windowsx.h>   // various listview macros etc
#include <CommCtrl.h>
#include <stdio.h>      // swprintf_s()

// enable Visual Styles
#pragma comment( linker, "/manifestdependency:\"type='win32' \
                         name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
                         processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
                         language='*'\"")

// link with Common Controls library
#pragma comment( lib, "comctl32.lib") 

//global variables
HINSTANCE hInst;

// subclass procedure for listview -> implements drag and drop
LRESULT CALLBACK Example(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam,
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (message)
    {
    case WM_LBUTTONUP:    
    {
        MessageBeep(0);  // so I know  it is received
    }
        return DefSubclassProc(hwnd, message, wParam, lParam);

    case WM_NCDESTROY:
        ::RemoveWindowSubclass(hwnd, Example, 0);
        return DefSubclassProc(hwnd, message, wParam, lParam);

    }
    return ::DefSubclassProc(hwnd, message, wParam, lParam);
}

// main window procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
    {
        //================ create an example listview
        RECT rec = { 0 };
        GetClientRect(hwnd, &rec);

        HWND hwndLV = CreateWindowEx(0, WC_LISTVIEW,
            L"", WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | WS_CLIPCHILDREN, 
            50, 50, 250, 200, hwnd, (HMENU)2000, hInst, 0);

        // set extended listview styles
        ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);

        // add some columns
        LVCOLUMN lvc = { 0 };

        lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
        lvc.fmt = LVCFMT_LEFT;

        for (long nIndex = 0; nIndex < 5; nIndex++)
        {
            wchar_t txt[50];
            swprintf_s(txt, 50, L"Column %d", nIndex);

            lvc.iSubItem = nIndex;
            lvc.cx = 60;
            lvc.pszText = txt;

            ListView_InsertColumn(hwndLV, nIndex, &lvc);
        }

        // add some items
        LVITEM lvi;

        lvi.mask = LVIF_TEXT;

        for (lvi.iItem = 0; lvi.iItem < 10000; lvi.iItem++)
        {
            for (long nIndex = 0; nIndex < 5; nIndex++)
            {
                wchar_t txt[50];
                swprintf_s(txt, 50, L"Item %d%d", lvi.iItem, nIndex);

                lvi.iSubItem = nIndex;
                lvi.pszText = txt;
                if (!nIndex)  // item 
                    SendDlgItemMessage(hwnd, 2000, LVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&lvi));
                else            // sub-item
                    SendDlgItemMessage(hwnd, 2000, LVM_SETITEM, 0, reinterpret_cast<LPARAM>(&lvi));
            }
        }

        //============================ subclass it
        SetWindowSubclass(hwndLV, Example, 0, 0);
    }
        return 0L;

    case WM_CLOSE:
        ::DestroyWindow(hwnd);
        return 0L;
    case WM_DESTROY:
    {
        ::PostQuitMessage(0);
    }
        return 0L;
    default:
        return ::DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// WinMain

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
    int nCmdShow)
{
    // store hInstance in global variable for later use
    hInst = hInstance;

    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    // register main window class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = L"Main_Window";
    wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION |
            MB_OK);

        return 0;
    }

    // initialize common controls
    INITCOMMONCONTROLSEX iccex;
    iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    iccex.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&iccex);

    // create main window
    hwnd = CreateWindowEx(0, L"Main_Window", L"Listview Drag and Drop",
        WS_OVERLAPPEDWINDOW,
        50, 50, 400, 400, NULL, NULL, hInstance, 0);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}
#包括
#包括//各种listview宏等
#包括
#包括//swprintf_s()
//启用视觉样式
#pragma注释(链接器,“/manifestdependency:\”类型='win32'\
name='Microsoft.Windows.Common控件'version='6.0.0.0'\
processorArchitecture='*'publicKeyToken='6595b64144ccf1df'\
语言=“*”\“”)
//与公共控件库的链接
#pragma注释(lib,“comctl32.lib”)
//全局变量
HINSTANCE hInst;
//listview->实现拖放的子类过程
LRESULT回调示例(HWND-HWND、UINT消息、WPARAM-WPARAM、LPARAM-LPARAM、,
UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
{
开关(信息)
{
案例WM_LBUTTONUP:
{
MessageBeep(0);//所以我知道它已收到
}
返回defsublassproc(hwnd、message、wParam、lParam);
案例WM\NCU:
::RemoveWindowsSubClass(hwnd,示例,0);
返回defsublassproc(hwnd、message、wParam、lParam);
}
return::defsublassproc(hwnd、message、wParam、lParam);
}
//主窗口程序
LRESULT回调WndProc(HWND HWND,UINT msg,WPARAM WPARAM,LPARAM LPARAM)
{
开关(msg)
{
案例WM_创建:
{
//===================创建示例listview
RECT rec={0};
GetClientRect(hwnd和rec);
HWND hwndLV=CreateWindowEx(0,WC_列表视图,
L'',WS|U儿童| WS|U可见| WS|U边界| LVS|U报告| WS|U儿童,
50,50,250,200,hwnd,(汉努)2000,hInst,0);
//设置扩展的listview样式
ListView_SetExtendedListViewStyle(hwndLV、LVS_EX_FULLROWSELECT、LVS_EX_GRIDLINES、LVS_EX_DOUBLEBUFFER);
//添加一些列
lvc列lvc={0};
lvc.mask=LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_子项;
lvc.fmt=LVCFMT_左;
对于(长nIndex=0;nIndex<5;nIndex++)
{
wchar_t txt[50];
swprintf_s(文本,50,L“第%d列”,索引为nIndex);
lvc.iSubItem=nIndex;
lvc.cx=60;
lvc.pszText=txt;
ListView_InsertColumn(hwndLV、nIndex和lvc);
}
//添加一些项目
lvi项目;
lvi.mask=LVIF_文本;
对于(lvi.iItem=0;lvi.iItem<10000;lvi.iItem++)
{
对于(长nIndex=0;nIndex<5;nIndex++)
{
wchar_t txt[50];
swprintf_s(txt,50,L“项目%d%d”,lvi.iItem,nIndex);
lvi.iSubItem=nIndex;
lvi.pszText=txt;
如果(!nIndex)//项
SendDlgItemMessage(hwnd,2000年,LVM_插入项,0,重新解释(和lvi));
其他//分项
SendDlgItemMessage(hwnd,2000,LVM_SETITEM,0,重新解释(和lvi));
}
}
//==============================================为其子类
SetWindowsSubClass(hwndLV,示例,0,0);
}
返回0升;
案例WM_结束:
::销毁窗口(hwnd);
返回0升;
案例WM_销毁:
{
::PostQuitMessage(0);
}
返回0升;
违约:
return::DefWindowProc(hwnd、msg、wParam、lParam);
}
返回0;
}
//温曼
int WINAPI WinMain(HINSTANCE HINSTANCE、HINSTANCE HPPreInstance、LPSTR lpCmdLine、,
国际展览(nCmdShow)
{
//将hInstance存储在全局变量中供以后使用
hInst=hInstance;
WNDCLASSEX wc;
HWND-HWND;
味精;
//注册主窗口类
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=0;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInst;
wc.hIcon=加载图标(hInstance,IDI_应用程序);
wc.hCursor=LoadCursor(空,IDC_箭头);
wc.hbrBackground=GetSysColorBrush(颜色窗口);
wc.lpszMenuName=NULL;
wc.lpszClassName=L“主窗口”;
wc.hIconSm=加载图标(hInstance,IDI_应用程序);
如果(!RegisterClassEx(&wc))
{
MessageBox(NULL,L“窗口注册失败!”,L“错误!”,MB_图标连接|
MB_OK);
返回0;
}
//初始化公共控件
INITCOMMONCONTROLSEX iccex;
iccex.dwSize=sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC=ICC_列表视图_类;
InitCommonControlsEx(&iccex);
//创建主窗口
hwnd=CreateWindowEx(0,L“主窗口”,L“列表视图拖放”,
WS_重叠窗口,
50,50,400,400,NULL,NULL,hInstance,0);
显示窗口(hwnd、nCmdShow);
更新窗口(hwnd);
while(GetMessage(&Msg,NULL,0,0)>0)
{
翻译信息(&Msg);
发送消息(&Msg);
}
返回Msg.wParam;
}
单击listview中的一行后,不会发出蜂鸣音。我做错了什么?

根据本次讨论:

:

…我正在对列表视图进行细分,以查看WM_LBUTTONDOWN和 WM_LBUTTONUP。。。我的问题是:我看到了WM_LBUTTONDOWN,但从来没有看到WM_LBUTTONUP。Spy++告诉我这两条消息都将发送到控件。我对控件如何“吃掉”WM_LBUTTONUP感到困惑

问题在于,列表控件本身设计了一些 相当复杂的点击处理。当列表控件的默认值为 windowproc接收WM_LBUTTONDOWN或WM_RBUTTONDOWN消息,它进入 它自己的模式消息循环,持续到相应的 接收到WM_LBUTTONUP或WM_RBUTTONUP消息。是的,基本上,这 模态消息循环吃掉WM_LBUTTONUP/WM_RBUTTONUP消息;你的窗户 代码永远不会变