| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| gibberishh Cheater
 
 ![]() Reputation: 1 
 Joined: 30 Aug 2021
 Posts: 45
 
 
 | 
			
				|  Posted: Tue Aug 06, 2024 7:58 am    Post subject: Add controls via script at design time |   |  
				| 
 |  
				| I followed example.ct from https://forum.cheatengine.org/viewtopic.php?t=586842&sid=f6321c5829c9b4e0731fa36868325bdb and got it working for my purpose. First of all, thanks for that. 
 I have 219 image files (character portraits in a game) and that populates a HUGE menu under Table. Before anyone goes screaming, the portraits are tiny and the CT is around 600KB with everything. However, I despise that long menu of files under Table.
 
 My idea of a workaround for this is to add image controls in design mode and assign the pictures to them, without going via the Add File route. But, here is what happens: I put the form in edit mode and run my script to add the controls. Everything shows correctly. However, the controls are not listed in Object Inspector. Ever the optimist, I save the table in the main window. Now I close the form, open again and everything added via code is gone. [cries in despair] (Note: files are still added to the table, I intend to delete them after they are populated at design time.)
 
 Obviously, I don't want to manually add 219 image controls in the scrollbox. So my question is this: is there a way to use Lua to add these controls at design time so that they will stay on the form?
 
 Thanks!
 
 Fully working code:
 
  	  | Code: |  	  | function ShowPortraits() -- frmPix is the form; all these named objects are created at design time (Table > Create form)
 -- frmPix.tabM, despite the name, is a group control for male portraits (need this for the caption it shows, which scrollbar control doesn't)
 -- frmPix.tabF is a group control for female portraits (earlier used tabs and then changed them to group controls, hence the bad naming)
 -- frmPix.tabM.sclPixM is a scrollbar control for male portraits
 -- frmPix.tabF.sclPixF is a scrollbar control for female portraits
 local img = {}
 local cols = 7
 local bspace = 3
 for x,g in ipairs({"M","F"}) do
 local ctrls = {}
 for i=0,127 do -- don't worry about the iterator; some numbers don't have files associated, in total I have 105 F and 114 M files
 local f = findTableFile(g..i..".png")
 if f then
 img[i] = createImage(frmPix.ComponentByName["sclPix"..g])
 img[i].Autosize = true
 img[i].Name = f.Name:sub(1,-5)
 table.insert(ctrls, img[i])
 if (#ctrls-1)%cols > 0 then -- puts the images in a neat grid, in this case of 7 columns
 img[i].anchorSideLeft.control = ctrls[#ctrls-1]
 img[i].anchorSideLeft.side = asrRight
 img[i].BorderSpacing.Left = bspace
 img[i].anchorSideTop.control = ctrls[#ctrls-1]
 img[i].anchorSideTop.side = asrTop
 img[i].BorderSpacing.Top = 0
 else
 img[i].anchorSideLeft.control = frmPix.ComponentByName["sclPix"..g]
 img[i].anchorSideLeft.side = asrLeft
 img[i].BorderSpacing.Left = bspace
 img[i].BorderSpacing.Top = bspace
 if #ctrls==1 then
 img[i].anchorSideTop.control = frmPix.ComponentByName["sclPix"..g]
 img[i].anchorSideTop.side = asrTop
 else
 img[i].anchorSideTop.control = ctrls[#ctrls-1]
 img[i].anchorSideTop.side = asrBottom
 end
 end
 local s = f.stream;
 img[i].Picture.loadFromStream(s)
 img[i].OnClick = SetPortrait -- a separate function that does things when the image is clicked
 end
 end
 end
 portraitsLoaded = true -- global var to prevent re-running of this code
 end
 | 
 _________________
 
 It's not cheating. It's playing by my rules. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| AylinCE Grandmaster Cheater Supreme
 
  Reputation: 37 
 Joined: 16 Feb 2017
 Posts: 1528
 
 
 | 
			
				|  Posted: Tue Aug 06, 2024 10:09 am    Post subject: |   |  
				| 
 |  
				| This code and example may be more understandable in your case. 
 1) 25 images have been added for example usage. Arrange them in the code according to yourself. (Look at the warning lines written as 105 and 114.)
 2) Mouse wheel option has been added to the code. (Active on TrackBar and Image boxes.)
 3) You can run functions based on image order on image clicks. (You can do this with "fIndex" and "mIndex".)
 4) Important factor; You need to create image names in order. (In the example table, they are shown as "F_1, F_2, F_3..")
 
 5 ) Below is an example table connection and the code used:
 CT Link : https://www.mediafire.com/file/xqfytc7b1esxe9a/Example_1.CT/file
 
 
  	  | Code: |  	  | if frm1 then frm1.Destroy() frm1=nil end DP1=getScreenDPI()/96
 frm1=createForm()
 frm1.height=290*DP1 frm1.width=600*DP1
 frm1.PopupMode=0 frm1.caption="frm1"
 frm1.Position="poDesktopCenter" frm1.ShowInTaskBar="stAlways"
 frm1.BorderStyle="bsSingle"
 -------------------------
 local frmPix = {}
 ----------------------- frmPix.bckImg1 -----
 frmPix.bckImg1=createImage(frm1)
 frmPix.bckImg1.AutoSize=false
 frmPix.bckImg1.height=200*DP1 frmPix.bckImg1.width=200*DP1 frmPix.bckImg1.left=50*DP1 frmPix.bckImg1.top=30*DP1
 frmPix.bckImg1.Stretch=true
 -----------------------
 ----------------------- frmPix.bckImg2 -----
 frmPix.bckImg2=createImage(frm1)
 frmPix.bckImg2.AutoSize=false
 frmPix.bckImg2.height=200*DP1 frmPix.bckImg2.width=200*DP1 frmPix.bckImg2.left=350*DP1 frmPix.bckImg2.top=30*DP1
 frmPix.bckImg2.Stretch=true
 -----------------------
 ----------------------- frmPix.trcBar1 -----
 frmPix.trcBar1=createTrackBar(frm1)
 frmPix.trcBar1.AutoSize=false
 frmPix.trcBar1.height=25*DP1 frmPix.trcBar1.width=280*DP1 frmPix.trcBar1.left=10*DP1 frmPix.trcBar1.top=240*DP1
 -----------------------
 ----------------------- frmPix.trcBar2 -----
 frmPix.trcBar2=createTrackBar(frm1)
 frmPix.trcBar2.AutoSize=false
 frmPix.trcBar2.height=25*DP1 frmPix.trcBar2.width=280*DP1 frmPix.trcBar2.left=310*DP1 frmPix.trcBar2.top=240*DP1
 -----------------------
 
 --############################################################################--
 --############################################################################--
 frmPix.trcBar1.Min=1
 frmPix.trcBar1.Max=11 -- 105
 frmPix.trcBar2.Min=1
 frmPix.trcBar2.Max=14 -- 114
 frmPix.trcBar1.Position=1
 frmPix.trcBar2.Position=1
 frmPix.bckImg1.picture.loadFromStream(findTableFile("F_1.png").stream)
 frmPix.bckImg2.picture.loadFromStream(findTableFile("M_1.png").stream)
 local fIndex = 1
 local mIndex = 1
 --------------------------------------------------
 
 frmPix.trcBar1.OnMouseWheelDown=function(sender)
 if sender.Position==11 then -- 105
 sender.Position=11 -- 105
 else
 sender.Position= tonumber(sender.Position) + 1
 end
 end
 
 frmPix.trcBar1.OnMouseWheelUp=function(sender)
 if sender.Position==1 then
 sender.Position=1
 else
 sender.Position= tonumber(sender.Position) - 1
 end
 end
 
 
 frmPix.bckImg1.OnMouseWheelDown=function()
 local sender = frmPix.trcBar1
 if sender.Position==14 then -- 114
 sender.Position=14 -- 114
 else
 sender.Position= tonumber(sender.Position) + 1
 end
 end
 
 frmPix.bckImg1.OnMouseWheelUp=function()
 local sender = frmPix.trcBar1
 if sender.Position==1 then
 sender.Position=1
 else
 sender.Position= tonumber(sender.Position) - 1
 end
 end
 
 --------------------------------------------------
 
 frmPix.trcBar2.OnMouseWheelDown=function(sender)
 if sender.Position==14 then -- 114
 sender.Position=14 -- 114
 else
 sender.Position= tonumber(sender.Position) + 1
 end
 end
 
 frmPix.trcBar2.OnMouseWheelUp=function(sender)
 if sender.Position==1 then
 sender.Position=1
 else
 sender.Position= tonumber(sender.Position) - 1
 end
 end
 
 
 frmPix.bckImg2.OnMouseWheelDown=function()
 local sender = frmPix.trcBar2
 if sender.Position==14 then -- 114
 sender.Position=14 -- 114
 else
 sender.Position= tonumber(sender.Position) + 1
 end
 end
 
 frmPix.bckImg2.OnMouseWheelUp=function()
 local sender = frmPix.trcBar2
 if sender.Position==1 then
 sender.Position=1
 else
 sender.Position= tonumber(sender.Position) - 1
 end
 end
 
 --------------------------------------------------
 
 frmPix.trcBar1.OnChange=function(sender)
 fIndex = sender.Position
 src = "F_"..sender.Position
 frmPix.bckImg1.picture.loadFromStream(findTableFile(src..".png").stream)
 end
 
 
 frmPix.trcBar2.OnChange=function(sender)
 mIndex = sender.Position
 src = "M_"..sender.Position
 frmPix.bckImg2.picture.loadFromStream(findTableFile(src..".png").stream)
 end
 
 ---------------------------------------------------
 ---------------------------------------------------
 function SetPortraitF()
 showMessage("You clicked on image number "..fIndex.."!")
 end
 
 function SetPortraitM()
 showMessage("You clicked on image number "..mIndex.."!")
 end
 
 frmPix.bckImg1.OnClick=function()
 SetPortraitF()
 end
 
 frmPix.bckImg2.OnClick=function()
 SetPortraitM()
 end
 | 
 _________________
 
 |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| gibberishh Cheater
 
 ![]() Reputation: 1 
 Joined: 30 Aug 2021
 Posts: 45
 
 
 | 
			
				|  Posted: Tue Aug 06, 2024 11:27 am    Post subject: |   |  
				| 
 |  
				| Apologies if I was not clear... I already have working code using findTableFile(), in exactly the format and structure that I need. The problem is that findTableFile() requires me to use Table > Add file, which then generates a totally useless (at least in my case) menu full of 220 filenames. 
 I want to be able to add image controls at design time via code to be able to circumvent CE's file handling.
 
 Your trackbar is cool, but it still uses runtime loading of images from the _files_ loaded into the table (as opposed to images that are stored within the image control's Picture property).
 
 For clarity: if at design time I manually add an image control, click Picture and Load a file into it, that is NOT added to the Table menu. It is stored as a pic (ASCII translation) within the image control. I want to be able to generate such image controls once at design time via code, save the form, and never have to deal with the Table menu or findTableFile().
 _________________
 
 It's not cheating. It's playing by my rules. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| AylinCE Grandmaster Cheater Supreme
 
  Reputation: 37 
 Joined: 16 Feb 2017
 Posts: 1528
 
 
 | 
			
				|  Posted: Tue Aug 06, 2024 1:14 pm    Post subject: |     |  
				| 
 |  
				| As far as I understand, you don't want the images in the table. If I understand correctly, I will give you 2 options and you can choose one of them:
 
 1) Upload all the images to a storage server and call them from the table via "Internet", upload and use them. (This option uploads the images only to the table, not to the PC.)
 
 2) Store the images in a desktop folder and upload and use them from there.
 
 (3.. I will not recommend ImageList. It may be a pixel concern!)
 
 Which one?
 
 Otherwise, all the images will still be saved in the form in the form design or in the "Add file" option.
 For a lighter table, I recommend option number 1.
 _________________
 
 |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| gibberishh Cheater
 
 ![]() Reputation: 1 
 Joined: 30 Aug 2021
 Posts: 45
 
 
 | 
			
				|  Posted: Tue Aug 06, 2024 10:37 pm    Post subject: |   |  
				| 
 |  
				| Oh. ParkourPenguin's suggestion looks promising. Am going to try saveCurrentStateAsDesign() first. Will return later and let you'll know how things work out. 
 Thanks both of you for all your suggestions!
 
 
 Update:
 Here's what I've ended up doing. saveCurrentStateAsDesign() was no bueno. The code-added controls never show up in Object Inspector so they are never saved along with the form/table (at least that's my uneducated reasoning).
 
 So I ran my original script, took a screenshot of the whole grid and saved that as two images (M, F). Then I manually added 2 image controls in design mode, and loaded these canvases into them.
 
 Modified my script to add fixed-size image controls without loading any picture into them (i.e., they are transparent/invisible). They sit exactly on top of each portrait because the code that positions them is the same from before (through which I took the screenshot). The portrait Ids I need went into an array instead of looking up the table files.
 
 Now I don't need any table files for images. The canvases are stored as part of form data. Opened the CT in a text editor, removed the whole <Files></Files> block, and now I'm golden.
 _________________
 
 It's not cheating. It's playing by my rules. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Wed Aug 07, 2024 12:55 am    Post subject: |   |  
				| 
 |  
				| Did you try my example code? It works fine for me 	  | gibberishh wrote: |  	  | The code-added controls never show up in Object Inspector so they are never saved along with the form/table (at least that's my uneducated reasoning). | 
 
 Open a new CE instance
Copy & paste that code into the Lua script window
Click Table -> Create Form
Execute the Lua script (the new image GUI component won't show up in the object inspector until you close and reopen it, but that's irrelevant)
Save the table (File -> Save as...)
Close CE and open a new instance
Load the CT file you just saved
Execute the Lua script- the image was saved properly
 I'm glad you got it working anyhow
 _________________
 
 I don't know where I'm going, but I'll figure it out when I get there. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| gibberishh Cheater
 
 ![]() Reputation: 1 
 Joined: 30 Aug 2021
 Posts: 45
 
 
 |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Wed Aug 07, 2024 1:36 pm    Post subject: |   |  
				| 
 |  
				| Parent / owner are different concepts. Generally the form should own everything unless you have a good reason otherwise (I'm not familiar enough with lazarus or pascal to say what such a reason could be) 
 Setting method properties to strings that are the names of global functions seem to save properly:
 
 If the global function isn't defined, then this won't work 	  | Code: |  	  | function UDF1_imageClicked(img) print'clicked'
 end
 
 ...
 
 img.OnClick = 'UDF1_imageClicked'
 | 
 _________________
 
 I don't know where I'm going, but I'll figure it out when I get there. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| gibberishh Cheater
 
 ![]() Reputation: 1 
 Joined: 30 Aug 2021
 Posts: 45
 
 
 | 
			
				|  Posted: Wed Aug 07, 2024 2:52 pm    Post subject: |   |  
				| 
 |  
				| Oh, good to know. When creating controls at runtime (not in design mode), simply assigning a function to it works -- i.e., not just ctrl.OnClick = function() ... end but also ctrl.OnClick = NamedGlobalFunction. 
 I was not aware of assigning function names as strings. Not the first... or even the last thing I would have thought of!
 
 Will keep the owner thing in mind from now on.
 _________________
 
 It's not cheating. It's playing by my rules. |  | 
	
		| Back to top |  | 
	
		|  | 
	
		| AylinCE Grandmaster Cheater Supreme
 
  Reputation: 37 
 Joined: 16 Feb 2017
 Posts: 1528
 
 
 | 
			
				|  Posted: Wed Aug 07, 2024 3:32 pm    Post subject: |   |  
				| 
 |  
				| When you create the table before and outside the function, you may be able to use the generated control as in the example. 
 
  	  | Code: |  	  | local img = {} 
 function ShowPortraits()
 -- ...
 img["x"..i] = createImage(frmPix) -- or "parent" createImage(frmPix.sclPixM)
 
 end
 
 img.x1.OnClick=function() print(1) end
 img.x2.OnClick=function() print(2) end
 | 
 _________________
 
 |  | 
	
		| Back to top |  | 
	
		|  | 
	
		|  |