Reputation: 3
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;
}
Upvotes: 0
Views: 2614
Reputation: 612914
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);
Upvotes: 0
Reputation: 595896
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);
Upvotes: 1