简体   繁体   中英

Remove an item from a list-view control

I have a list-view control in my program and I want to remove the selected item. This is done with a button press.

The problem is that no matter what item I select it always deletes the first one...

I think the problem is with the list-view focus being lost. When the button is pressed, the list-view loses focus first, then it tries to remove an item that's not selected anymore, thus it removes the first one.

My question is: Is there any option to make the list-view not to lose its focus?

EDIT:

Here's the code :

stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN    // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>


// TODO: reference additional headers your program requires here

Main.cpp

#include "stdafx.h"


LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);

void CreateList();
void CreateButtons();

enum
{
    IDC_REMOVE_BUTTON = 1000,
    IDC_LIST
};


struct ListBox
{
    HWND hwnd;

    LVCOLUMN lvc;
    LVITEM   lv;

    ListBox(HWND h = 0, LVCOLUMN l = { 0 }, LVITEM lvi = { 0 })
    {
        hwnd = h;
        lvc = l;
        lv = lvi;
    }

};



int selitm = -1;


HINSTANCE g_hInstance;

HWND hwndRemoveButton;

HWND g_hwnd;

ListBox List;





int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
    LPSTR Args, int WinMode)
{
    HWND hWnd;
    MSG Message;
    WNDCLASSEX WinClass = { 0 };
    INITCOMMONCONTROLSEX icc = { 0 };

    g_hInstance = hThisInst;

    icc.dwSize = sizeof(icc);
    icc.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&icc);

    WinClass.cbSize = sizeof(WNDCLASSEX);
    WinClass.hInstance = hThisInst;
    WinClass.lpszClassName = "Test";
    WinClass.lpfnWndProc = WindowFunc;
    WinClass.style = 0;
    WinClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WinClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    WinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WinClass.lpszMenuName = NULL;
    WinClass.cbClsExtra = 0;
    WinClass.cbWndExtra = 0;
    WinClass.hbrBackground = (HBRUSH)COLOR_WINDOW;

    if (!RegisterClassEx(&WinClass)) return 0;

    hWnd = CreateWindow("Test", "Test", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 660, 350,
        NULL, NULL, hThisInst, NULL);

    ShowWindow(hWnd, WinMode);
    UpdateWindow(hWnd);


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


    return Message.wParam;
}


LRESULT CALLBACK WindowFunc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{

    switch (Message)
    {
    case WM_CREATE:

        g_hwnd = hWnd;

        CreateList();
        CreateButtons();

        ListView_InsertItem(List.hwnd, &List.lv);
        ListView_SetCheckState(List.hwnd, List.lv.iItem, true);
        ListView_SetItemText(List.hwnd, List.lv.iItem, 1, "One");
        ListView_SetItemText(List.hwnd, List.lv.iItem, 2, "$1");
        ListView_SetItemText(List.hwnd, List.lv.iItem++, 3, "2010-05-05");


        ListView_InsertItem(List.hwnd, &List.lv);
        ListView_SetCheckState(List.hwnd, List.lv.iItem, true);
        ListView_SetItemText(List.hwnd, List.lv.iItem, 1, "Two");
        ListView_SetItemText(List.hwnd, List.lv.iItem, 2, "$2");
        ListView_SetItemText(List.hwnd, List.lv.iItem++, 3, "2008-05-05");


        ListView_InsertItem(List.hwnd, &List.lv);
        ListView_SetCheckState(List.hwnd, List.lv.iItem, false);
        ListView_SetItemText(List.hwnd, List.lv.iItem, 1, "Three");
        ListView_SetItemText(List.hwnd, List.lv.iItem, 2, "$3");
        ListView_SetItemText(List.hwnd, List.lv.iItem++, 3, "2006-05-05");

        break;


    case WM_COMMAND:

        // The low word of wParam contains the menu ID.
        switch (LOWORD(wParam))
        {

        case IDC_REMOVE_BUTTON:

            selitm = ListView_GetFocusedGroup(List.hwnd);

            ListView_DeleteItem(List.hwnd, selitm);

            break;

        }

        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;


    default:
        return DefWindowProc(hWnd,
            Message,
            wParam,
            lParam);
    }
    return 0;
}


void CreateButtons()
{
    hwndRemoveButton = CreateWindow("Button", "Remove",
        BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
        20, 265, 70, 30,
        g_hwnd, (HMENU)IDC_REMOVE_BUTTON,
        g_hInstance, NULL);
}


void CreateList()
{

    List.hwnd = CreateWindow(WC_LISTVIEW, NULL,
    WS_CHILD | WS_VISIBLE | LVS_REPORT,
    20, 30, 600, 230,
    g_hwnd, (HMENU)IDC_LIST, g_hInstance, NULL);

    ListView_SetExtendedListViewStyle(List.hwnd, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP);

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

    /* Add four columns to the list-view (first column contains check box). */
    List.lvc.iSubItem = 0;

    List.lvc.cx = 50;
    List.lvc.pszText = "Good?";
    ListView_InsertColumn(List.hwnd, List.lvc.iSubItem++, &List.lvc);

    List.lvc.cx = 300;
    List.lvc.pszText = "Name";
    ListView_InsertColumn(List.hwnd, List.lvc.iSubItem++, &List.lvc);

    List.lvc.cx = 150;
    List.lvc.pszText = "Cost";
    ListView_InsertColumn(List.hwnd, List.lvc.iSubItem++, &List.lvc);

    List.lvc.cx = 100;
    List.lvc.pszText = "Watched Since";
    ListView_InsertColumn(List.hwnd, List.lvc.iSubItem++, &List.lvc);

    List.lv.iItem = 0;

}

Your problem has nothing to do with focus. You are using the wrong API to determine the selected item. You are using ListView_GetFocusedGroup() when you need to use ListView_GetNextItem() instead:

selitm = ListView_GetNextItem(List.hwnd, -1, LVNI_SELECTED);
if (selitm != -1)
    ListView_DeleteItem(List.hwnd, selitm);

You are calling ListView_GetFocusedGroup . As documented this:

Gets the group that has the focus

Groups are a somewhat advanced feature of list views. Again, as documented :

Grouping allows a user to arrange lists into groups of items that are visually divided on the page, using a horizontal divider and a group title.

So, that's just not what you want. The API that you need to get the selected item is ListView_GetNextItem . Call it like this:

int selectedIndex = ListView_GetNextItem(List.hwnd, -1, LVNI_ALL | LVNI_SELECTED);
if (selectedIndex != -1)
    ListView_DeleteItem(List.hwnd, selitm);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM