win32: allow multiselect in cheat dialog, handle delete and selection

(#916)
This commit is contained in:
OV2 2024-05-08 16:53:11 +02:00
parent add607c38f
commit be53955553
2 changed files with 91 additions and 43 deletions

View File

@ -241,7 +241,7 @@ STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_M
CAPTION "Cheat Entry and Editor" CAPTION "Cheat Entry and Editor"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
CONTROL "List1",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,6,6,294,120,WS_EX_CLIENTEDGE CONTROL "List1",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,6,6,294,120,WS_EX_CLIENTEDGE
DEFPUSHBUTTON "&Add",IDC_ADD_CHEAT,306,6,66,14,WS_DISABLED DEFPUSHBUTTON "&Add",IDC_ADD_CHEAT,306,6,66,14,WS_DISABLED
PUSHBUTTON "&Delete",IDC_DELETE_CHEAT,306,60,66,14,WS_DISABLED PUSHBUTTON "&Delete",IDC_DELETE_CHEAT,306,60,66,14,WS_DISABLED
PUSHBUTTON "&Update",IDC_UPDATE_CHEAT,306,24,66,14,WS_DISABLED PUSHBUTTON "&Update",IDC_UPDATE_CHEAT,306,24,66,14,WS_DISABLED

View File

@ -8669,6 +8669,25 @@ int WinSearchCheatDatabase()
ListView_GetItem(GetDlgItem(hDlg, b), &a); ListView_GetItem(GetDlgItem(hDlg, b), &a);
#define CHEAT_SIZE 1024 #define CHEAT_SIZE 1024
/* return a vector of all selected list items with their index in the listview
* as first element and their lparam as second element of a pair
*/
static std::vector<std::pair<int, int>> get_all_selected_listitems(HWND lView)
{
std::vector<std::pair<int, int>> result;
LVITEM lvitem = { 0 };
lvitem.mask = LVIF_PARAM;
int index = ListView_GetNextItem(lView, -1, LVNI_SELECTED);
do
{
lvitem.iItem = index;
ListView_GetItem(lView, &lvitem);
result.push_back(std::make_pair(index, (int)lvitem.lParam));
} while ((index = ListView_GetNextItem(lView, index, LVNI_SELECTED)) != -1);
return result;
}
INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
static bool internal_change; static bool internal_change;
@ -8755,19 +8774,31 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
switch(LOWORD(wParam)) switch(LOWORD(wParam))
{ {
case IDC_CHEAT_LIST: case IDC_CHEAT_LIST:
if(0==ListView_GetSelectedCount(GetDlgItem(hDlg, IDC_CHEAT_LIST))) {
// react only to item changes (we are interested in selection or checkbox)
if (((LPNMHDR)lParam)->code == LVN_ITEMCHANGED)
{
NMLISTVIEW* listview_notify = (NMLISTVIEW*)lParam;
if (listview_notify->uChanged & LVIF_STATE)
{
HWND lView = GetDlgItem(hDlg, IDC_CHEAT_LIST);
int sel_count = ListView_GetSelectedCount(lView);
// selection change, update button states and selection tracking variable
if ((listview_notify->uOldState & LVIS_SELECTED) != (listview_notify->uNewState & LVIS_SELECTED))
{
if (0 == sel_count)
{ {
EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), false); EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), false);
EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false);
has_sel=false; has_sel = false;
sel_idx=-1; sel_idx = -1;
} }
else else
{ {
EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), true); EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), true);
if(!has_sel||sel_idx!=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST))) if (!has_sel || sel_idx != ListView_GetSelectionMark(lView))
{ {
new_sel=3; new_sel = 3;
//change //change
TCHAR buf[CHEAT_SIZE]; TCHAR buf[CHEAT_SIZE];
LV_ITEM lvi; LV_ITEM lvi;
@ -8775,7 +8806,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
internal_change = true; // do not enable update button internal_change = true; // do not enable update button
/* Code */ /* Code */
ITEM_QUERY (lvi, IDC_CHEAT_LIST, 0, buf, CHEAT_SIZE); ITEM_QUERY(lvi, IDC_CHEAT_LIST, 0, buf, CHEAT_SIZE);
SetDlgItemText(hDlg, IDC_CHEAT_CODE, lvi.pszText); SetDlgItemText(hDlg, IDC_CHEAT_CODE, lvi.pszText);
/* Description */ /* Description */
@ -8784,11 +8815,25 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
internal_change = false; internal_change = false;
} }
sel_idx=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST)); sel_idx = ListView_GetSelectionMark(lView);
has_sel=true; has_sel = true;
}
}
// multi-select and change of checkbox state - set same state to all selected items
if (sel_count > 1 && (listview_notify->uOldState & LVIS_STATEIMAGEMASK) != (listview_notify->uNewState & LVIS_STATEIMAGEMASK))
{
auto selected_items = get_all_selected_listitems(lView);
for (const auto &item : selected_items)
{
ListView_SetItemState(lView, item.first, listview_notify->uNewState, LVIS_STATEIMAGEMASK);
}
} }
return true; return true;
}
}
}
default: return false; default: return false;
} }
} }
@ -8904,20 +8949,22 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
break; break;
case IDC_DELETE_CHEAT: case IDC_DELETE_CHEAT:
{ {
LVITEM lvi;
// get index in internal cheat list, if present mark as deleted
memset(&lvi, 0, sizeof(LVITEM));
lvi.mask = LVIF_PARAM;
lvi.iItem = sel_idx;
ListView_GetItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), &lvi);
if (lvi.lParam >= 0)
ct.state[lvi.lParam] = Deleted;
// save index, deleting item removes selection // save index, deleting item removes selection
int old_sel = sel_idx; int old_sel = sel_idx;
ListView_DeleteItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), sel_idx); HWND lView = GetDlgItem(hDlg, IDC_CHEAT_LIST);
ListView_SetItemState(GetDlgItem(hDlg, IDC_CHEAT_LIST), old_sel, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); auto deleted_items = get_all_selected_listitems(lView);
// we delete in reverse order so that our item indexes stay valid
std::reverse(deleted_items.begin(), deleted_items.end());
for (const auto &item : deleted_items)
{
// get index in internal cheat list, if present mark as deleted
if(item.second >= 0)
ct.state[item.second] = Deleted;
ListView_DeleteItem(lView, item.first);
}
ListView_SetItemState(lView, old_sel, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
} }
break; break;
@ -9087,6 +9134,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
return false; return false;
} }
} }
default: return false; default: return false;
} }
} }