jeeswg wrote:icuurd12b42 wrote:yet missing the most ridiculous obvious features here and there
I wondered what you had in mind.
Ridiculously easy to manually code a GUI but can't run it modal for example (without resorting to winapi mastery... or using functions normally used to control a target process window which is what I did being lazy)...
Ridiculously easy to setup a trieeview or list view, an almost incomprehensible task in c++, yet there is no item extra data available to you. Extra data is the first thing you realise you need dealing with list items..
This, this is anoying
var := TV_GetChild(item_index)
vs
TV_GetText(out_var,item_index)
We have the ability to return strings in functions we make... and many old statements have a function equivalent to the output argument method.... This is an omission, I guess
And I'm still scratching my head about "What if I have 2 treeviews on the gui!!"
as I said, here and there. All and all I understand these feature were likely tacked on with enough thought for this to be moderately useable, more so in many cases than a conventional development platform, but the language is almost there for way better implementation, see my ending statement.
icuurd12b42 wrote:t := Function();
Why is this a problem? I wish Visual Studio could let you miss them out (semicolons), and add them in for you. If I spend more time with Visual Studio I may even try to write a script in AHK to add missing semicolons prior to compile. Trailing semicolons are the one thing I don't like about C++, I'd like to hear the rationale for their usage.
The facepalm about this line of code is that ; is a comment!!! think about it.
this is an error
t:=Function();
t:=Function();This is an error
t:=Function() ;This is OK
The fact that ; is a comment means that ; and everything after it should be ignored. having it err out because of the missing space is annoying. Even if inadvertently typed, it would be a blessing if simply ignored...
>I'd like to hear the rationale for their usage.
the ; indicates the end of a statement because they found out that, especially in the early days of 40 character per line, one would need to spread out the code over multiple lines
so this is allowed
x = 10 +
20 +
15;
and that character was an easy eol indicator...
icuurd12b42 wrote:and no for i loop!
I agree. I don't need it that often, but it's good for maths-related tests and plotting points in graphs, and converting scripts from other languages. I mention traditional for loops here:
jeeswg's documentation extension tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=33596
Dont get me wrong, the loop features are pretty cool, just that the missing for loop is likely THE WTH moment for most everyone...
I also agree about the GUI. AHK v2 is overhauling it though, and I've partially created my own replacement functions, which has helped me to appreciate just how many things Chris got right and the good decisions he made, even though I have my reservations about many things. And ultimately, everything in AHK v1 with GUI, though not always intuitive, usually doesn't require many code lines.
I agree that the chm is fine. Everything you need in one file. Any problems and you can explode the chm into separate htms, which I find handy for doing searches, and checking that I've seen every page of the documentation.
I welcome criticism of AHK, although I think it's pretty good overall, especially if you replace commands with custom functions. You take the syntax of Excel functions in sheet formulae, add in curly braces, control flow statements and directives, and you have something very effective. So many of the standard things you would want to do a lot are well covered, cf. C++ where everything that should take one line takes six lines.
So yeah, I 'concuur' with a lot of the things you're saying.
I do prefer typing 6 comprehensible lines of code over one line that will make me scratch my head and force me to re-read the help coming back to it 3 months later...
I can always make a script to pass 6 arguments to convert thos 6 calls in a one liner... you cant do the opposite with the GUI system
I been spending the day trying to encapsulate a GUIs in classes... Just to see how far I could go... Here's an example
One example
Code: Select all
;This hybrid mix of global and class is weird, but here's a reminder
; ListProcessDialog is the class name, used to set-up and preform actions
; ListProcessDialog_ is the Window Name
; ListProcessDialog_ControlName is the name convention for the controls that need to receive events
; vListProcessDialog_ControlName and gListProcessDialog_ControlName and ListProcessDialog_ControlName() for the event handling
;The global Name/Handlers for controls
global ListProcessDialog_ListView :=
global ListProcessDialog_StatusBar :=
;Class ListProcessDialog
; Creates and show a Process Viewer window
; Calls the MainUI function to add a new App to it's list on double click and closes
;
Class ListProcessDialog
{
static Icons :=
ShowModal()
{
;disable the main ui window
WinSet,Disable, ,HotKeySpeak
;show myself
Gui, ListProcessDialog_:Show , w400 h400, Select Program From Running Processes
}
;creates the Main GUI Window
Create()
{
;set ListProcessDialog_ as target for setting things up
Gui, ListProcessDialog_:Default
;allow resize
Gui, +resize
Gui, +AlwaysOnTop
;Label on top of treeview
Gui, Add, Text, section, Running Processes:
;the icons list to use in the treeview
ListProcessDialog.Icons := IL_Create(10,10,1)
;stub icons
;from dll or exe
;Loop 10 ; Load the ImageList with some standard system icons.
; IL_Add(ListProcessDialog.Icons, "shell32.dll", A_Index)
;from ico file
;IL_Add(ListProcessDialog.Icons, "Graphics\HotKeySpeak.ico", 2)
;listview
; Create the ListView with two columns, Name and Size:
Gui, Add, ListView, x0 y+m r20 w700 vListProcessDialog_ListView gListProcessDialog_ListView, Application|Path
LV_SetImageList(ListProcessDialog.Icons,1)
;Gather a list of all processes path
WinGet, all, list
;loop through list
ImageIndex := 1
Loop, %all%
{
Try
{
;get the path
WinGet, PPath, ProcessPath, % "ahk_id " all%A_Index%
;get component parts of the path
SplitPath, PPath , OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
;check if not in listview already
if(ListProcessDialog.Find(OutNameNoExt) = 0)
{
;load the icon from exe
hicon := LoadPicture(PPath, "Icon1")
;if not failed loading
if(hicon <> 0)
{
;add icon. reload it in image since the documented HICON method fails
;IL_Add(ListProcessDialog.Icons, HICON:%hicon%) ;compile fail yet document sais it should work
IL_Add(ListProcessDialog.Icons, PPath, 1)
;Add the treeview item
LV_Add("Icon" . ImageIndex, OutNameNoExt, OutDir)
ImageIndex:=ImageIndex+1
}
}
}
catch e ; Handles the first error/exception raised by the block above.
{
break
}
}
LV_ModifyCol() ; Auto-size each column to fit its contents.
;LV_ModifyCol(2, "Integer") ; For sorting purposes, indicate that column 2 is an integer.
;Status Bar
t := " Double Click on Application to Add..."
Gui, Add, StatusBar, vListProcessDialog_StatusBar, %t%
;reset the default
Gui, 1:Default
}
;Finds if entry is in the listview
Find(entry)
{
out := ""
Loop % LV_GetCount()
{
LV_GetText(RetrievedText, A_Index)
if(RetrievedText = entry)
{
return 1
}
}
return 0
}
;Window Resize event
OnGuiSize(GuiHwnd, EventInfo, Width, Height)
{
; The window has been minimized. No action needed.
if EventInfo = 1
return
;Set GUI context to ListProcessDialog_
Gui, ListProcessDialog_:Default
;Move, Expand, shrink the controls to match new size
;Treeview
GuiControl, Move, ListProcessDialog.ListView, % "H" . (Height - 42) . " W" . (Width)
;reset the default
Gui, 1:Default
return
}
;ListView events
OnListViewEvents()
{
if A_GuiEvent = DoubleClick
{
LV_GetText(ExeName, A_EventInfo,1) ; Get the text from the row's first field.
LV_GetText(ExePath, A_EventInfo,2)
MainUI_Add_Process(ExePath . "\" . ExeName . ".exe")
ListProcessDialog_GuiClose()
;ToolTip You double-clicked row number %A_EventInfo%. Text: "%RowText%"
}
return
}
;GUI Close event
OnGUIClose()
{
;Re-enable the MainUI
WinSet,Enable, ,HotKeySpeak
;Destruct the process viewer window
Gui, ListProcessDialog_:Default
Gui, Destroy
;cleanup
ListProcessDialog_Listview := 0
ListProcessDialog_StatusBar := 0
ListProcessDialog.Icons := 0
Gui, 1:Default
}
}
;All events dispatched to the class function
ListProcessDialog_GuiSize(GuiHwnd, EventInfo, Width, Height)
{
return ListProcessDialog.OnGuiSize(GuiHwnd, EventInfo, Width, Height)
}
ListProcessDialog_ListView()
{
return ListProcessDialog.OnListViewEvents()
}
ListProcessDialog_GuiClose()
{
return ListProcessDialog.OnGuiClose()
}
It's not possible to set the event handler to a class function, which is basically the major pain for me...
It's all so close to javascript though, a class seems to be instantiatable and give static access, just like javascript and vb classes. 90% there really