[Library] GuiVar - Use Gui as Variable Between AHK Scripts

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

04 Nov 2014, 17:04

tzucker wrote:What is my library folder? I have GuiVar in the same folder with my scripts. I use AHK Startup to put them all together, GuiVar is one of the scripts that AHK Startup runs.
http://ahkscript.org/docs/Functions.htm#lib

The library fold is one of three places that you put a function library script.
  • %A_ScriptDir%\Lib\ ; Local library - requires AHK_L 42+.
    %A_MyDocuments%\AutoHotkey\Lib\ ; User library.
    path-to-the-currently-running-AutoHotkey.exe\Lib\ ; Standard library.
You need to put the GuiVar.ahk script in one of these three locations. If there is not already a Lib folder at the location then you have to create the Lib folder. Then any of your scripts will be able to use the GuiVar functions automatically without having to define them in the scripts. Any function that you want all your scripts to be able to use can be put in a function library script and placed in a proper library location. The library functions become almost the same as if they were functions built-in to AHK. It is a way of extending AHK and adding your own custom functions to AHK.

Simple running GuiVar.ahk at startup will not work. There is rarely ever a reason to actually run a script that contains nothing but function definitions like a function library script. The script will just run and terminate without really doing anything.

FG

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

04 Nov 2014, 17:47

Thanks. I tried just putting the script in the same folder that ahk is in. I will create a lob folder and put it there tomorrow.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

04 Nov 2014, 21:23

I put the guivar script in the ahk directory \lib so its path is C:\Program Files (x86)\AutoHotkey\Lib\GuiVar.ahk. I tried running Script_one.ahk above and got this error:
scriptone error with guivar.PNG
Screenshot of error with Script_one.ahk
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 02:30

tzucker wrote:I put the guivar script in the ahk directory \lib so its path is C:\Program Files (x86)\AutoHotkey\Lib\GuiVar.ahk. I tried running Script_one.ahk above and got this error:
You need to download the newest version of AHK from this website:
http://ahkscript.org/download/

You probably have an old version that you downloaded from autohotkey.com. Unfortunately that website has been pretty much abandon by any developers and the version you can download from there is over 5 years old and very very outdated.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 09:36

I downloaded the latest stable version (32 bit). After putting the GuiVar.ahk file in the newly created lib directory in the new install all errors are gone - thanks! :clap: Now I am left with one problem - the variables still are having trouble. Here is a screen shot of the out put of Script_two (after running script_one):
output - script 2.PNG
output from msgbox in script two - see code I copied from FG post
output - script 2.PNG (6.5 KiB) Viewed 6445 times
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 11:32

Now I'm not sure what the problem is. I installed the new version over the old version on another computer and the script works perfectly (after I tweaked it to take into account some one like me picking a drive instead of a folder), but on this machine it doesn't work - still get same weird output.

The revised Script_one is the following

Code: Select all

; **************************************************************
; ***** Script to set path and File variables to be shared *****
; **************************************************************
#v:: ; assign [WIN}+v to start script
	FileSelectFolder, MyFolder,,6,Select a Destination Folder for the extracted message ; ask for preferred destination folder
	MyFile = %A_Year%%A_MM%%A_DD%_%A_Hour%%A_Min% ; variable contains yyyymmdd_hhmm
	basefilename = %MyFolder%\%MyFile%
; **************************************************************
; ***** Determine if chosen directory is folder or drive   *****
; ***** If it is a directory put extra \ in, else not      *****
; **************************************************************
	slashes = \\
	ifInString basefilename, %slashes%
	{
		basefilename = %Myfolder%%MyFile%
        }
	Else
	{
		Basefilename = %MyFolder%\%MyFile%
	}
; **************************************************************
	Destination = %basefilename%.txt ; destination is the selected folder ":\" followed by today's date and time
	; **************************************************************
	; ***** GuiVar is a script by FanaticGuru of AHKScript.org *****
	; **************************************************************
	GuiVar_Set("SelectedFolder", MyFolder)
	GuiVar_Set("NowText", MyFile)
	GuiVar_Set("BaseFileName", basefilename)
	GuiVar_Set("Destination", Destination)
return
The script_two now works as expected on my other win 7 x64 box, but not this one.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 11:37

it has something to do with the AHK Startup script. That is the only difference between the two systems. When I exit that script and just start script_one and Script_two by themselves, there is no problem - everything works.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 11:42

Now I think it has something to do with the other scripts that are running. I didn't use AHK Startup, but instead just started all the scripts. The result is that I am getting the same erroneous output. So with only script_one and script_two running everything is okay, if I run all my scripts back to bad output. I will try running one other at a time to see which one is the culprit.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 11:49

Maybe I am wrong - All the scripts are running but the output is fine now. Could the order be a problem? I will try again with AHK Startup.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 11:51

tried AHK Startup again and had same problem.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 12:11

with just the 3 scripts running everything is okay (script_one, script_two, backup). I am now changing the running scripts to be setvar (to take place of script_one to set variables) and backup (will retrieve the vars it needs and backup the database).
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 12:16

the two script setvar and backup are working fine.
Tom Zucker-Scharff
An AutoHotKey Newbie
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 12:20

Dude. There's an edit button under your post. Please USE IT instead of spamming with 20 different posts.

Edit: Image of bottom right of post: Image
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 12:48

As I am sure you are aware there were not 20 posts after the last post by FG. When posting from a phone it is hard enough to read the last post and reply without scrolling around for the edit button. I have used the edit button and although I may be rather new to AHK, I have been a member of various forums, as well as an admin, for at least 15 years if not more.

If I think the reply is faster with a new post I take that route. If you feel so strongly about it I will take your opinion into account the next time I post. And since you would like to join in, feel free to offer any advice you feel would improve the script. I don't think I need to repost the code it is at the beginning of this thread, although it has changed significantly since then.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 14:10

tzucker wrote:it has something to do with the AHK Startup script. That is the only difference between the two systems. When I exit that script and just start script_one and Script_two by themselves, there is no problem - everything works.
I would imagine that it is not AHK Startup per say but some other script you are running besides the two example scripts I posted. Those other scripts probably also contains GuiVar_Set and are changing the values of the GuiVar "SelectedFolder", "NowText", and "BaseFileName". The reason GuiVar "Destination" is probably not being messed up is you did not have that GuiVar in your original script I looked at and I added it just for illustration purposes. So that GuiVar name is probably not in your other scripts you have running and is not being messed up by your other scripts for my two example scripts.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 14:16

I was being hyperbolic with my "20", I know. It sounds to me like you might like our live IRC channel
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

05 Nov 2014, 14:47

FG:

I had already thought about the solution you just provided and did indeed find one script with one of the vars in it. I am changing all the scripts to get the GuiVar version and then use a local differently named version.

GD:

I've been on the IRC and did receive some help from 2 members there (nothing in comparison to here). But most of the time the IRC is just peeps hanging out talking about something else completely. Although sometimes interesting, When the inside jokes you don't know are not in the majority, it doesn't fulfill my need for actual help. When people there do help they usually post code that is over my head or tell me to post my code via the link which I already did - all in all frustrating.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

06 Nov 2014, 14:37

If I should start a new topic with this let me know.

Now I have the various scripts seemingly working. I have the small problem of scripts having to be executed in a certain order in order to get the initial variables to pass from one to the other. Sometimes I only need to do a backup, sometimes I will do more. So I would like to have the script include a script I call setvar.ahk which sets the various variables with some user input. But when I put an include statement in the script seems to stop executing after the include - as if it went to the setvar script and never returned. I have a return statement at the end of that script, do I need more?

The setvar script is as follows:

Code: Select all

; **************************************************************
; ***** Script to set path and File variables to be shared *****
; **************************************************************
#v:: ; assign [WIN}+v to start script
	FileSelectFolder, MyFolder,,6,Select a Destination Folder ; ask for preferred destination folder
	MyFile = %A_Year%%A_MM%%A_DD%_%A_Hour%%A_Min% ; variable contains yyyymmdd_hhmm
	basefilename = %MyFolder%\%MyFile%
; **************************************************************
; ***** Determine if chosen directory is folder or drive   *****
; ***** If it is a directory put extra \ in, else not      *****
; **************************************************************
	slashes = \\
	ifInString basefilename, %slashes%
	{
		basefilename = %Myfolder%%MyFile%
	}
	Else
	{
		Basefilename = %MyFolder%\%MyFile%
	}
    ; **************************************************************
	Destination = %basefilename%.txt ; destination is the selected folder ":\" followed by today's date and time
	; **************************************************************
	; ***** GuiVar is a script by FanaticGuru of AHKScript.org *****
	; **************************************************************
	GuiVar_Set("SelectedFolder", MyFolder)
	GuiVar_Set("NowText", MyFile)
	GuiVar_Set("BaseFileName", basefilename)
	GuiVar_Set("Destination", Destination)
return
The backup script with the include is:

Code: Select all

; ------------------------------------------------------------------------------------------------------------------------------
; ----- This script performs the following actions                                                                         -----
; -----                                                                                                                    -----
; -----     1. Sets the title matching mode for a partial beginning string                                                 -----
; -----     2. Checks for the existence of the window for EndNote X7 -, then activates that window                         -----
; -----     3. Isolates and puts in a variable the name of the open library                                                -----
; -----     4. Backs up the current library to an endnote library folder                                                   -----
; -----     5. Names the backup file (with extension .enlx) with today's date and time and the name of the library         -----
; -----                                                                                                                    -----
; ------------------------------------------------------------------------------------------------------------------------------
; -----                                                                                                                    -----
; -----                                This script was written by Thomas Zucker-Scharff                                    -----
; -----                                                                                                                    -----
; ------------------------------------------------------------------------------------------------------------------------------
Return

#b:: ; assign [Win]+b to backup script
MsgBox, Have you opened your library yet, if not please do so, then click Okay.
#include d:\dropbox\ahk\setvar.ahk
; *********************************************************
; ***** get shared variables using GuiVar library     *****
; *********************************************************
	MyFolder := GuiVar_Get("SelectedFolder")
	MyFile := GuiVar_Get("NowText")
	BaseFileName := GuiVar_Get("BaseFileName")
	Destination := GuiVar_Get("Destination")
; *********************************************************
datetime = %A_Year%%A_MM%%A_DD%_%A_Hour%%A_Min%
SetTitleMatchMode,1 ; title must begin with String
IfWinExist,EndNote X7 - ; Endnote must have a library open to display the - after the title name
{
   WinActivate
   WinGetActiveTitle, title
   mytitle:=substr(title, instr(title, "["), -5) ; -5 gets rid of ".enl]"is to end of line
   libname:=substr(mytitle, 2) ; basename of library
   CompressedFileName = %datetime%_%libname% ; get GuiVar variable basefilename and put into variable destination
   MsgBox % "MyFolder`t`t = " MyFolder "`nMyFile `t`t = " MyFile "`nBaseFileName `t = " BaseFileName "`nDestination `t = " Destination "`nCurrent datetime `t = " datetime "`nBase Library name `t = " libname "`nCompressed file name `t = " CompressedFileName
   Send !f ; send alt f to access the File menu
   Send {UP 2} ; send 2 up keystrokes to access the compressed file function
   Send {ENTER} ; send enter key to choose function
   Send {ENTER} ; send the enter key to continue with no changes
   sleep 1000
   Send %CompressedFileName%
   Send {ENTER}
}
else
	MsgBox, Please open One Library, No Open Library was found or more than one library is open. Please rectify the situation and rerun the script.
It should be noted that I also had to redeclare the date/time because when I put it in a variable it does not get changed each time I rerun the script. I will probably rewrite the seetvar script to not include that as a variable to be passed.
Tom Zucker-Scharff
An AutoHotKey Newbie
User avatar
Relayer
Posts: 160
Joined: 30 Sep 2013, 13:09
Location: Delaware, USA

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

06 Nov 2014, 15:02

I have been fascinated by classes and look for every opportunity to put another one together. I was intrigued by FG's use of a hidden Gui for cross communication between scripts. Well, here is the functionality in the form of a class. It may or may not be useful, but the more I worked with it, the more I liked it, so I thought I'd share. The level of complexity is higher at the code level but should make using this functionality more natural (er, I think :eh: ) and it enforces some discipline in defining shared variables.

Put the class and the two demo scripts in the same directory and run script#1.ahk. It will automatically start script#2.ahk and then run through a demonstration of the capabilities. Read the class documentation header first to get a primer.

Let me know what you think. -Relayer

Code: Select all

/*
Class GuiVar
class by: Relayer
inspired by: Fanatic Guru's LIBRARY that uses hidden Gui windows to pass information between scripts.

Features:
 - all variables are instantiated by each script before use
 - syntax for variable use is much like that of objects: [variable name].value
 - a given variable must use the same name in all scripts accessing that variable
 - all variables are bi-directional - can be written and read by all participating scripts
 - each variable has but one owner called the server... the first instantiation
 - a variable must be known to exist before instantiation as a client... use poll() to check
 - each participating script can have both server (owned) variables and client variables
 - can set up notifications to flag instantiation of a server variable owned by another scipt
 - can set up notification when a variable has a specific content or simply changes
 - notification is by a call to either a label or to a user function
 - notification timer only runs when needed for pending notifications

Remarks:
	The beauty of this class is that multiple scripts can share variables by using the same class.
	Each script will have its own instance of the class which will manage which variables are
	owned and manage which variables are simply used by the others.  The instances of each
	script's class is normalized by the common variable name and the HWND of the hidden Gui
	that holds the variable's contents.
 
Methods:
__New(varName, varValue = "null")
	Used to instantiate a variable.  A server script is the owner of a variable and can instantiate
	variables at any time.  Client scripts use variables and instantiate them once they are known
	to exist.  In other words, this method makes the first instantiation of a variable the server
	copy and all others are set to client.

__Set(a, b)
__Get(a)
	These two methods are used internally.  They enforce the management of the key designated
	to hold the contents or value of a variable.  The default for the key is ".value".  This can
	be changed by modifying the class variable GuiVar.keyForVariableContent

_set(varValue)
_get()
	These two methods are for internal use... do not use.
	
list()
	Returns an object of all instantiated variables as keys and their contents.
	
poll(varName)
	Returns true if the variable has been instantiated by a server script and is now ready to
	be instantiated by a client script for use.
	
destroy()
	Destroys an instantiated variable.  Destroying a server variable (by its owner) will invoke
	an error in client scirpts using that variable name.  Destroying a client variable has no
	effect on other scripts and simply unregisters that variable for use by that client script.
	
_hwndList()
	Returns an object containing all Gui names as keys and their HWND.  Used internally.

notifyOnGuiVarAvailable(varName, notifyService)
	Used by scripts to set automatic notification of the instantiation of a variable by another
	script designed to be the owner of that variable.  This method will instantiate the client
	version of the variable and then call the given notifyService which can be a label or a
	function name. NOTE: notification needs a "Return" by the host to complete the transaction.
	
setOnGuiVar(service, triggerOnContent = "", frequency = 1)
	Used by either server or client scripts to notify when a variable changes where:
	- service = the label or function name to call
	- triggerOnContent = "" for any change in contents or set to a specific contents
	- frequency is decremented on each notification and disables notification when = zero.
	- NOTE: notification needs a "Return" by the host to complete the transaction.
	
getOnGuiVar()
	Retrieves the class object for this variable from GuiVar.onGuiVar for inspection.

------------------------------------------

class member keys of interest:
	[varName].value is the default contents of a variable; change by writing to GuiVar.keyForVariableContent
	[varName].relationship returns either "server" or "client" from the script's perspective


Limitations:
 1) A script serving a variable does not have a simple method for determining if there is a
	client using that variable.  A dialog needs to take place between the scripts.
 2) Since the class will and its timer routine are instantiating Gui's there may be a need
	for a using script to do a "Gui, [guiName]:Default" to return to its captive Gui
 3) Every effort has been made to avoid race conditions since multiple scripts will be
	running asynchronously.
*/



/*
Class initialization
*/
GuiVar_Class()
{
	SetTimer, GuiVarTimer, 100
	SetTimer, GuiVarTimer, Off
	Return
}

/*
Class
*/
Class GuiVar
{
	static onGuiVar := Object()
	static keyForVariableContent := "value"
	static GuiVarTimerState := "off"
	
	
	__New(varName, varValue = "null")
	{
		Critical, On
		this.varName := varName
		this.guiID := "GuiVar_" . varName
		this.relationship := "server"
		for key, GuiHWND in this._hwndList()
			if (key = varName)
			{
				this.relationship := "client"
				this.hwnd := GuiHWND
				GuiVar.onGuiVar[this.guiID] := Object()
				GuiVar.onGuiVar[this.guiID].hwnd := this.hwnd
				;a client instantiation can write a value to the variable
				;text 'null' allows user to initialize to "" to clear the variable
				;otherwise it will remain with the value set by the server of that variable
				if (varValue != "null")
					this[GuiVar.keyForVariableContent] := varValue
				Break
			}
		;the first instantiation of a variable will be a server variable
		;client variables must be instantiated after the server version
		if (this.relationship = "server")
		{
			guiID := this.guiID
			Gui, %guiID%:New, +hwndGuiHWND
			Gui, %guiID%:Add, Text,, % ((varValue = "null") ? ("") : (varValue))
			Gui, %guiID%:Show, Hide, %guiID%
			this.hwnd := GuiHWND
			GuiVar.onGuiVar[this.guiID] := Object()
			GuiVar.onGuiVar[this.guiID].hwnd := this.hwnd
		}
		Critical, Off
	}
	
	__Set(a, b)
	{
		if (a = GuiVar.keyForVariableContent)
		{
			;variable name must be registered with the class object
			if (GuiVar.onGuiVar.Haskey(this.guiID))
			{
			Critical, On
				this._set(b)
				;prevent triggering on change initiated by same script waiting for trigger
				;this lets the trigger condition be set up before the contents of a
				;shared variable is written to by the same script
				;i.e. trigger must come from an external source
				GuiVar.onGuiVar[this.guiID].watchValue := b
			Critical, Off
				Return
			}
			else
			{
				Msgbox %  "error: " . this.varName . " not instantiated"
				Return
			}
		}
	}
	
	__Get(a)
	{
		if (a = GuiVar.keyForVariableContent)
		{
			;variable name must be registered with the class object
			if (GuiVar.onGuiVar.Haskey(this.guiID))
				Return this._get()
			else
			{
				Msgbox %  "error: " . this.varName . " not instantiated"
				Return
			}
		}
	}
	
	_set(varValue)
	{
		Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
		DetectHiddenWindows, On
		guiID := this.guiID
		Hwnd := this.hwnd
		ControlSetText,, %varValue%, ahk_id %Hwnd%
		DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
		if (ErrorLevel)
		{
			Msgbox % "error: " . this.varName . " not found"
			Return False
		}
		Return True
	}
	
	_get()
	{
		Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
		DetectHiddenWindows, On
		Hwnd := this.hwnd
		ControlGetText, value,, ahk_id %Hwnd%
		DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
		if (ErrorLevel)
		{
			Msgbox % "error: " . this.varName . " not found"
			Return False
		}
		Return value
	}
	
	list()
	{
		Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
		DetectHiddenWindows, On
		result := Object()
		for key, Hwnd in this._hwndList()
		{
			ControlGetText, value,, ahk_id %Hwnd%
			if (ErrorLevel)
			{
				result := "error: " . this.varName . " not found"
				Break
			}
			else
				result[key] := value
		}
		DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
		Return result
	}
	
	poll(varName)
	{
		result := False
		for key, Hwnd in this._hwndList()
		{
			if (key = varName)
			{
				result := True
				Break
			}
		}
		Return result
	}
	
	destroy()
	{
		Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
		DetectHiddenWindows, On
		guiID := this.guiID
		if (this.relationship = "server")
			Gui, %guiID%:Destroy
		GuiVar.onGuiVar.Remove(guiID)
		DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
	}
	
	_hwndList()
	{
		Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
		DetectHiddenWindows, On
		Array := Object()
		WinGet, WinList, List, GuiVar_
		Loop, %WinList%
		{
			X := A_Index
			Hwnd := WinList%X%
			WinGetTitle, WinTitle, ahk_id %Hwnd%
			ControlGetText, Text,, ahk_id %Hwnd%
			WinTitle := SubStr(WinTitle, 8)
			Array[WinTitle] := Hwnd ;Text
		}
		DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
		Return Array
	}
	
	/*
	Notify when variable becomes available
	*/
	notifyOnGuiVarAvailable(varName, notifyService)
	{
		if (isLabel(notifyService)) or (isFunc(notifyService))
		{
			SetTimer, GuiVarTimer, Off
			GuiVar.onGuiVar[varName] := Object()
			GuiVar.onGuiVar[varName].notifyService := notifyService
			if (GuiVar.GuiVarTimerState = "off")
				SetTimer, GuiVarTimer, On
			Return True
		}
		else
			Return False
	}
	
	/*
	Notify on variable content or content change
	*/
	;use trigger content that is unlikely to match user data... allows trigger on blank ("")
	setOnGuiVar(service, triggerOnContent = "wackenfus", frequency = 1)
	{
		if ( (isLabel(service)) or (isFunc(service)) ) and (GuiVar.onGuiVar.Haskey(this.guiID))
		{
			SetTimer, GuiVarTimer, Off
			GuiVar.onGuiVar[this.guiID].triggerOnContent := triggerOnContent
			GuiVar.onGuiVar[this.guiID].watchValue := this._get()
			GuiVar.onGuiVar[this.guiID].state := 0
			GuiVar.onGuiVar[this.guiID].service := service
			GuiVar.onGuiVar[this.guiID].frequency := frequency
			if (GuiVar.GuiVarTimerState = "off")
				SetTimer, GuiVarTimer, On
			Return True
		}
		else
			Return False
	}
	
	getOnGuiVar()
	{
		Return GuiVar.onGuiVar[this.guiID]
	}
	
}

GuiVarTimer:
	GuiVar.GuiVarTimerState := "on"
	SetTimer, GuiVarTimer, Off
	for GuiVarObjName, GuiVarObj in GuiVar.onGuiVar
		if (GuiVarObj.HasKey("service")) and (GuiVarObj.frequency > 0)
		{
			GuiVarHwnd := GuiVarObj.hwnd
			GuiVarService := GuiVarObj.service
			
			Setting_A_DetectHiddenWindows := A_DetectHiddenWindows
			DetectHiddenWindows, On
			ControlGetText, GuiVarText,, ahk_id %GuiVarHwnd%
			DetectHiddenWindows, %Setting_A_DetectHiddenWindows%
			
			if ((GuiVarObj.triggerOnContent = "wackenfus")
					and (GuiVarObj.watchValue != GuiVarText)) ;on change (most useful)
				or ((GuiVarObj.triggerOnContent = GuiVarText)
					and (GuiVarObj.state = 0)) ;immediate trigger if var already matches
				or ((GuiVarObj.triggerOnContent = GuiVarText)
					and (GuiVarObj.watchValue != GuiVarText)
					and (GuiVarObj.state != 0)) ;trigger once per becoming the trigger value
			{
				if (GuiVarObj.triggerOnContent = "")
					GuiVarObj.watchValue := text
				GuiVarObj.frequency -= 1
				GuiVarObj.state := 1
				if (isLabel(GuiVarService))
					Gosub % GuiVarService
				else
					%GuiVarService%(%GuiVarObjName%)
			}
		}
		else if (GuiVarObj.HasKey("notifyService")) and (GuiVar.poll(GuiVarObjName))
		{
			%GuiVarObjName% := New GuiVar(GuiVarObjName) ;instantiate this variable for the client
			GuiVarNotifyService := GuiVarObj.notifyService
			GuiVar.onGuiVar.Remove(GuiVarObjName)
			if (isLabel(GuiVarNotifyService))
				Gosub % GuiVarNotifyService
			else
				%GuiVarNotifyService%(%GuiVarObjName%)
		}
	
	;check full structure of class object to see if timer needs to be turned on again
	for GuiVarObjName, GuiVarObj in GuiVar.onGuiVar
		if ((GuiVarObj.HasKey("service")) and (GuiVarObj.frequency > 0)) or (GuiVarObj.HasKey("notifyService"))
		{
			SetTimer, GuiVarTimer, On
			Break
		}
		else
			GuiVar.GuiVarTimerState := "off"
Return
Demo script#1.ahk

Code: Select all

;Sript#1.ahk
#SingleInstance Force
#NoEnv
SetTitleMatchMode, 2  ;contains
CoordMode, Mouse, Relative

GuiVar_Class() ;initialize

blurb := "This is script #1: Foo"
		. "`n`nI have set GuiVar to notify me when fruit, color"
		. ", and cost are made available by Script #2 called Bar"
Gui, Add, Edit, w275 h400 vEdit1, % blurb
Gui, Show, x200 y200, Foo
SendInput, {End}

;set up to get notifications when external script instantiates these variables
GuiVar.notifyOnGuiVarAvailable("cost", "costFound")
GuiVar.notifyOnGuiVarAvailable("fruit", "fruitFound")
GuiVar.notifyOnGuiVarAvailable("color", "colorFound")


Sleep, 2500
blurb .= "`n`nFoo will now start script #2: Bar"
GuiControl,, Edit1, % blurb
Sleep, 5000
Run, %A_ScriptDir%\script#2.ahk
Goto, jump


;these three are the service routines for the notifications
	fruitFound:
		;Msgbox % "Script #1 found Fruit is: " . fruit.value
		blurb .= "`nScript #1 found Fruit is: " . fruit.value
		GuiControl,, Edit1, % blurb
		Sleep, 250
	Return

	colorFound(color)
	{
		Global blurb, Edit1
		;Msgbox %  "`nScript #1 found Color is: " . color.value
		blurb := blurb . "`nScript #1 found Color is: " . color.value
		GuiControl,, Edit1, % blurb
		Sleep, 250
		Return
	}

	costFound:
		;Msgbox %  "`nScript #1 found Cost is: " . cost.value
		blurb .= "`nScript #1 found Cost is: " . cost.value
		GuiControl,, Edit1, % blurb
		Sleep, 250
	Return



jump:
While % (!InStr(blurb, "found fruit")) or (!InStr(blurb, "found color")) or (!InStr(blurb, "found cost"))
{
}
blurb .= "`n`n  ...Now I will echo what Bar says to me `n`nEchoing Bar:"
GuiControl,, Edit1, % blurb


comChannel := New GuiVar("comChannel") ;instantiate the server variable owned by this script
comChannel.setOnGuiVar("next") ;set up notification triggered when comChannel changes
;say hi to script #2 -- note that this setting the variable doesn't trigger the notification
;triggers come from external scripts.
comChannel.value := "Hello Bar, how are you?"
Return


next:
Sleep, 2500
blurb .= "`nBar replied: " comChannel.value ;display what Bar had to say
GuiControl,, Edit1, % blurb


comChannel.setOnGuiVar("next1")
comChannel.value := "Fine, thanks for asking!"
Return

next1:
Sleep, 2500
blurb .= "`n`nBar replied: " comChannel.value
GuiControl,, Edit1, % blurb

comChannel.setOnGuiVar("next2")
comChannel.value := "OK, give me a the variable name to store it in?"
Return

next2:
Sleep, 2500
blurb .= "`n`nBar replied: " comChannel.value
GuiControl,, Edit1, % blurb

tmp := comChannel.value ;this contains the variable name Bar wants the data in
;now look for Bar to instantiate his variable as server then instantiate it here as a client
GuiVar.notifyOnGuiVarAvailable(comChannel.value, "varReady")
Return

varReady:
%tmp%.value := "0,0.50,0.80,1.00,1.50,2.00,2.50,3.00,5.00,7.00,10.00"
comChannel.setOnGuiVar("next3")
comChannel.value := "Here ya go! Your data is now in """ . tmp . """."
Return

next3:
Sleep, 2500
blurb .= "`n`n`n`n`nBar replied: " comChannel.value
GuiControl,, Edit1, % blurb

comChannel.setOnGuiVar("next4")
if (comChannel.value = "Thank you")
	comChannel.value := "You are welcome... see ya!"
Return

next4:
blurb .= "`n`nBar replied: " comChannel.value
GuiControl,, Edit1, % blurb

Sleep, 3000
Msgbox, Foo is finished
ExitApp
Escape::ExitApp

#Include %A_ScriptDir%\GuiVar_class.ahk

Demo script#2

Code: Select all

;Sript#2.ahk
#SingleInstance Force
#NoEnv
SetTitleMatchMode, 2  ;contains
CoordMode, Mouse, Relative

GuiVar_Class() ;initialize

blurb := "This is script #2: Bar `n`nI will instantiate 3 variables:"
		. "`n`tfruit = apple"
		. "`n`tcolor = red"
		. "`n`tcost = Round(.99*1.095,2)"

Gui, Add, Edit, w375 h400 vEdit1, % blurb
Gui, Show, x500 y200, Bar
SendInput, {End}

Sleep, 2500
blurb .= "`n`n  ...Now I will echo what Foo says to me `n`n`n`n`nEchoing Foo:"
GuiControl,, Edit1, % blurb
Sleep, 250

fruit := New GuiVar("fruit", "apple")
color := New GuiVar("color", "red")
cost := New GuiVar("cost", Round(.99*1.095,2))
Gui, 1: Default

;this is one way to monitor when the server variable is instantiated
;later, Foo (script #1) will use GuiVar.notifyGuiVarAvaliable() to automatically wait for it
while !GuiVar.poll("comChannel")
{
}

Sleep, 2500
comChannel := New GuiVar("comChannel") ;instantiate the client version of the variable
while (comChannel.value = "") ;can monitor contents like this or use [varName].setOnGuiVar()
{
}
blurb .= "`nFoo asked: " . comChannel.value ;display what Foo had to say
GuiControl,, Edit1, % blurb
Sleep, 2500

comChannel.setOnGuiVar("next")
comChannel.value := "I am doing fine!  How about you?"
Return

next:
Sleep, 2500
blurb .= "`n`nFoo replied: " comChannel.value
GuiControl,, Edit1, % blurb

comChannel.setOnGuiVar("next1")
comChannel.value := "I need some data"
Return

next1:
Sleep, 2500
blurb .= "`n`nFoo replied: " comChannel.value
GuiControl,, Edit1, % blurb

comChannel.value := "someData" ;tell Foo the variable name to put data in
comChannel.setOnGuiVar("next2")
someData := New GuiVar("someData") ;instantiate the server variable
Return

next2:
Sleep, 2500
blurb .= "`n`nFoo replied: " comChannel.value
GuiControl,, Edit1, % blurb

blurb .= "`n`nBar reveals the data sent:`n  Data is: " . someData.value
GuiControl,, Edit1, % blurb
comChannel.setOnGuiVar("next3")
comChannel.value := "Thank you"
Return

next3:
Sleep, 2500
blurb .= "`n`nFoo replied: " comChannel.value
GuiControl,, Edit1, % blurb

if (InStr(comChannel.value, "see ya"))
comChannel.value := "Bye, bye"

Sleep, 3000
Msgbox, Bar is finished
ExitApp
Escape::ExitApp
#Include %A_ScriptDir%\GuiVar_class.ahk
User avatar
tzucker
Posts: 42
Joined: 28 Oct 2014, 14:07
Location: Bronx, New York
Contact:

Re: [Library] GuiVar - Use Gui as Variable Between AHK Scrip

06 Nov 2014, 15:26

Thanks I will look at these, but they are a little over my head, although it does sound promising.
Tom Zucker-Scharff
An AutoHotKey Newbie

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: charlie89, gwarble and 126 guests