Gui in a class

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: Gui in a class

17 Oct 2019, 23:31

Great examples, It helped me a lot.

Below is another nice example of a class gui.
The purpose is to have a Gui is a class that when typing in Control Edit_1, it copies the value of Edit_1 to Edit_3.
The purpose is to have an interactive Gui, if you click or modify some values, it will autofill some other controls to help the user.

A question, is it possible to Set the controlclass of a control?
if you use "Gui, Add, Edit" it sets the ClassNN always as Edit1, Edit2, Edit3, I would prefer more meaningfull names.
This way I would not need to save the hwnd's of the controls in an array (arrHandles) to acces them later.

Code: Select all

#NoEnv
#SingleInstance, Force
; Modification of examples of post https://www.autohotkey.com/boards/viewtopic.php?t=55952&start=20

MainGui := new GUI("Main", "Two Buttons ...", "+AlwaysOnTop")

MainGui.Show(50, 50)

return
Esc:: ; end of auto-execute section
ExitApp

;===============================================================================
class GUI { ; object oriented GUI structure
;===============================================================================
	
    __New(Name, WinTitle := "", Options := ""){ ; constructor
		
        static
		this.arrHandles := {}
		this.Name := Name
        Gui, % this.Name ":New", HWNDhGui, %WinTitle%
        Gui, +Labelmy +Resize %Options%
		
        Gui, Font, s16
		This.Add("Edit", "Edit_1", "w250",  "Edit_onTyping", "Hello, World!")
		This.Add("Button", "Button_1", "wp hp","Button_onClick", "1")
		This.Add("Button", "Button_2", "wp hp","Button_onClick", "2")
		This.Add("Edit", "Edit_3", "w250", "Edit_onTyping")
		This.Add("Edit", "Edit_4", "w250", "Edit_onTyping")
		
		 ; house keeping
        this.Handle := hGui
        this.WinTitle := WinTitle
        OnMessage(0x05, ObjBindMethod(this, "GuiSize")) ; WM_SIZE
    }
	
    __Delete(){
		Gui, % this.Name ":Destroy"
    }
	
    Show(x := "Center", y := "Center"){
        Gui, % this.Name ":Show", x%x% y%y%
    }
	
	GuiSize(wParam, lParam, msg, hwnd){ ; resize events	
        if this.Handle != hwnd
			return
		
        /* wParam = "event info"
			0: The window has been restored or dragged by its edges.
			1: The window has been minimized.
			2: The window has been maximized.
        */
		
        ; lParam = (width and height)
        w := lParam & 0xFFFF    ; low word  (bits 16..32)
        h := lParam >> 16       ; high word (bits  1..15)
		
        ToolTip, Resizing ...`n%w%`n%h%`n%wParam%
    }
	
    Edit_onTyping(hwnd, GuiEvent, EventInfo){
		
		if (A_GuiControl="Edit_1"){
			Tooltip, % "Trying to write @" outVar "@ in control Edit_3 on " this.Name
			hEdit_3 := this.arrHandles["Edit_3"] 
			GuiControlGet, outVar,, %hwnd% 
			GuiControl,, %hEdit_3%, %outVar%
		}
		else{
			GuiControlGet, outVar,, %hwnd%
			Tooltip, % "You are typing @" outVar "@ in Edit box on " this.Name " - " A_GuiControl
		}
    }
	
    Button_onClick(){
        Tooltip, % "You pressed button " A_GuiControl " on " this.Name
    }
	
	Add(ControlType:="Edit", Name_Control:="Edit1", Options:="", Function:="Edit_onTyping", Value:=""){
		static
		Gui, Add, %ControlType%, HWNDh%Name_Control% v%Name_Control% %Options%,%Value%
		Handle_Control := h%Name_Control%
		this.arrHandles[Name_Control]:=Handle_Control
		ControlHandler := ObjBindMethod(this, Function)
		GuiControl +g, %Handle_Control%, %ControlHandler%
	}
	
	GuiControlGet(cmd := "", value := ""){
		GuiControlGet, ov, %cmd%, % this.Handle, % value
		return ov
	}
	
	myClose(){      ; {Alt+F4} pressed, [X] clicked
		;myclose:      ;if any "myclose:" label is used outside this "class", a "duplicated" label found msgbox shows up!
		This.Delete()
		
		return
	}
	
} ; end of class
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

18 Oct 2019, 00:51

AHK_user wrote: A question, is it possible to Set the controlclass of a control?
No, you can't rename a control's class.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

18 Oct 2019, 05:35

AHK_user wrote:
17 Oct 2019, 23:31
Below is another nice example of a class gui.
Hi, ist your __Delete() ever called?
ciao
toralf
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: Gui in a class

18 Oct 2019, 10:44

toralf wrote:
18 Oct 2019, 05:35
AHK_user wrote:
17 Oct 2019, 23:31
Below is another nice example of a class gui.
Hi, ist your __Delete() ever called?
In the function myClose()
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

18 Oct 2019, 12:57

No, in your code __Delete() is never called. You could check it by adding MsbBox into __Delete():

Code: Select all

    __Delete(){
        MsgBox, __Delete()
		Gui, % this.Name ":Destroy"
    }
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: Gui in a class

19 Oct 2019, 04:41

Thanks for pointing that out :)

Actually, even the myClose function was not called...

Here is an improved updated version,
I have added parameters to the Add function for statusbar and tooltips for the controls :D .
It works quite good, except the tooltip of the combobox seems to be freezing when trying to select the options.

Code: Select all

#NoEnv
#SingleInstance, Force
; Modification of examples of post https://www.autohotkey.com/boards/viewtopic.php?t=55952&start=20

MainGui := new GUI("Main", "Gui1", "+AlwaysOnTop")
MainGui2 := new GUI("Main2", "Gui2", "+AlwaysOnTop")
MainGui.Show(50, 50)
MainGui2.Show(500, 50)
return
Esc:: ; end of auto-execute section
ExitApp

;===============================================================================
class GUI { ; object oriented GUI structure
;===============================================================================
	
    __New(Name, WinTitle := "", Options := ""){ ; constructor
		
        static
		this.arrHandles := {}
		this.arrTooltip := {}
		this.arrStatusbar := {}
		This.Controls := []
		this.Name := Name
		this.WinTitle := WinTitle
		
		; Building the Gui
        Gui, % this.Name ":New", HWNDhGui, %WinTitle%
		this.Handle := hGui
        Gui, +Labelmy +Resize %Options%
		
        Gui, Font, s16
		This.Add("Edit", "Edit_1", "w250",  "Edit_onTyping", "Hello, World!", "Status:Edit_1", "The content of Edit_1 will be copied to Edit_2")
		
		This.Add("ComboBox", "ComboBox_1", "wp r10","Edit_onTyping", "file:delete_material|file:get_cur_material|file:list_materials|file:load_material_file", "Combo statusbar", "Combo Tooltip")
		This.Add("Text", "Text_3", "w250", "Edit_onTyping", "test", "Text Statusbar", "Tooltip text")
		This.Add("Edit", "Edit_2", "w250", "Edit_onTyping", "", "Status:Edit_2", "This tooltip is displayed afther 0 msec.", "0")
		This.Add("Button", "Button_1", "wp hp","Button_onClick", "Send", "Press this button", "Press this button to display a msgbox.", "0")
		Gui, Add, StatusBar,, 
		
		; house keeping
        OnMessage(0x05, ObjBindMethod(this, "WM_SIZE")) ; WM_SIZE
		OnMessage(0x112, ObjBindMethod(this, "WM_SYSCOMMAND"), "1") ; WM_SYSCOMMAND
		OnMessage(0x200, ObjBindMethod(this, "WM_MOUSEMOVE"), "1") ; WM_MOUSEMOVE
    }
	
	Edit_onTyping(hwnd, GuiEvent, EventInfo){ ; Handling of Edit events
		
		if (A_GuiControl="Edit_1"){
			hEdit_2 := This.Controls["Edit_2", "Handle"]
			GuiControlGet, outVar,, %hwnd% 
			GuiControl,, %hEdit_2%, %outVar%
		}
    }
	
    Button_onClick(){ ; Handling the Buttons
        MsgBox, % "You pressed button " A_GuiControl " on " this.Name
    }
	
    Show(x := "Center", y := "Center"){
        Gui, % this.Name ":Show", x%x% y%y%
    }
	
	Add(ControlType:="Edit", Name_Control:="Edit1", Options:="", Function:="Edit_onTyping", Value:="", StringStatusBar:="", StringTooltip:="", DelayTooltip:=500){
		static
		Gui, Add, %ControlType%, HWNDh%Name_Control% v%Name_Control% %Options%,%Value%
		Handle_Control := h%Name_Control%
		
		This.Controls[Name_Control, "Handle"]:=Handle_Control
		This.Controls[Name_Control, "StatusBar"]:=StringStatusBar
		This.Controls[Name_Control, "Tooltip"]:=StringTooltip
		This.Controls[Name_Control, "TooltipDelay"]:=DelayTooltip		
		ControlHandler := ObjBindMethod(this, Function)
		GuiControl +g, %Handle_Control%, %ControlHandler%
	}
	
	GuiControlGet(cmd := "", value := ""){
		GuiControlGet, ov, %cmd%, % this.Handle, % value
		return ov
	}
	
	Delete(){
		Gui, % this.Name ":Destroy"
    }
	
	WM_MOUSEMOVE(wParam, lParam, msg, hwnd){
        ; Run when the mouse is moving,  this function is activated
		static
		
		if (this.Name != a_gui) {
			return
		}
		
		StringStatusBar := This.Controls[A_GuiControl, "Statusbar"]
		SB_SetText(StringStatusBar)
		
		MouseGetPos, , , WhichWindow, Curr_Control, 2
		
		If (Curr_Control != Prev_Control){
			Prev_Control := Curr_Control
			StringTooltip := This.Controls[A_GuiControl, "Tooltip"]
			TooltipDelay := This.Controls[A_GuiControl, "TooltipDelay"]
			TooltipCounter := A_TickCount
		}
		else{
			
			if(Curr_Control=""){
				ToolTip,
			}
			else if(A_TickCount-TooltipCounter>TooltipDelay){
				ToolTip,  % StringTooltip
			}
		}
		
    }
	
	WM_SIZE(wParam, lParam, msg, hwnd){ ; resize events	
        if this.Handle != hwnd
			return
		
        /* wParam = "event info"
			0: The window has been restored or dragged by its edges.
			1: The window has been minimized.
			2: The window has been maximized.
        */
		
        ; lParam = (width and height)
        w := lParam & 0xFFFF    ; low word  (bits 16..32)
        h := lParam >> 16       ; high word (bits  1..15)
		
        ToolTip, Resizing ...`n%w%`n%h%`n%wParam%
    }
	
	WM_SYSCOMMAND(wParam, lParam, msg, hwnd){
		
		static SC_CLOSE := 0xF060
		if (wParam = SC_CLOSE && this.Handle = hwnd) { ; fired when closing the Gui
			MsgBox, Closing Gui %A_Gui%
			This.Delete()
		}
		return
	}
	
} ; end of class
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Gui in a class

19 Oct 2019, 18:49

toralf wrote:
16 Oct 2019, 23:30
While reading the docs, I came across __CAll(). This would be an alternative approache to callback function.
__Call enables the object itself to be called, as in %obj%() or x := {y: obj}, x.y() (with x being the first parameter in that case).

If you pass the object to GuiControl +g, SetTimer, Hotkey, etc. (or do the above with v2), the object's Call method is used instead.

However, rather than this.callback(hEdit), you could just as easily call this.callback.anyOtherMethod(hEdit). You'd just have to avoid IsFunc when the object is not a Func.

If you were to pass the dialog itself to the EventHook for it to later call a method of the dialog, that would introduce a circular reference, which would defeat the point of separating EventHook from the dialog.

If you call this.callback(hEdit) and this.callback is a Func, the first parameter will be this, and the second will be hEdit. To pass only hEdit, you may use func := this.callback, %func%(hEdit) or this.callback.call(hEdit).
toralf wrote:
17 Oct 2019, 13:25
Hmmm, thanks a lot, but I”m not a [huge] fan of “while sleep”
Functions like MessageBox (the system function used by MsgBox) work by entering a "modal message loop", where they wait for the next message to arrive on the thread, handle it if it pertains to the dialog or just dispatch it to its destination, then repeat. Once the dialog is closed by some means, the loop breaks.

"While sleep" is not much different, but there is a more suitable method: WinWaitClose.

I suppose there are multiple ways one could get the dialog's answer:
  • Have the dialog wait until it is closed before returning its answer.
  • Have the answer passed to a callback function that you specify.
  • Have the answer stored somewhere you specify (a variable or object).
  • Retrieve the answer from the dialog itself.
Since you've gone with the class instance model, I think it makes more sense to retrieve the answer from the dialog itself than to have the dialog store the answer in some other object or variable. You could store the answer back into the dialog instance, but there's no need: it's already in the dialog's control. Just don't destroy the dialog until the caller is done with it (you can even give the option of showing the same dialog repeatedly).

If you're waiting for the dialog to close before retrieving the answer, it makes sense to wrap that into a function or method (like MsgBox, InputBox, FileSelectFile, etc.).

Code: Select all

answer := Dialog("How are you?")
MsgBox, % answer
ExitApp

Dialog(Question) {
    dlg := new Dialog(Question)
    return dlg.Wait()
}

class Dialog
{
    __New(Question) {
        Gui, New, +hwndhGui +LabelDialog.static_, Dialog
        this.hwnd := hGui
        Gui, Margin, 10, 10
        Gui, Add, Text,, % Question
        Gui, Add, Edit, w200 h100 hwndhEdit
        this.hEdit := hEdit
        Gui, Add, Button, +hwndhButton x+-99 y+5 w100 h24 gCancel, Send Answer
        Gui, Show
    }
    
    static_Close() {
        MsgBox, 4, % " ", Do you want to close the window?
        IfMsgBox, No
            Return 1
    }
    
    Answer {
        get {
            GuiControlGet, value,, % this.hEdit
            return value
        }
        set {
            GuiControl,, % this.hEdit, % value
            return value
        }
    }

    Wait() {
        dhw := A_DetectHiddenWindows
        DetectHiddenWindows, Off
        WinWaitClose, % "ahk_id " this.hwnd
        DetectHiddenWindows, % dhw
        return this.Answer
    }

    __Delete() {
        Gui, % this.hwnd ":Destroy"
    }
}
The previous two examples by teadrinker retrieved the control's contents when the GUI is closed, but then did nothing with them (actually returned them to the message monitor, which would have no effect if they are not integers). This one does not distinguish between closing the GUI window and clicking the button.

+LabelDialog.static_ is a bit of a cheat. It relies on the undocumented fact that methods are registered as global functions, with the class name and method name delimited by .. The corresponding script function is called with the usual parameters for a GUI event; i.e. this is a HWND, not an object. Given that the Gui command can be very awkward and has already been replaced in AutoHotkey v2, I think it's acceptable to use hacks like this with Gui. Alternatively, you could move the method outside the class and (for example) call it Dialog_static_Close instead of Dialog.static_Close.

Since I didn't need to do anything more than close when the button was clicked, I used gCancel. Otherwise, something like gDialog.static_Button would work like static_Close. If it needs to refer to the GUI object, it probably needs to be a bound function set with GuiControl +g.

One way to avoid circular references is to "register" the GUI HWND and object, allowing an object to be retrieved via its HWND. For as long as the window exists, the object should also exist. When the window is destroyed, the object is released.

AutoHotkey does this with its own GUI structs in v1 (which may also be assigned a unique name or number), or GUI objects in v2 (but with some reference counting hacks).

If you want the GUI to be destroyed automatically when the script is no longer referencing the object, the reference in the GUI list must not be counted. The easiest way to do that is to store the object's address instead of a reference, and use Object(address) to get a reference. Just make sure to delete it when __Delete is called.

Another way is to register the GUI when it is shown, and unregister the GUI when it is hidden. If the GUI is still visible, the user can interact with it and potentially trigger event callbacks (if your GUI object supports that). Even if the script doesn't have a direct reference to the GUI object, it can be given one when the callback is called. But if the GUI is hidden and the script has no direct references to it, the script probably won't be using the GUI anymore so it should be destroyed and deleted.

For examples, see DebugVars.ahk. The simplest one is probably VarEditGui - in particular, see Show() and RevokeHwnd(). VarEditGui can be used standalone.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Gui in a class

19 Oct 2019, 18:50

Odlanir wrote:
17 Oct 2019, 12:00
It seems the __Call is called even if a method is in the constructor of the class:
"Meta-functions define what happens when a key is requested but not found within the target object."

The target object is an instance of the class, whereas the method is defined in the class itself, not the instance.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

19 Oct 2019, 23:45

Thanks a lot Lexikos for the detailed answer and links. I’ll have to study them. It seems to fulfill what I want to achieve.Now I have to understand what all the functions do to know where I can modify them to my needs.
ciao
toralf
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: Gui in a class

20 Oct 2019, 00:08

Great example, Lexicos!

The only confusing part of the example is that the name of the gui and the name of the classname are the same.
It confused me when changing +Label option:
so +LabelDialog refers to +Label%ClassName%.static_

class GuiBuilder
{
__New(Question) {
Gui, New, +hwndhGui +LabelGuiBuilder.static_, Dialog
this.hwnd := hGui
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

20 Oct 2019, 00:42

lexikos wrote: One way to avoid circular references is to "register" the GUI HWND and object, allowing an object to be retrieved via its HWND.
Could you give an example, please?
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

20 Oct 2019, 02:53

Good morning teadrinker,
I think he did, in the VarEditGui class, he used the technique:

Code: Select all

VarEditGui.Instances[this.hGui] := this
ciao
toralf
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

20 Oct 2019, 03:13

Good morning @toralf, thanks!
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

20 Oct 2019, 03:17

lexikos wrote:
19 Oct 2019, 18:49

Code: Select all

    Answer {
        get {
            GuiControlGet, value,, % this.hEdit
            return value
        }
        set {
            GuiControl,, % this.hEdit, % value
            return value
        }
    }
Why have you specified set for Answer? IMHO it is never used nor needed.

lexikos wrote:
19 Oct 2019, 18:49
For examples, see DebugVars.ahk. The simplest one is probably VarEditGui - in particular, see Show() and RevokeHwnd(). VarEditGui can be used standalone.
Thanks, for a tip. I looked at the code. AFAIU
  • one has to specify callback functions via ed.OnSave to get the values back from the gui, correct?
  • this.SetVar(this.Var) only sets the original value again into the Gui
ciao
toralf
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

20 Oct 2019, 10:21

Ok, I understood the concept. When a gui controls function gets called, it doesn't get the object as this. But it has A_Gui and with it it can retrieve the object if the object ist stored in itself. But if the storage space is not cleared when the Gui closes, __Delete() gets never called.

What troubled me was that the gui controls function gets called it doesn't get the parameters as written in the docs:
CtrlEvent(CtrlHwnd, GuiEvent, EventInfo, ErrLevel:="")
instead it only receives CtrlEvent(GuiEvent, EventInfo). But since A_Gui, A_GuiControl, A_GuiEvent and A_EventInfo are available too, all info is available.

This is my modified and shorted code. It works, and I think I can achieve now what I need. Thanks a lot to all of you for the great help and explanation.

Code: Select all

answer := Dialog("How are you?", "good")
MsgBox, % "you answered: " answer
ExitApp

Dialog(Question, DefaultValue := "") {
    return new Dialog(Question, DefaultValue).Wait()
}
class Dialog
{
    __New(Question, DefaultValue) {
        Gui, New, +hwndhGui +LabelDialog.On_, Dialog
        this.hwnd := hGui
        Gui, Add, Text,, % Question
        Gui, Add, Edit, w200 h100 hwndhEdit, %DefaultValue%
        this.hEdit := hEdit
        Gui, Add, Button, gDialog.On_ButtonSendAnswer, Send Answer
        this.SaveStatus := False
        Gui, Show
        Dialog.Instances[hGui] := this
    }
    
    On_Close() {
        MsgBox, 4, % " ", Do you want to close the window?
        IfMsgBox, No
            Return 1
        Dialog.RemoveInstance(A_Gui)
    }

    On_ButtonSendAnswer() {
        this := Dialog.Instances[A_Gui]
        this.SaveStatus := True
        Dialog.RemoveInstance(this.hwnd)
        Gui, Cancel
    }
 
    RemoveInstance(hwnd) {
        Dialog.Instances.Delete(hwnd)
    }
 
    Wait() {
        dhw := A_DetectHiddenWindows
        DetectHiddenWindows, Off
        WinWaitClose, % "ahk_id " this.hwnd
        DetectHiddenWindows, % dhw

        If !this.SaveStatus
          Return "not saved"
        GuiControlGet, value,, % this.hEdit
        return value
    }

    __Delete() {
        Gui, % this.hwnd ":Destroy"
    }
}
ciao
toralf
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

20 Oct 2019, 10:23

toralf wrote: Why have you specified set for Answer? IMHO it is never used nor needed.
It is used here:

Code: Select all

    Wait() {
        dhw := A_DetectHiddenWindows
        DetectHiddenWindows, Off
        WinWaitClose, % "ahk_id " this.hwnd
        DetectHiddenWindows, % dhw
        return this.Answer ; <— this launches Answer::Get
    }
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Gui in a class

20 Oct 2019, 22:39

The GUI does not have a name. +Label sets the prefix to use when searching for event handling labels/functions. Like I said, the example relies on the method name being automatically prefixed with the class name.

The setter is present for symmetry, and because if someone tried to set it and there was no setter, it would get overwritten and stop working, but have no visible effect on the GUI.

InputBox has a Default parameter that I use frequently. This may serve the same purpose, in theory.

You're probably not accounting for the "this" parameter. If you use a method directly as a control callback, "this" would contain the hwnd.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

21 Oct 2019, 10:34

lexikos wrote:
20 Oct 2019, 22:39
You're probably not accounting for the "this" parameter. If you use a method directly as a control callback, "this" would contain the hwnd.
In on_Close() and On_ButtonSendAnswer() this didn’t contain the hwnd. And also not the object this, so that this.hwnd could be used. Instead A_Gui contained the hwnd of the GUI.
But maybe I do not understand what you mean by “accounting” or “contain the hwnd”.
ciao
toralf
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Gui in a class

21 Oct 2019, 11:19

@toralf
An example:

Code: Select all

inst := new MyGui

class MyGui
{
   __New() {
      Gui, Add, Button, hwndhButton gMyGui.On_Button, Click to see THIS
      Gui, Add, Text,, % "Button HWND: " . hButton
      Gui, Show, w300 h100
   }
   
   On_Button() {
      MsgBox, % "This: " . Format("{:#x}", this)
   }
}
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Gui in a class

21 Oct 2019, 12:03

Thanks teadrinker, so it is the hwnd of the button (ControlHwnd)
That explains why the contolHwnd is missing in the parameters.
But what I need is the hwnd of the GUI. Since the object is registered with the hwnd of the GUI
ciao
toralf

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 121 guests