I am one of the original old time programmers that has roots in cobol, APL, turbo pascal and assembler with solid background in working with linux and much more, and even though I am no newbie when it came to AutoHotkey, I was floored by the latest version which included Objects....
One of the flaws as well as one of the strengths of AutoHotKey is the lackadaisical syntax of its programming language; It is worse then the spaghetti coding we did back in late 70s and early 80s. It is this lackadaisical strength of AHK that you can almost tease the program into doing the impossible with just a bit of imagination.
However this strength which is also AHK flaws, creates a torturous time for the old programmers who are hard coded in structures, pointers and variable types.
I spent the last two days researching the creation of objects in order to incorporate them into my latest project. At the moment I have been hard coding statements like
if control = static1
{
do something with button 1
}
else
if control = static2
{
do something with button 2
}
I knew that objects and associative arrays would probably simplified the hard coding of the if then statements by using the control to index into an array, but nobody talked about creating an array of objects. Everyone talked about objects and there were numerous youtube tutorials on a single object and the relationship of that one object to its color, shape and size, but not on a collections.
I was frustrated and I noticed a trend with the old fashion programmers that were being whipped by the youngsters who were patronizing with their tutorials by creating examples that just as convoluted and useless as the objects that they were creating.
Some old programmer even asked "what good is object oriented programming?" and some youngster piped in "why everything!!" and proceeded to create another covoluted example of everything.
The problem was that although the example was wonderfully created, it had no real world value in its creation when a straight forward program would do the trick.
So from old time programmer to another (for those who are old time programmers and is reading this), welcome to the world of objects.
------------------------
So lets begin with the problem rather then the elegant solution. In that way you can be lead down the rabbit hole with me.
I am a Sims 3 game player. Actually I build houses within the game rather then actually playing the game itself. Recently I finally bought all the expansion packs that expanded the games with a large variety of house items with each expansion pack; there are a total of 17 expansion packs.
Now the way that you can control what EP shows on the Sim game launcher is by a couple of registry entries. By deleting the EP registration in the registry, the Sim Game Launcher will think that you don't have that EP.
So by controlling the registry entries, you can play the bare bone Sims 3 game or different combination of Expansion packs.
The reason that you would do this, is to make the game play faster by not having as many items boggling down the game such as the Sims Pets EP which adds pets to your game, but as you play in this world, you will notice wild Horses, cats, deers, chipmunks wandering your world.
Removing this EP while you build houses would be a more optimal experience.
Thus my Sim Game Selector was born. My first trial of this program was using the Smart Gui creator to create radio buttons for the game icons. However as I became familiar with the latest version of AHK, I started to substitue the radio buttons with just various versions of the icons themselves; grey out version of the icon to represnt not selected and a red circle with a line through the icon representing that the game is not available for toggling.
----------------------------------
So far so good?
The programming "Without" Objects has been very easy. Every icon, every game status, is represented by a global value depending on which part of this panel that we are dealing with. As an example for toggling the icon picture we use the function
ToggleIcon(byref onoff,byref togglectrl,byref imageon,byref imageoff)
{
onoff := not onoff
soundplay, button-35.mp3
if onoff
GuiControl, , togglectrl, %imageon%
else
GuiControl, , togglectrl, %imageoff%
return
}
Thus each button has a G variable to go to an individual separate button routine such as
EPWORLD:
if not Installed_EPWORLD
BlinkIcon(EPWORLD,Imageoff_EPWORLD, ImageNA_EPWORLD)
else
ToggleIcon(Status_EPWORLD, EPWORLD, Imageon_EPWORLD , Imageoff_EPWORLD )
return
The blinkicon() function blinks the red circle line crossed out icon.
Everything was working fine.... and the program was huge... (well not really that huge) but it was repetitious and in my mind, not very elegant. It had line after line after line of if then else...
and to toggle an icon, every icon was separate from every other icon....
-----------------------------------------
Objects and an array of Objects
After two days of trial and error and a folder full of examples, the road was long and hard.
Before simplifying my program, I decided to start up my tutorial thread for us Old timers before my object becomes too complicated to post. At the moment, it has very simple and clean methods along with a very clean class definition.
class iconbutton { somedata := "Hello Within Class" buttonstatus := true __New(control, iconon, iconoff, iconna) { this.control := control, this.iconon := iconon, this.iconoff := iconoff, this.iconna := iconna } off() { this.buttonstatus := false control := this.control iconimage := this.iconoff guicontrol, , %control%, %iconimage% } on() { this.buttonstatus := true control := this.control iconimage := this.iconon guicontrol, , %control%, %iconimage% } na() { this.buttonstatus := false control := this.control iconimage := this.iconna guicontrol, , %control%, %iconimage% } toggle() { control := this.control imageon := this.iconon imageoff := this.iconoff this.buttonstatus := not this.buttonstatus if this.buttonstatus guicontrol, , %control%, %imageon% else guicontrol, , %control%, %imageoff% } }
This is the iconbutton class much like the record types in the old days. It contains all the local variables and self functions (called methods) for the icon to work as an object.
just a few explanations...
I had to use
control := this.control
before using it in
guicontrol, , %control%, %imageon%
because AHK would not allow me to use directly in the statement like
guicontrol, , %this.control%, %this.iconon%
go figure...
So now we have the class, lets use it...
class iconbutton { somedata := "Hello Within Class" buttonstatus := true __New(control, iconon, iconoff, iconna) { this.control := control, this.iconon := iconon, this.iconoff := iconoff, this.iconna := iconna } off() { this.buttonstatus := false control := this.control iconimage := this.iconoff guicontrol, , %control%, %iconimage% } on() { this.buttonstatus := true control := this.control iconimage := this.iconon guicontrol, , %control%, %iconimage% } na() { this.buttonstatus := false control := this.control iconimage := this.iconna guicontrol, , %control%, %iconimage% } toggle() { control := this.control imageon := this.iconon imageoff := this.iconoff this.buttonstatus := not this.buttonstatus if this.buttonstatus guicontrol, , %control%, %imageon% else guicontrol, , %control%, %imageoff% } } global Imageon_EPWORLD = "Sims3EP01-WorldAdventures.ico" global Imageoff_EPWORLD = "BWSims3EP01-WorldAdventures.jpg" global ImageNA_EPWORLD = "NASims3EP01-WorldAdventures.jpg" Gui, Add, Picture, x12 y10 w50 h50 VEPWORLD, %Imageon_EPWORLD% Gui -MinimizeBox -MaximizeBox +toolwindow Gui, Show, x411 y276 h613 w152 , Sim Game Select Buttonme := new iconbutton("EPWORLD",Imageon_EPWORLD,Imageoff_EPWORLD,ImageNA_EPWORLD) msgbox test off Buttonme.off() msgbox test on Buttonme.on() msgbox test NA Buttonme.na() msgbox % buttonme.somedata buttonme.somedata := "Give me some love" msgbox % buttonme.somedata return guiclose: exitapp
We can see that we can store extra data like somedata within the object, so objects are very flexible in grouping together related data and functions all encapsulated!!
and to tell that object to turn on, off or even turning itself into a NA icon is as simple as saying
buttonme.na()
So lets take a break.... and allow you to post up any thoughts you may have on this topic and whether or not you wish for me to continue.
The second part of this tutorial will show you how to put a collection of iconbutton objects into an array and access them using the
mousegetpos, , , id, control
only a few lines more.... but lets hear what you think? come on post up old timers!!