Event(guiescape) call function problem in class Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
holahapi
Posts: 72
Joined: 09 Nov 2016, 21:52

Event(guiescape) call function problem in class

07 May 2019, 04:19

Trying to call a function when gui close.

When putting the GUI inside a class.function
Guiclose sub will not able to call the function.
I found that Guiclose can be a function, But i dont know how it is work.

need some help, thanks

Code: Select all

#SingleInstance, force

tc := new TestClass()
return

Class TestClass {

	__New()
	{
	  gui a: new
	  gui a: show, x100 y100 w100 h100
	}
   
	FunctionA()
	{
		msgbox, Hello
		return
	}
   
   
	FunctionB()
	{
	aguiclose:
		{
		this.FunctionA() ;This one not working
		return
		}
	}
   
	GuiClose(GuiHwnd) 	;dont know how this work https://autohotkey.com/docs/commands/Gui.htm#GuiClose
	{  
		msgbox, This is GUI close function
        return
	}
	
   
}
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Event(guiescape) call function problem in class

07 May 2019, 11:34

Hi,

Here's one solution. You can use OnMessage instead if you want to encapsulate the onclose handler inside the class. Demonstrated elsewhere by Helgef in the forum (if I manage to retrieve it i'll link it [EDIT] Here you go).

Code: Select all

#NoEnv
#SingleInstance force
#Warn

tc := new TestClass("myGUIInstancesOn")
tc.show(,, 400, 400)
OnExit, handleExit
return

handleExit:
tc.destroy()
ExitApp


Class TestClass {
	static _instances := []
	__New(_customPrefix) {
		local _GUIID
		gui new, +HWND_GUIID +Label%_customPrefix% ; https://autohotkey.com/docs/commands/Gui.htm#PlusLabel
		this._GUIID := _GUIID
	return TestClass._instances[_GUIID] := this ; keep track of GUI instances by storing them by their respective hwnd.
	}
	show(_x:="Center", _y:="Center", _w:=0, _h:=0) {
	gui % this._GUIID . ":show", % Format("x{} y{} w{} h{}", _x, _y, _w, _h)
	}
	destroy() {
	gui % this._GUIID . ":destroy"
	TestClass._instances[this._GUIID] := "" ; remove circular references (useful if you intend to implement a __Delete µfunc) | https://autohotkey.com/docs/Objects.htm#Usage_Freeing_Objects
	}
	__Delete() {
	MsgBox % A_ThisFunc
	}
	methodA() {
		MsgBox 4,, % "Are you sure you want to hide the GUI " this._GUIID . "?"
		IfMsgBox No
			return true
		return 0
	}
}
myGUIInstancesOnClose(_guiHwnd) {
local _instance
_instance := TestClass._instances[_guiHwnd] ; retrieve the target instance @ _instances by means of its hwnd.
return _instance.methodA() ; call 'methodA' and use its return value as GuiClose's callback return value (any non-zero integer will prevent the GUI from hiding).
}
Hope this helps.
my scripts
holahapi
Posts: 72
Joined: 09 Nov 2016, 21:52

Re: Event(guiescape) call function problem in class

08 May 2019, 05:12

Thank you for the solution. however, it is too difficult for me.

The best solution I want is pack everthing inside the class, and use 1 line code to create a instance.

After readings your links, I end up by using a guiclose-sub outside the class to call the class.function

Code: Select all

#SingleInstance, force

tc := new TestClass()
return

aguiclose:
	tc.CloseFunction()

Class TestClass {
	__New()
	{
	  gui a: new
	  gui a: show, x100 y100 w100 h100
	}
	CloseFunction()
	{
		msgbox, Here is closeFunctin
	}
}
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Event(guiescape) call function problem in class

08 May 2019, 15:14

holahapi wrote:
08 May 2019, 05:12
holahapi wrote:
08 May 2019, 05:12
After readings your links, I end up by using a guiclose-sub outside the class to call the class.function
I recommend against the use of labels (in this case). Btw, in your exemple, @ aGuiCLose, you presuppose that tc is the target instance of you class which fired the label.
holahapi wrote:
08 May 2019, 05:12
Thank you for the solution. however, it is too difficult for me.[...]The best solution I want is pack everthing inside the class, and use 1 line code to create a instance.
After what has been said, it all depends on whether or not your class is intended to create many instances. Generally, with objects, there may be multiple GUI, existing concurrently. In this case your code must ensure, at least, that each time it targets the right instance. The simpliest way I can think of with your specific requirement and how GuiClose label/function are designed is the following:

Code: Select all

#NoEnv
#SingleInstance force
#Warn

tc := new TestClass("blabla")
tc2 := new TestClass("hola!")
return

Class TestClass {
	static _instances := [] ; keep track of instances
	__New(name) {
	  GUI, New, % "+HWNDGUIhwnd +Label" . this.__Class ".__on" ; https://autohotkey.com/docs/commands/Gui.htm#PlusLabel
	  this.GUIhwnd := GUIhwnd
	  this.name := name
	  this.show()
	return TestClass._instances[ GUIhwnd+0 ] := this ; keep track of GUI instances by storing them by their respective hwnd.
	}
	show(x:=100, y:=100, w:=100, h:=100) {
	GUI % this.GUIhwnd . ":Show", % "x" x "y" y "w" w "h" h
	}
	destroy() {
		GUI % this.GUIhwnd . ":Destroy"
		TestClass._instances[this._GUIID] := "" ; remove circular references.
	return 0
	}
	__onClose() { ; the first callback parameter - for the GUIClose label: the GUIhwnd - is passed to 'this' (see also: https://autohotkey.com/docs/Objects.htm#Custom_Classes_method)
		GUIID := this, this := TestClass._instances[GUIID] ; retrieve the target instance by means of its hwnd.
		MsgBox 4,, % "Are you sure you want to close the GUI '" . this.name . "'?"
		IfMsgBox No
			return true
		return this.destroy() ; for example
	}
}
It might exist a simpliest solution (I have a poor tendency to make things more complicated... :facepalm: :headwall: ). Maybe someone think up something else.

Hope this helps.
my scripts
teadrinker
Posts: 4344
Joined: 29 Mar 2015, 09:41
Contact:

Re: Event(guiescape) call function problem in class

08 May 2019, 15:49

Maybe somehow like this:

Code: Select all

new TestClass()
return

class TestClass {
   __New() {
      static WM_SYSCOMMAND := 0x112
      Gui, New, +hwndhGui
      Gui, Show, x100 y100 w100 h100
      onClose := ObjBindMethod(this, "OnClose", hGui)
      OnMessage(WM_SYSCOMMAND, onClose)
   }
   
   OnClose(hGui, wp, lp, msg, hwnd) {
      static SC_CLOSE := 0xF060
      if (hGui = hwnd && wp = SC_CLOSE) {
         MsgBox, The script will be terminated!
         ExitApp
      }
   }
}
holahapi
Posts: 72
Joined: 09 Nov 2016, 21:52

Re: Event(guiescape) call function problem in class

10 May 2019, 09:30

A_AhkUser wrote:
08 May 2019, 15:14
depends on whether or not your class is intended to create many instances
For this time, I juse have one instance for the class, using class is because dont want messy up with other messsy codes.
A_AhkUser wrote:
08 May 2019, 15:14
The simpliest way I can think of with your specific requirement and how GuiClose label/function are designed is the following:
All the stuffs inside the class, it's perfect, thankyou very much.
A_AhkUser wrote:
08 May 2019, 15:14
(I have a poor tendency to make things more complicated... :facepalm: :headwall: )
It is because you are the AHK Master, normal person like me wont understand it easily. :D




teadrinker wrote:
08 May 2019, 15:49
Maybe somehow like this:
Thank you for your solution.
I just tested it, it works smoothly.
Althought it seems only allow one instance, but it fits for me this time.
Thank you~~
teadrinker
Posts: 4344
Joined: 29 Mar 2015, 09:41
Contact:

Re: Event(guiescape) call function problem in class  Topic is solved

10 May 2019, 10:00

holahapi wrote:it seems only allow one instance
No, it allows as much instances as you need:

Code: Select all

new MyGuiClass("First GUI", "x100 y100 w300 h100")
new MyGuiClass("Second GUI", "x500 y100 w300 h100")
Return

class MyGuiClass {
   WM_SYSCOMMAND := 0x112, SC_CLOSE := 0xF060
   
   __New(guiName, options) {
      this.guiName := guiName
      Gui, New, +hwndhGui, % guiName
      Gui, Show, % options
      this.closeObj := ObjBindMethod(this, "OnClose", hGui)
      OnMessage(this.WM_SYSCOMMAND, this.closeObj)
   }
   
   OnClose(hGui, wp, lp, msg, hwnd) {
      if (hGui = hwnd && wp = this.SC_CLOSE) {
         MsgBox, % "The " . this.guiName . " will be closed!"
         Gui, %hGui%: Destroy
         OnMessage(this.WM_SYSCOMMAND, this.closeObj, 0)
      }
   }
}
holahapi
Posts: 72
Joined: 09 Nov 2016, 21:52

Re: Event(guiescape) call function problem in class

12 May 2019, 22:49

teadrinker wrote:
10 May 2019, 10:00
No, it allows as much instances as you need
Wow, I didnt realize the parameter's part, I was too careless.
It is compact and undestandable, thank you!
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Event(guiescape) call function problem in class

12 May 2019, 23:11

Ideally,

Code: Select all

OnMessage(this.WM_SYSCOMMAND, this.closeObj, 0)
should be replaced by:

Code: Select all

OnMessage(this.WM_SYSCOMMAND, this.closeObj, 0), this.closeObj:=""
or something equivalent.
my scripts
teadrinker
Posts: 4344
Joined: 29 Mar 2015, 09:41
Contact:

Re: Event(guiescape) call function problem in class

13 May 2019, 17:51

Yes, also one could using something like this:

Code: Select all

this.Delete(Chr(0), Chr(0x10FFFF)) 
this.Delete(this.MinIndex(), this.MaxIndex())
this.SetCapacity(0)
this.base := ""
:)
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Event(guiescape) call function problem in class

13 May 2019, 18:52

teadrinker wrote:
13 May 2019, 17:51
It is what is called annihilate an object. :shock: :lol:
my scripts

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: mikeyww and 340 guests