mirror of https://github.com/snes9xgit/snes9x.git
win32: allow multiselect in cheat dialog, handle delete and selection
(#916)
This commit is contained in:
parent
add607c38f
commit
be53955553
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue