IronToolbar - 2021/06/21 - beta.1

Post your working scripts, libraries and tools.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

IronToolbar - 2021/06/21 - beta.1

05 Nov 2020, 14:26

Image

Old Preview (still applies)

Download on :arrow: GitHub

The goal with this class script is simplicity. You can still exercise lots of granular control manually, but I wanted to make this toolbar in a way that would reflect a legit toolbar supported in AutoHotkey where the user can apply minimal script code in order to create a toolbar and manage its events.

Extensive docs are on GitHub. The included example script is displayed in the animated preview above.

I was inspired by @Pulover's Class_Toolbar. The end result ended up quite different, so a direct comparison of AHK v1 to v2 might not be as useful as you think, unless you understand the win32 API functions that control the Toolbar.

===================================================================
Updates
===================================================================
Last edited by TheArkive on 14 Jun 2022, 00:59, edited 16 times in total.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2020/11/09 - a122

09 Nov 2020, 15:08

Update 2020/11/09:
  • Added enhancements to Easy Mode.
  • Now MixedButtons, List, and Flat Styles/ExStyles are automatically applied to the toolbar. This allows a mixture of only-icon buttons, only-text buttons, and icon+text buttons (where text is to the right of the icon).
  • Added ability to disable MixedButtons mode when calling tb.New()
  • Added ability to disable Easy Mode when calling tb.New() (automatically disables MixedButtons mode).
  • Added automatic spacing added in front of button text, but ONLY when user specified icon:-1 during tb.Add(). This causes text-only button text to appear centered. Otherwise the text would be flush with left button edge. User can change this if needed with tb.txtSpacing := x, where x is number of spaces to insert to the left of button text. Default is 2 spaces.
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: IronToolbar - 2020/11/09 - a122

09 Nov 2020, 15:13

:dance: :bravo:
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/03/11 - a129

11 Mar 2021, 17:45

This is a significant update. Flexibility, reliability, and ease of use is improved in this release.

2021/03/11
  • Added automatic toolbar sizing/docking when window is resized (see docs).
  • Added several new methods for getting/setting button states.
  • Improved toolbar creation with Gui.AddToolbar() (see docs).
  • Improved the example with 2 toolbars, and example menus for DropDown buttons, as well as lots of comments to explain everything.
User avatar
hoppfrosch
Posts: 443
Joined: 07 Oct 2013, 04:05
Location: Rhine-Maine-Area, Hesse, Germany
Contact:

Re: IronToolbar - 2021/03/11 - a129

12 Mar 2021, 01:51

:clap:
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/03/13 - a129

13 Mar 2021, 07:02

Update 2021/03/13
  • Changed tb.callback to require a type of function object.
  • Changed Toolbar.SizeToolbars(x,y) to ToolbarSizeToolbar(tb,x,y) for per-toolbar resizing.
  • Updated docs.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/06/21 - beta.1

26 Apr 2022, 14:29

AHK_user wrote:
25 Apr 2022, 15:55
Another idea is to see the toolbar more similar to the menubar syntax, define the buttons seperately and connect the toolbar to the gui

Something like:

Code: Select all

MyToolbar := Toolbar(generaloptions)
oToolbarButton1 := MyToolbar.Add(options, "buttontext 1", callback1, IconNumber, PartNumber)
oToolbarButton2 := MyToolbar.Add(options, "buttontext 2", callback2, IconNumber, PartNumber)
MyGui.ToolBar := MyToolbar 

callback1(GuiObject,ToolbarObject){
	MsgBox(ToolbarObject.text)
}

callback2(GuiObject,ToolbarObject){
}
This seems logical ahk syntax and gives flexibility for later expansion, setting,... :D

Most of that looks pretty good to me, and is definitely the intent behind GuiControl_Ext (to look and feel like AHK v2).

For the callbacks I will try to conform to the AHK v2 OnEvent() or OnNotify() callbacks. Something like:

Code: Select all

TB_callback(Toolbar, Btn_Obj) {
    ; Toolbar - the GuiControl object
    ; Btn_Obj - lots of info about the click event
}

OR

Gui_Toolbar(GuiCtrl_TB, Btn_obj, X, Y) {
    ; this is similar to Gui_ContextMenu in AHK v2 docs
}

So of course if a user wants to assign a different callback for each toolbar then they can, but it will also be simple to assign a single callback for all toolbars.
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: IronToolbar - 2021/06/21 - beta.1

27 Apr 2022, 01:09

Cool that you like it, I also agree that the more it looks like the original syntax, more users will find it easy to use.

It is indeed cool if the onevent and onnotify would also work, but I would certainly appreciate it if the default "Click" callback would be also included in the line where you add the button to the toolbar.

If possible, It would be completed if it could also accepts flat arrow functions.

This callback parameter could be possible also a menu object to show the menu.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 09:08

AHK_user wrote:
27 Apr 2022, 01:09
It is indeed cool if the onevent and onnotify would also work, but I would certainly appreciate it if the default "Click" callback would be also included in the line where you add the button to the toolbar.

I think I understand what you are saying here, but the callback for a toolbar is for the entire toolbar, not a specific button. So adding such a field to the Toolbar.Add() method would not make much sense. It would make more sense to mimic the AHK v2 behavior with OnEvent / OnNotify. What context are you thinking of that would require specifying a callback for a specific button?

Below I explain a bit more about the data that is fed into a toolbar callback (currently and likely in future updates).

PS: I know that I didn't actually write any docs for this. I plan to do that with a rewrite of this lib.

AHK_user wrote:
27 Apr 2022, 01:09
If possible, It would be completed if it could also accepts flat arrow functions.

The fat arrow functions are simply another kind of function object. So a predefined callback or a fat arrow function would work either way. I think this old script may actually accept just a string (old AHK v1 style), so that should change for sure.

AHK_user wrote:
27 Apr 2022, 01:09
This callback parameter could be possible also a menu object to show the menu.

I don't quite understand what you mean here. When you click anywhere on a toolbar (including on a button), the callback function (currently and in the update) will give an object that specifies the following:
  • Button Index (0 or -1 for no button i think)
  • Button CmdID (a TBBUTTON struct thing)
  • X/Y coords of the mouse cursor click on the toolbar
  • X/Y coords of the top-left of the button clicked
  • W/H of the button
  • and much more

All this info, in part or in whole, can be used in order to create the menu at the specified location. In the example I tried to briefly explain the contents of the obj in the callback (there is a lot).

In the example the explanation is several commented lines, starting at Line 179: Toolbar event callback: tbEvent(tb, lParam, dataObj)

And you can see some of this info as the example script is run, in the text box.

But actually creating and/or displaying the menu obj is done by the user in the callback with the above info, and this process is done completely externally according to my observations. If I conform to the AHK v2 syntax, the user can still customize their callback function and the setup of the Toolbar object using something like this:

Code: Select all

; after creating the Toolbar obj, then...

; ========= maybe don't do both of these ============================
Toolbar.OnNotify( 0x1234, cb_func.Bind(,, UserMenuObj) )
; -- or --
Toolbar.menu := MenuObj ; then is accessible below without Bind)
; ===================================================================

cb_func(GuiControl, lParam, MenuObj) {
    ; the resulting callback has the extra user-defined parameter
    ; -- or --
    ; Simply use GuiControl.menu to access the menu obj
}

This kind of customization is basically limitless. I think you can even override the default fields in any given built-in AHK v2 callback funciton with the Bind() method. You can also attach the MenuObj to the Toolbar obj (as shown above).

If you can show me a context where an actual menu object should be somehow handled by the internal code of the toolbar, and not by the user in some way, then I'd be happy to consider making that change in this script.
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 10:27

A menuobject would indeed only make sense if the callbacks would be defined by separate toolbar buttons.

I agree that Toolbar.OnEvent("Click", ToolbarCallback) should work, but the ToolbarCallback would almost always be a function that check which button was pressed with a if or a case statement.

We could avoid that by setting a callback for each button, resulting in shorter code in the script that the users would use.
Setting the toolbar to respond on the buttons is not that hard, just automatically add the onEvent method if a Callback is present for one of the buttons to a internal function that checks which button was pressed and if the button has a callback and call that function.
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 10:30

Ok that sounds reasonably easy. I can add an option to also specify a callback per button. Hopefully I can do it in a way that doesn't add too much code to the lib.
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 12:59

TheArkive wrote:
29 Apr 2022, 10:30
Ok that sounds reasonably easy. I can add an option to also specify a callback per button. Hopefully I can do it in a way that doesn't add too much code to the lib.
I have done some tests, you can run the passed callback with the method call:

Code: Select all

CallBack.Call(Parameters,...)
User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 13:31

@AHK_user

Yep. The main goal is to internally have a callback (which the current version does) in order to organize the data.

The process of assigning a callback to a specific button will probably require a Map() to relate a button index or CmdID to a specific function, then every WM_NOTIFY msg will have to check this Map() within the internal callback, so that the user-defined callbacks can then be triggered.
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: IronToolbar - 2021/06/21 - beta.1

29 Apr 2022, 14:00

Yes, I would recommend to add a new property to the controlGuiObject of the toolbar that contains a map of ButtonObjects with all the properties of the button and even the controlguiObject as the parent property.

Or you could use the defineprop method that also lets you call a function when one of the properties is changed.

something like:
oButton := {options: options, text: buttontext, callback: callback, iconFile: iconFile, iconNumber: iconNumber, enabled:EnabledState , parent: controlGuiObject }

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: jacek678 and 28 guests