cannonfodderex Advanced Cheater
Reputation: 0
Joined: 30 Oct 2012 Posts: 66
|
Posted: Thu Nov 06, 2025 2:18 am Post subject: A filterable list box for dropdown value change |
|
|
When I try to change a value of address with dropdown, a "change value" dialog popup.
When typing something in the combo box, and press up or down on keyboard, it only matches the start of a string.
So I made a form with text box filter for a list box, and match any substring, not just the start, so I can click to select a value from the filtered list.
This is done with the help of AylinCE and Dark Byte in this post, and AI
https://forum.cheatengine.org/viewtopic.php?p=5794106
How to use:
You need a memory record with dropdown data, in my code it's called "iItemList", you can change it's name in DropdownDataRecordName.
Then you need to modify the function isTargetMemoryRecordValid(memRecord), to judge what memory records you want to modify.
In my example it's 4bytes record with description beginning with "iItem[".
Create a script in your table, paste the code.
Enable the script, a window will popup, you may close it.
Double click the value of a record which you want to change, the window will popup, then double click a line in the list box, the id of that line will be set to the value of your selected record.
| Code: |
[ENABLE]
{$lua}
-- UNIQUE FORM NAME
local FORM_NAME = "CE_ItemListFilterForm"
local DropdownDataRecordName = "iItemList"
local function isTargetMemoryRecordValid(memRecord)
--print(memRecord)
if memRecord and memRecord.Type == 2 and string.sub(memRecord.Description, 1, 6) == "iItem["
then return true
else return false
end
end
-- Find existing form by name using getForm/getFormCount
local function findFormByName(name)
for i = 0, getFormCount() - 1 do
local f = getForm(i)
if f and f.Name == name then return f end
end
return nil
end
-- Create UI and store control references in frm.luaData
local function createUI()
-- If an existing form is present, return it (reuse)
local existing = findFormByName(FORM_NAME)
if existing then
return existing, true
end
-- Create new form as a child of main form
local mf = getMainForm()
local frm = createForm(mf)
frm.Name = FORM_NAME
frm.Caption = "Item List Filter"
frm.Width = 500
frm.Height = 400
frm.Position = "poOwnerFormCenter"
-- Create controls
local lblFilter = createLabel(frm); lblFilter.Caption = "Filter:"; lblFilter.Left = 20; lblFilter.Top = 20
local edtFilter = createEdit(frm); edtFilter.Left = 80; edtFilter.Top = 18; edtFilter.Width = 200; edtFilter.Text = ""; edtFilter.Hint = "Enter keywords for real-time filtering"; edtFilter.ShowHint = true
local btnClear = createButton(frm); btnClear.Caption = "Clear"; btnClear.Left = 290; btnClear.Top = 18; btnClear.Width = 60
local lblStatus = createLabel(frm); lblStatus.Caption = "Total 0 items"; lblStatus.Left = 360; lblStatus.Top = 22; lblStatus.Font.Style = '[]'
local lbItems = createListBox(frm); lbItems.Left = 20; lbItems.Top = 50; lbItems.Width = 460; lbItems.Height = 300; lbItems.MultiSelect = false
local lblSelected = createLabel(frm); lblSelected.Caption = "Selected: None"; lblSelected.Left = 20; lblSelected.Top = 355; lblSelected.Width = 460; lblSelected.Height = 20
-- Store references and data on the form object so Disable can find them
frm.luaData = {
edtFilter = edtFilter,
btnClear = btnClear,
lblStatus = lblStatus,
lbItems = lbItems,
lblSelected = lblSelected,
allItems = {}
}
-- Helper: convert id to number for sorting
local function idToNumber(id) return tonumber(id) or 0 end
-- Read item data from iItemList dropdown
local function getItemDataFromDropdown()
local itemData = {}
local addressList = getAddressList()
local iItemListRecord = nil
for i = 0, addressList.Count - 1 do
local rec = addressList[i]
if rec and rec.Description == DropdownDataRecordName then iItemListRecord = rec; break end
end
if not iItemListRecord then return itemData end
if not iItemListRecord.DropDownCount or iItemListRecord.DropDownCount == 0 then return itemData end
for i = 0, iItemListRecord.DropDownCount - 1 do
local v = iItemListRecord.DropDownValue[i]
local d = iItemListRecord.DropDownDescription[i]
if v and d then itemData[tostring(v)] = d end
end
return itemData
end
-- Update status label
local function updateStatus(frm, matchCount)
local data = frm.luaData
local total = #data.allItems
matchCount = matchCount or total
if matchCount == total then
data.lblStatus.Caption = string.format("Total %d items", total)
data.lblStatus.Font.Color = 0x000000
else
data.lblStatus.Caption = string.format("Showing %d / %d items", matchCount, total)
data.lblStatus.Font.Color = 0xFF0000
end
end
-- Initialize list content from dropdown
local function initializeList(frm)
local data = frm.luaData
data.lbItems.Items.clear()
data.allItems = {}
local itemData = getItemDataFromDropdown()
local temp = {}
for id, name in pairs(itemData) do
table.insert(temp, { id = id, name = name, display = string.format("[%s] %s", id, name), numericId = idToNumber(id) })
end
table.sort(temp, function(a, b) return a.numericId < b.numericId end)
for _, it in ipairs(temp) do
table.insert(data.allItems, it)
data.lbItems.Items.add(it.display)
end
updateStatus(frm)
end
-- Get currently selected item info from listbox
local function getSelectedItemInfo(frm)
local data = frm.luaData
local idx = data.lbItems.ItemIndex
if idx >= 0 then
local txt = data.lbItems.Items[idx]
local id, name = string.match(txt, "%[(%d+)%] (.+)")
if id and name then return { id = id, name = name } end
end
return nil
end
-- Apply selected value to currently selected addresslist record
local function applyValue(frm, selected)
local addressList = getAddressList()
local target = addressList.SelectedRecord
if not target then showMessage("ERROR: No item memory record is selected in the Cheat Table."); return end
if isTargetMemoryRecordValid(target) then
target.Value = selected.id
addressList.refresh()
end
end
-- Filter list by text
local function filterList(frm, text)
local data = frm.luaData
data.lbItems.Items.clear()
local f = string.lower(text or "")
local matches = 0
for _, it in ipairs(data.allItems) do
if string.find(string.lower(it.display), f, 1, true)
or string.find(string.lower(it.name), f, 1, true)
or string.find(string.lower(it.id), f, 1, true) then
data.lbItems.Items.add(it.display)
matches = matches + 1
end
end
updateStatus(frm, matches)
end
-- Event bindings using stored control refs
edtFilter.OnChange = function() filterList(frm, edtFilter.Text) end
btnClear.OnClick = function() edtFilter.Text = ""; filterList(frm, ""); edtFilter.SetFocus() end
lbItems.OnSelectionChange = function()
local s = getSelectedItemInfo(frm)
if s then frm.luaData.lblSelected.Caption = string.format("Selected: ID=%s, Name=%s", s.id, s.name)
else frm.luaData.lblSelected.Caption = "Selected: None" end
end
lbItems.OnDblClick = function()
local s = getSelectedItemInfo(frm); if s then applyValue(frm, s) end
end
-- Try to make OnClose hide the form instead of forcing destruction
pcall(function()
frm.OnClose = function(sender, closeAction)
if type(closeAction) == "userdata" then closeAction = caHide end
sender.Hide()
end
end)
-- Populate the list now so it is ready when shown later
initializeList(frm)
return frm, false
end
-- Create UI but do not show it now; it will be shown in AddressList.OnValueChange
local ok, frm = pcall(function() return createUI() end)
if not ok then
print("Failed to create UI in ENABLE:", frm)
end
-- Bind AddressList.OnValueChange safely; this will show the form when appropriate
AddressList.OnValueChange = function(addresslist, memrec)
if isTargetMemoryRecordValid(memrec) then
-- Ensure the form exists; create if missing
local f = findFormByName(FORM_NAME)
if not f then
pcall(function() createUI() end)
f = findFormByName(FORM_NAME)
end
-- Show the form safely (only here)
if f then pcall(function() if not f.Visible then f.Show() end end) end
return true
else
return false
end
end
[DISABLE]
{$lua}
local FORM_NAME = "CE_ItemListFilterForm"
-- Find existing form by name using getForm/getFormCount
local function findFormByName(name)
for i=0, getFormCount()-1 do
local f = getForm(i)
if f and f.Name == name then return f end
end
return nil
end
-- Locate form and safely detach events, hide and destroy it
local frm = findFormByName(FORM_NAME)
if frm then
pcall(function()
if frm.luaData then
if frm.luaData.lbItems then
frm.luaData.lbItems.OnSelectionChange = nil
frm.luaData.lbItems.OnDblClick = nil
end
if frm.luaData.edtFilter then frm.luaData.edtFilter.OnChange = nil end
if frm.luaData.btnClear then frm.luaData.btnClear.OnClick = nil end
end
if frm.Visible then frm.Hide() end
frm.Destroy()
end)
end
-- Clear AddressList callback
AddressList.OnValueChange = nil
|
| Description: |
|
| Filesize: |
41.32 KB |
| Viewed: |
180 Time(s) |

|
|
|