Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Form Disappearing when Settings Form Closes

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 4:26 am    Post subject: Form Disappearing when Settings Form Closes Reply with quote

I'm writing a Lua script that is based off of the main Settings form. I'm getting odd behavior that I can't seem to resolve - I haven't yet concluded if this is a bug or if I'm just doing something wrong. I'd appreciate any help!

Basically, what's happening is I have a form that should show when a checkbox is checked in the main Settings form. The form very briefly appears, but disappears almost immediately (it seems to disappear as soon as all the code is done executing). The form is not closing, nor is it hiding. It is getting destroyed or crashing altogether? I'm not sure.

You can replicate it with this:

Code:

local sfrm = getSettingsForm()
local tsExtra = sfrm.findComponentByName('Extra')
local cbProcessWatcher = sfrm.findComponentByName('cbProcessWatcher')
local btnOK = sfrm.findComponentByName('btnOK')
local btnOKOnClick = btnOK.OnClick -- so we can add to this without changing it

-- checkbox
local cbExample = createCheckBox(tsExtra)
cbExample.AnchorSideTop.Control = cbProcessWatcher
cbExample.AnchorSideTop.Side = asrBottom
cbExample.AnchorSideLeft.Control = cbProcessWatcher
cbExample.Caption = 'Form shows if this box is checked and you press OK'
cbExample.Checked = false

local frmExample = createForm(false)

local function showExampleForm()
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   frmExample.show()
end

function cbExample.OnChange()
   local isCbChecked = cbExample.getState()

   if isCbChecked == 1 then
      btnOK.setOnClick(showExampleForm)
   end
end


If you add a second form that shows after the first one, notice how that one will indeed continue to show.

Other things happening:
- if you add a second form, it stays up but when you close it, it hides the main CE form behind other opened other windows
- after these forms are closed you can't call them again even with show()
- if you have two forms, click the box and then OK, close the remaining one, uncheck and check the box again, press OK, you get an access violation
- if I add
Code:
local frmExample = createForm(false)
frmExample.show()
frmExample.hide()
frmExample.OnClose = function() frmExample.hide() end
it works fine (other than the form obviously popping up and hiding quickly).

It seems to have something to with the OnChange() method, and the Settings form in particular. I really just don't understand what's going here. Do I need to thread it or something? Thanks to any readers!


Last edited by dexter3 on Sun Jul 29, 2018 5:33 pm; edited 2 times in total
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sun Jul 29, 2018 5:27 am    Post subject: Reply with quote

Yeah, seems that the thread your form is running on gets killed when the settings form closes, so I think you will need to create a thread to allow your form to continue running.

https://wiki.cheatengine.org/index.php?title=Lua:Class:Thread

_________________
Back to top
View user's profile Send private message Visit poster's website
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Sun Jul 29, 2018 9:41 am    Post subject: Reply with quote

I can't replicate it. The window is shown and stays until closed. There are other bugs:
  • The OnClose function of the form should return caHide so it doesn't free itself when it's closed. Alternatively, create a new form every time the settings form is closed. Just don't access freed memory.
  • It won't show the form if the checkbox was already checked before the settings form is opened.
  • Checking and unchecking the checkbox will still show the form.
  • If the settings form is created when opened and destroyed when closed, your cached references to the GUI elements won't be valid. (although, the checkbox wouldn't exist either, so this probably isn't a problem)

PS: This has absolutely nothing to do with threads.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 12:04 pm    Post subject: Reply with quote

Thank you guys. @ParkourPenguin, I am really disappointed that you can't replicate this. It persists even across a restart on my computer. Did you place the script into a file in the autorun directory or run it directly?

I am aware of the other bugs and have handled them in the main script.

@TheyCallMeTim13 I also am feeling that this is not really threads, I have tried threading it and calling or synchronizing a thread just does the same thing. I am not an expert on threads though.

I changed the last function to this
Code:
function btnOK.OnClick()
   local isCbChecked = cbExample.getState()

   if isCbChecked == 1 then
      showExampleForm()
   end
end
and still get the same result, so it rules out the OnChange method and it seems more to do with the settings form in particular.

I also tried creating a new form every time the settings form is closed.
Code:
local function showExampleForm()
   local frmExample = createForm(false)
    frmExample.OnClose = function() return caFree end
   
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   frmExample.show()
end

function btnOK.OnClick()
   local isCbChecked = cbExample.getState()

   if isCbChecked == 1 then
      showExampleForm()
   end
end
Same result as before. I can't open the form again after I press OK. I think it's because the form is not actually closing (if you put a print statement in the OnClose, it doesn't print).

It is even odder to me if the same code doesn't replicate it for you. I guess it is worth mentioning I'm using version 6.8.1. Cheers for your responses though Very Happy

EDIT: Okay so I just tried the following code which does the same thing but for the "Advanced Options" form in the Main CE Form... and it works? So this is only happening in the Settings.

Code:
local aofrm = getForm(4)
print(aofrm.Caption) -- just check that it is Advanced Options form for you too
local pnl = aofrm.findComponentByName('Panel1')
local btnOK = aofrm.findComponentByName('Button1')
local btnOKOnClick = btnOK.OnClick

-- checkbox
local cbExample = createCheckBox(pnl)
cbExample.AnchorSideRight.Control = btnOK
cbExample.AnchorSideRight.Side = asrBottom
cbExample.AnchorSideBottom.Control = pnl
cbExample.BorderSpacing.Left = 10
cbExample.Caption = 'CB Shows From on OK'
cbExample.Checked = false

local frmExample = createForm(false)
frmExample.OnClose = function() return caHide end

local function showExampleForm()
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   frmExample.show()
end

function cbExample.OnChange()
   local isCbChecked = cbExample.getState()

   if isCbChecked == 1 then
      btnOK.setOnClick(showExampleForm)
   else btnOK.setOnClick(btnOKOnClick) end
end
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25798
Location: The netherlands

PostPosted: Sun Jul 29, 2018 1:47 pm    Post subject: Reply with quote

autoclosing only happens on things with popupmode set (or have it as a parent/owner)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 2:32 pm    Post subject: Reply with quote

Thanks DarkByte Smile but I don't believe popupmode is set:

print(getSettingsForm().PopupMode) --> prints pmNone

PopupMode is not set on any of the other involved elements either, unless I'm understanding incorrectly.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Sun Jul 29, 2018 3:32 pm    Post subject: Reply with quote

dexter3 wrote:
Did you place the script into a file in the autorun directory or run it directly?
I copied/pasted it into the Lua script window. Putting it in the autorun directory didn't seem to change anything on my end.

Try reducing this problem as much as you possibly can and figure out where exactly it stops working.

Is anything else interfering? Any other autorun scripts?

Does the form get destroyed or just hidden? Does changing the return value in the OnClose event change this behaviour?

The settings form is shown using ShowModal while the advanced options form is just shown normally. Perhaps reentrancy is a problem in certain cases.

See if this makes any difference:
Code:
local sfrm = getSettingsForm()
local tsExtra = sfrm.findComponentByName('Extra')
local cbProcessWatcher = sfrm.findComponentByName('cbProcessWatcher')
local btnOK = sfrm.findComponentByName('btnOK')
local btnOKOnClick = btnOK.OnClick -- so we can add to this without changing it

-- checkbox
local cbExample = createCheckBox(tsExtra)
cbExample.AnchorSideTop.Control = cbProcessWatcher
cbExample.AnchorSideTop.Side = asrBottom
cbExample.AnchorSideLeft.Control = cbProcessWatcher
cbExample.Caption = 'Form shows if this box is checked and you press OK'
cbExample.Checked = false

local frmExample = createForm(false)
frmExample.OnClose = function() return caHide end

local function showExampleForm(...)
  local result = { btnOKOnClick(...) }
  frmExample.show()
  return table.unpack(result)
end

function cbExample.OnChange()
  btnOK.OnClick = cbExample.Checked and showExampleForm or btnOKOnClick
end

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 4:14 pm    Post subject: Reply with quote

Thank you so much for your effort. I have been reducing the problem as much as possible. Here is everything I've done:

1. Reinstalled Cheat Engine
2. Tried both 32 and 64 bit versions
3. Removed all other scripts from autorun directory
4. I removed the checkbox altogether, and just made the form show when the OK button is pressed
5. Tried changing return value of OnClose event
6. Tried putting a print statement in OnClose event - nothing ever prints
7. Created a timer and printed out all the properties of the form before and after it is shown. The only thing that changes is the width
8. Tried doing this in "Advanced Options" form - it worked fine
9. If I show and then hide the form right after I create it, it works (but this is a weird workaround, and doesn't solve other problems I'm having)
10. Tried your script
11. Tried creating a form every time the OK button is pressed -doesn't work
[EDIT:] 12. If I hide the Settings Form rather than using the built-in OnClose function, the form remains visible and can be closed, but then my CE bugs out and I cannot close CE without using the Task Manager. So maybe the Settings OnClose function has something to do with this.

And this is exactly what happens:
1. I click OK - the form shows up very briefly but disappears along with the Settings Form
2. The Main CE window get pushed behind any other windows behind it (like my browser)
3. I cannot open the form again without restarting CE - it just won't show
4. No OnClose function is called, so I would assume the form is destroyed, but it is also not destroyed because I can't even create another new form


I also found something very strange!
1. If I click the "Enable Process Watcher" checkbox (in the extra tab) when I first start CE (remember my checkbox doesn't even exist anymore), the form shows and stays! It doesn't matter if the box is already checked or not.
2. But once I close it I still cannot open it again (even with return caHide), regardless if I check the box again
3. this time I do get an OnClose event
4. With this the Main CE Form does not hide behind the other windows below it
5. This works exactly the same with any other checkbox

Maybe now you're convinced this problem is CE and not the code, lol

EDIT: Progress

Alrighty I got it to work by using this:

Code:
local function showForm()
   frmExample.show()
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   btnOK.setOnClick(showForm)
end

btnOK.OnClick = showForm


You have to reset the OnClick back to the original function after calling it. Of course, that doesn't explain the other things. I'm still having trouble getting it to work with a checkbox, so unfortunately we still have to dig deeper. This code works (now we have a checkbox again):

Code:
local function showExampleForm()
   local iscbchecked = cbExample.getState()
   print("WORKING", iscbchecked)
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   btnOK.setOnClick(showExampleForm)
   if iscbchecked == 1 then frmExample.show() end
end

btnOK.OnClick = showExampleForm


...but, if I delete the print statement it stops working again Confused The reason is because the print statement brings up a different form, making my form the second form. If my form is the second form, it works fine. But I move the print statement so that my form is the first form to pop up, it breaks again. What the heck is going on with this form?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Sun Jul 29, 2018 6:23 pm    Post subject: Reply with quote

dexter3 wrote:
I realized that the print("SHOWING FORM") statement was not getting called at all after I first closed the form (Penguin, I'd be curious if it does for you).
Both strings are printed exactly as expected for me.

Perhaps the problem is that the original OnClick is executed before the form is shown. The original OnClick function assigns a value to the setting form's ModalResult member. Because the form was shown via ShowModal, this should terminate the form and return immediately.

Try my previous code again, but replace the showExampleForm function with this definition:
Code:
local function showExampleForm(...)
  frmExample.show()
  return btnOKOnClick(...)
end


If it still doesn't work, maybe the event functions aren't reentrant.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 6:36 pm    Post subject: Reply with quote

No, it still disappears immediately after unfortunately.

Could you explain what you mean by reentrant?

And even if that is the case, what would cause them to be reentrant for you, but not me?

Edit: Okay, I was wrong before. The reason why the code with only the button worked is because I had a print statement as well. I didn't think it was influencing the outcome.

Code:
local function showForm()
   print("SHOWING FORM")
   frmExample.show()
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   btnOK.setOnClick(showForm)
end

btnOK.OnClick = showForm


It's because I have two forms showing up that it is working, the checkbox should not have an influence. It breaks once more if I delete the print statement. Likewise, if I use your code like this:

Code:
local function showExampleForm(...)
  print("SHOWING")
  frmExample.show()
  return btnOKOnClick(...)
end


then it works
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Sun Jul 29, 2018 7:22 pm    Post subject: This post has 1 review(s) Reply with quote

"Reentrant" basically means a function can be interrupted and still do what it's suppose to do. In this case, the OnClick callback function is being interrupted by calling a function to show another form. The process of showing another form can have side effects on the application as a whole, which might cause undefined behaviour if the OnClick callback wasn't expecting those side effects to happen.

Undefined behaviour is what it sounds like: anything can happen. It can work exactly as expected for some people, fail miserably for other people, or even open a portal to another dimension occupied by entities that will enslave humanity. Regardless of what happens, it's never a good thing and should be avoided if at all possible.

I'm not saying reentrancy is without a doubt the problem- it could be an unrelated bug.


Another total shot in the dark, but try this:
Code:
local function showExampleForm()
   frmExample.show()
   processMessages()
   btnOK.setOnClick(btnOKOnClick)
   btnOK.doClick()
   btnOK.setOnClick(showForm)
   processMessages()
end
You definitely shouldn't be calling processMessages in a GUI callback, but at this point I'm curious if it'll work.

Maybe try calling bringToFront() at different points on either the settings form or the other form and see if that does anything.

I guess you could wait to show the form:
Code:
local function showExampleForm(...)
  local t = createTimer(nil, true)
  t.Interval = 100
  t.OnTimer = function()
    frmExample.show()
    t.destroy()
  end
  return btnOKOnClick(...)
end

These suggestions are becoming more like a hack and don't really address the problem at all.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
dexter3
Newbie cheater
Reputation: 0

Joined: 19 Jul 2018
Posts: 10

PostPosted: Sun Jul 29, 2018 7:41 pm    Post subject: Reply with quote

Great explanation! You could be right... it does fit the premise of the problem so far. Would there be some way we could check if the functions are reentrant?

I tried processMessages() and it didn't change anything. frmExample.bringToFront() in every location in the function did nothing, but sfrm.bringToFront() stopped the main CE window from going behind my other windows after I clicked OK.

Yeah, those are pretty hacky solutions. I already have a hacky solution to this, but that's why I brought it up here - I wanted to know what's really happening.

But interestingly, your timer solution works. In fact, I could even set the interval to 1ms and it seems to be working? So strange. I'll use this for now, and perhaps I'll pm you if I have any questions about it. I'm super grateful for your input, thank you Smile
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4702

PostPosted: Sun Jul 29, 2018 8:57 pm    Post subject: Reply with quote

I can't think of any good way of checking it besides looking at documentation (I haven't found anything yet).

The main thread is responsible for running that timer's code. Since the main thread can't run that code immediately, it has to finish executing the callback and closing the modal form. This means your form will only be shown after the settings form has closed completely (and not while the settings form is in the process of closing).

Creating the timer in the callback probably doesn't cause any problems because timers aren't significantly related to the GUI. Although, again, that's just a hypothesis.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites