Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Object Programming for Old Time Programmers - Using Tight Object coding for toggling Icon Buttons in a Window


  • Please log in to reply
27 replies to this topic
RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

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.

 

simgameselectpanel_zpsa85d4cc1.jpg

 

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

 

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!!

 

 

 

 

 

 



faqbot
  • Members
  • 997 posts
  • Last active:
  • Joined: 10 Apr 2012
Not an old timer and I know nothing about this classes stuff but I'm all for better/more examples/tutorials. Perhaps it might be useful to post examples that work out of the box? At the moment I would have to modify the example to work with my own images - perhaps providing the icons or using standard shell32.dll icons so people can just save the code and run it. But please continue regardless.

RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

So now that my mind has been AHK objectized and while my mind is still fresh on the simpiler format of the icon button, I thought I better finish my post on this before it my code gets really complicated and I'm no longer able to pass on my knowledge. 

 

At this point in time, object programming can probably reduce my coding in terms of the number of lines by 50%. Definitely all the "IF-Then-else" statements are now reduced to one line. As I sit here, I am overwhelmed by the simplicity of all this, so lets get started on finishing what we started.

 

The above code shows how easy the icon becomes a button that we can press by simply stating buttonme.on() or buttonme.off()

 

To incorporate it into a panel of icon buttons, rather then having separate iconbutton object that is perhaps stored on individual global variables such as EPWORLD_Button, EPAMBS_Button, I was determined to have them stored as part of an Associative Array; indexed by the control names of the buttons themselves.

 

Thus starting with first icon, the control names were Static1, Static2... and so on until  Static17. Thus what we needed was something like:

 

simbuttons["Static1"].off()

 

 

So here is the iconbutton class unchanged from above....

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%
	}
}

 

and this time we have 4 sets of icon images for the examples. Since I cannot post the icons themselves, feel free to replace the icon images with any jpg or icons that you have lying around.

 

global	Imageon_EPWORLD 	= "Sims3EP01-WorldAdventures.ico" 
global	Imageoff_EPWORLD 	= "BWSims3EP01-WorldAdventures.jpg"
global	ImageNA_EPWORLD 	= "NASims3EP01-WorldAdventures.jpg" 

global 	Imageon_EPAMBS		= "Sims3EP02-Ambitions.ico"
global 	Imageoff_EPAMBS		= "BWSims3EP02-Ambitions.jpg"
global 	ImageNA_EPAMBS		= "NASims3EP02-Ambitions.jpg"

global 	Imageon_EPLATE		= "Sims3EP03-LateNight.ico"
global 	Imageoff_EPLATE		= "BWSims3EP03-LateNight.jpg"
global 	ImageNA_EPLATE		= "NASims3EP03-LateNight.jpg"

global 	Imageon_EPGENS		= "Sims3EP04-Generations.ico"
global 	Imageoff_EPGENS		= "BWSims3EP04-Generations.jpg"
global 	ImageNA_EPGENS		= "NASims3EP04-Generations.jpg"

here is the gui part of the code with the 4 icon button objects defined in an array!! 

 

Gui, Add, Picture, x12 y10 w50 h50 VEPWORLD gpressmybuttons, %Imageon_EPWORLD%
Gui, Add, Picture, x12 y60 w50 h50 VEPAMBS gpressmybuttons, %Imageon_EPAMBS%
Gui, Add, Picture, x12 y110 w50 h50 VEPLATE gpressmybuttons, %Imageon_EPLATE%
Gui, Add, Picture, x12 y160 w50 h50 VEPGENS gpressmybuttons, %Imageon_EPGENS%

Gui -MinimizeBox -MaximizeBox +toolwindow
Gui, Show, x411 y276 h613 w152 , Sim Game Select

/* The icon button objects defined in an array */
SimButtons := {}
SimButtons.insert("Static1", 
             new iconbutton("EPWORLD",Imageon_EPWORLD,Imageoff_EPWORLD,ImageNA_EPWORLD) )
SimButtons.insert("Static2", 
             new iconbutton("EPAMBS",Imageon_EPAMBS,Imageoff_EPAMBS,ImageNA_EPAMBS) )
SimButtons.insert("Static3", 
             new iconbutton("EPLATE",Imageon_EPLATE,Imageoff_EPLATE,ImageNA_EPLATE) )
SimButtons.insert("Static4", 
             new iconbutton("EPGENS",Imageon_EPGENS,Imageoff_EPGENS,ImageNA_EPGENS) )

return

guiclose:
	exitapp

 

and lastly the single line code that handles the button presses....

 

 

PressmyButtons:
	MouseGetPos, , , id, control
	simbuttons[control].toggle()

	return

 

This reduces the 20 conditional if-then-else lines previously to 4 lines. 

 

I am very very excited in simplifying my code as I can see whole blocks of code reduced down to a loop as each object checks itself for changes ie. if the user has toggled one of the icon to an "off" status, it is as simple as calling the method savechanges() on each object to check its own status and to implement its own change.

 

In comparison, the non object code is to check global boolean flags on every button on a separate line of code for each button. Thus at least 5 lines of code per game x 18 game icons = 90 lines of code...

 

 if Start_EPWORLD <> Status_EPWORLD
  if Status_EPWORLD
   RestoreReg(Games01_EPWORLD,Games02_EPWORLD)
  else
   DeleteReg(Games01_EPWORLD,Games02_EPWORLD)

 if Start_EPAMBS <> Status_EPAMBS
  if Status_EPAMBS
   RestoreReg(Games01_EPAMBS,Games02_EPAMBS)
  else
   DeleteReg(Games01_EPAMBS,Games02_EPAMBS)

 if Start_EPLATE <> Status_EPLATE
  if Status_EPLATE
   RestoreReg(Games01_EPLATE,Games02_EPLATE)
  else
   DeleteReg(Games01_EPLATE,Games02_EPLATE)

.

.

.

.

.

 

reduced down to:

 

      for key, value in simbuttons

                 simbuttons[%key%].update_registry()

   

 

So this completes a real world application, or at least a real world game application for this knowledge. Once you start building programs using objects there is no turning back as you encapsulate your data and functions into objects and then extending the basic object model to encapsulate similar objects, your programming becomes more and more simpler and your code also becomes re-usable as you see similarities with other objects.

 

Thanks for reading....

 

Please leave your comments below...



RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

Not an old timer and I know nothing about this classes stuff but I'm all for better/more examples/tutorials. Perhaps it might be useful to post examples that work out of the box? At the moment I would have to modify the example to work with my own images - perhaps providing the icons or using standard shell32.dll icons so people can just save the code and run it. But please continue regardless.

Thanks for reading faqbot... sorry about the icons but I really tried to get them uploaded but there were no local storage for zip files that I could find on the posting functions. Even the image that I posted up had to be hosted on photobucket. If anyone can post up how to host zip files, I will upload the program and icons immediately ...

 

Thanks for reading!!

 

Also I've posted up a complete solution in the script area on compacting all your icons and other files into a single .exe file. It has been viewed a 128 times but nobody has made any comments.



RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

http://sdrv.ms/131693k

 

Here you go everyone.... the code, the icons.... all there....



Jackie Sztuk _Blackholyman
  • Spam Officer
  • 3757 posts
  • Last active: Apr 03 2016 08:47 PM
  • Joined: 28 Feb 2012
nice with more guides on this topic

and you can use % to force an expression like this
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
		guicontrol, , % this.control, % this.iconoff
	}
	on() {
		this.buttonstatus := true
		guicontrol, , % this.control, % this.iconon
	}
	na() {
		this.buttonstatus := false
		guicontrol, , % this.control, % this.iconna
	}

	toggle() {
		this.buttonstatus := not this.buttonstatus

		if this.buttonstatus
			guicontrol, , % this.control, % this.iconon
		else
			guicontrol, , % this.control, % this.iconoff
	}
}
happy to read one more take on this...
Helping%20you%20learn%20autohotkey.jpg?d

[AHK] Version. 1.1+ [CLOUD] DropBox ; Copy [WEBSITE] Blog ; About

RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

Thank you Blackholyman on the % fix. 

 

That shortens the code by 9 lines :p



RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

well? it would be appreciated if the lurkers could step forward and tell me if I should continue posting these non-responsive posts in LHK or perhaps I've lost everyone with these useless pieces of coding since nobody plays the sims in here :p and of course nobody wants a icon button menu...

 

comments anyone?

 

I've been busy modifying my original code and have found that I could almost reduce the coding down by 80% however it is extremely difficult shifting paradigm from straight function coding to object oriented style. One style , the function one, operates on a global scale against a plethora of icons versus a plethora of registry settings, and when converted to an object oriented style everything simplifies to a single icon mapped to a single game mapped to a single registry entry that determines whether or not the game is installed. This simple object is multiplied 18 times into an array of objects that is now so simple that it almost bounces with delightfulness. :p

 

The scale of keeping track of all the game variables and naming conventions are now self contained into one game object. Although I kept the global variables

 

If you wish for me to continue this article on the other grand changes that object oriented programming provides, I would be glad to do so, but you must respond on whether or not you like what you are reading. I am new to the AHK forums and I find the quietness to be quite disconcerting; however I do notice that the number of lurkers are in the hundreds so I would appreciate a hello from a few of you… go ahead make me feel welcome?



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
i dont think you should get discouraged if not many people read or respond to your posts

most people are only interested in specific things, and only those users will be active in your threads

however, that shouldn't discourage you from sharing your code/ideas. maybe someone 3 months from now will search and find your topic and will post some ideas and additions

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008
Don't be discouraged from posting due to a lack of replies; you'd be amazed at how much people read at the forums without replying to. I've posted some very simple stuff that only I ever replied to in updating it, and years later found out in separate discussions that others were using that code.

RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

i dont think you should get discouraged if not many people read or respond to your posts

most people are only interested in specific things, and only those users will be active in your threads

however, that shouldn't discourage you from sharing your code/ideas. maybe someone 3 months from now will search and find your topic and will post some ideas and additions

 

Thank you guest3456... your response is greatly  appreciated.

Don't be discouraged from posting due to a lack of replies; you'd be amazed at how much people read at the forums without replying to. I've posted some very simple stuff that only I ever replied to in updating it, and years later found out in separate discussions that others were using that code.

 

I understand sinkfaze... and thank you for responding...



faqbot
  • Members
  • 997 posts
  • Last active:
  • Joined: 10 Apr 2012
I like the practical example. Not the theoretical "lets assume we have a piece of fruit or a car which has a colour" etc.

deguix
  • Members
  • 87 posts
  • Last active: Jun 17 2014 05:18 AM
  • Joined: 26 Aug 2004

When I started ahk, there weren't any object programming in it at all, so instead of using objects like you did, I started by using arrays which use the Array%Index% syntax. For me, coming from C++, it was a pain in the ass. Glad the language now has the option for oop - I still avoid it in AHK because the syntax gets weird the more new stuff I use.

 

About the this.variable... probably you should be using all of the new syntax, including this:

 

guicontrol, ,% this.control, % this.iconoff

 

Try that, I don't really remember if that works or not, but that's how the new syntax goes.



RalphaelNinja
  • Members
  • 24 posts
  • Last active: Jul 24 2013 09:04 PM
  • Joined: 13 Mar 2013

I like the practical example. Not the theoretical "lets assume we have a piece of fruit or a car which has a colour" etc.

so you are saying that you like my tutorial that doesn't have a piece of fruit or cars :) with colour

 

When I started ahk, there weren't any object programming in it at all, so instead of using objects like you did, I started by using arrays which use the Array%Index% syntax. For me, coming from C++, it was a pain in the ass. Glad the language now has the option for oop - I still avoid it in AHK because the syntax gets weird the more new stuff I use.

 

About the this.variable... probably you should be using all of the new syntax, including this:

 

guicontrol, ,% this.control, % this.iconoff

 

Try that, I don't really remember if that works or not, but that's how the new syntax goes.

That does work. thank you deguix... The problem is that same syntax isn't always workable. I've tried to use it in various circumstances and AHK complains that I'm missing the end % and in this case it has one too many.

 

Although I really cannot complain about AHK but the variability and almost random syntax has vexed me once too often. I have had to think outside the box when trying to outthink AHK for its reason for not working. 

 

I almost gave up on stuffing a gui control into an object because I couldn't store it until I figure a string might be the key rather then a ptr to a control block.



IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007

Yeah it is a common issue that the OOP examples tend to be too simple and the value behind can not be identified. After all, the OOP approach makes things more complicated in the first place, but as soon the program gets a bit of complexity the abstraction shows its true value.

 

@RalphaelNinja: I have taken several approaches to show "old school" programmers with a background in RPG and now (Visual) Basic to get in touch with OOP. It is amazing how difficult it is to show someone the benefits of it by just a discussion. Common arguments against OOP from the old school people cover "needs more code to achieve the same", "I can not follow the code flow due to abstraction (polymorphism)" and finally "it might just be too complicated".

 

I understand that the root cause of those wrong arguments comes from the fact that those people try to apply their old and proven structural programming knowledge to the OOP world. Off course, you still program structurally inside classes, but they seem not to be able to get the big picture.

 

I wonder if you have some easy to understand arguments to explain the matter to "another" old school programmer? happy.png