[Class] Toolbar - Create and modify (Updated Aug, 9, 2020)
Posted: 04 Oct 2013, 07:25
by Pulover
This class attempts to provide intuitive methods to work with toolbars created using Gui Custom controls.
Since the new Custom controls were implemented I've been waiting for someone to come up with a library or class to work with toolbars but as nothing has shown I decided to try and make one myself.
Screenshot:
I've been learning from examples in MSDN and from Toolbar.ahk, included in majkinetor's impressive Forms Framework, to implement the most essential methods needed.
Features:
Add, insert, delete and modify buttons.
Add or insert various buttons in a single call with general and individual options.
Add default, hot, pressed and disabled Image Lists.
Export layouts.
Save, load, import and export presets.
Retrieve and change information about buttons and toolbars.
Thanks, joedf! Btw I've reverted the last update. Turned out I had misunderstand the request and the result was not very good...
Re: [Class] Toolbar - Create and modify
Posted: 20 Nov 2013, 21:08
by BGM
Hi, Pulover. Does this new toolbar have a configurator? Majkenator's toolbar.ahk from the forms framework had a configuration window that would allow you to add and remove buttons.
Re: [Class] Toolbar - Create and modify
Posted: 20 Nov 2013, 21:18
by Pulover
Hi BGM,
It does. Check out the Customize() method and the demo script to know how to implement it.
Re: [Class] Toolbar - Create and modify
Posted: 20 Nov 2013, 22:14
by BGM
Thanks, Pulover - I played with it and it works fine. Figured out how to add a Customize button to the demo in less than 10 minutes!
The demo is wonderful, by the way.
Maybe you should add the Customize button to the demo, too?
Re: [Class] Toolbar - Create and modify
Posted: 21 Nov 2013, 06:42
by Pulover
I didn't use the Customize method in the demo because I used CCS_ADJUSTABLE to show it when you double-click on an empty area of the toolbar. But I might add a button for the method too. Thanks.
Re: [Class] Toolbar - Create and modify
Posted: 21 Nov 2013, 21:21
by BGM
Pulover, I am trying to adjust my script to use your class instead of the older forms framework toolbar.ahk.
The gosubs I am using detect whether the user held the shift key when they were called.
However, it seems that when I use this with the class_toolbar, the modifier keys get lost.
Here is what I have (the forum is escaping all my parentheses within the code-block, by the way....):
Spoiler
I put this in the main sub where the toolbar is built (after it is constructed):
And that worked. The script would call the function instead of the toolbar calling the function, and so the keyboard modifiers didn't get lost.
What do you recommend?
Re: [Class] Toolbar - Create and modify
Posted: 21 Nov 2013, 21:25
by BGM
Also, Pulover, in my own script, when I call hMYtoolbar.Customize(), the customize window appears for a second and then goes away. I can see the buttons just fine on my toolbar, and they work well enough (except for what I mentioned in my other post), but the customizer is wrong. I confirm that 0x0020 is present in the toolbars options. What can I do?
Re: [Class] Toolbar - Create and modify
Posted: 21 Nov 2013, 22:25
by BGM
Pulover, sorry to be so noisy, but I've another problem. And this one is a bit strange.
Spoiler
I have a bunch of gosubs that I name by number, say 101, 102, 103, 201, 202, 203
Now, if I create an array for the buttons to be inserted, all is well if I do this:
then it starts doing weird things: it won't show the tooltip for 101, and the tooltip for 201 is what 101 ought to be. However, the icons are still correct.
So it looks like the tooltip mechanism doesn't like similar numbers. It confuses 201 with 101 even though they are two different labels in the script.
I think this is a bug somewhere.
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 03:05
by Chef
Hello Pulover,
I don't think autoResize resizes the width to fit buttons.
Is it meant to do that?
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 07:51
by Pulover
BGM wrote:Pulover, I am trying to adjust my script to use your class instead of the older forms framework toolbar.ahk.
The gosubs I am using detect whether the user held the shift key when they were called.
However, it seems that when I use this with the class_toolbar, the modifier keys get lost.
What do you recommend?
Well, you didn't give me an example to try so I don't know how you're doing this check. I've tested here with a sample script and I could detect the shift key pressed on the target label.
#NoEnv
#SingleInstance, Force
#Include <Class_Toolbar>
; Create an ImageList.
ILA := IL_Create(4, 2, True)
IL_Add(ILA, "shell32.dll", 127)
IL_Add(ILA, "shell32.dll", 128)
IL_Add(ILA, "shell32.dll", 129)
IL_Add(ILA, "shell32.dll", 130)
; TBSTYLE_FLAT := 0x0800 Required to show separators as bars.
; TBSTYLE_TOOLTIPS := 0x0100 Required to show Tooltips.
Gui, Add, Custom, ClassToolbarWindow32 hwndhToolbar 0x0800 0x0100
Gui, Show,, Test
; Initialize Toolbars.
; The variable you choose will be your handle to access the class for your toolbar.
MyToolbar := New Toolbar(hToolbar)
; Set ImageList.
MyToolbar.SetImageList(ILA)
; Add buttons.
MyToolbar.Add("", "Label1=Button 1:1", "Label2=Button 2:2", "Label3=Button 3:3", "Label4=Button 4:4")
; Removes text labels and show them as tooltips.
MyToolbar.SetMaxTextRows(0)
; Set a function to monitor the Toolbar's messages.
WM_COMMAND := 0x111
OnMessage(WM_COMMAND, "TB_Messages")
; Set a function to monitor notifications.
WM_NOTIFY := 0x4E
OnMessage(WM_NOTIFY, "TB_Notify")
return
; This function will receive the messages sent by both Toolbar's buttons.
TB_Messages(wParam, lParam)
{
Global ; Function (or at least the Handles) must be global.
MyToolbar.OnMessage(wParam) ; Handles toolbar's messages.
}
; This function will receive the notifications.
TB_Notify(wParam, lParam)
{
Global ; Function (or at least the Handles) must be global.
ReturnCode := MyToolbar.OnNotify(lParam) ; Handles notifications.
return ReturnCode
}
; Your labels.
Label1:
Label2:
Label3:
Label4:
If GetKeyState("Shift", "P")
GoSub, ShiftLabel
Else
MsgBox, You selected %A_ThisLabel%
return
ShiftLabel:
MsgBox, You selected %A_ThisLabel%
return
F1::MyToolbar.Customize()
GuiClose:
ExitApp
return
BGM wrote:Also, Pulover, in my own script, when I call hMYtoolbar.Customize(), the customize window appears for a second and then goes away. I can see the buttons just fine on my toolbar, and they work well enough (except for what I mentioned in my other post), but the customizer is wrong. I confirm that 0x0020 is present in the toolbars options. What can I do?
I forgot to add a note that this method requires OnNotifiy() implemented to work. The demo above shows a simple way to use it.
BGM wrote:Pulover, sorry to be so noisy, but I've another problem. And this one is a bit strange.
Spoiler
I have a bunch of gosubs that I name by number, say 101, 102, 103, 201, 202, 203
Now, if I create an array for the buttons to be inserted, all is well if I do this:
then it starts doing weird things: it won't show the tooltip for 101, and the tooltip for 201 is what 101 ought to be. However, the icons are still correct.
So it looks like the tooltip mechanism doesn't like similar numbers. It confuses 201 with 101 even though they are two different labels in the script.
I think this is a bug somewhere.
In order to trigger an action the toolbar buttons are assigned to a CommandID, which is sent in a WM_COMMAND message. I didn't want to have to care about assigning those codes manually so I've created a function (StringToNumber()) that converts the label into a (possibly) unique code number. I don't recommend using labels that contain only numbers, not for toolbars nor for any project you're working on. Make them at least begin with a letter like L101. Or you can modify the function on the class to fit your needs.
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 07:55
by Pulover
Chef wrote:Hello Pulover,
I don't think autoResize resizes the width to fit buttons.
Is it meant to do that?
Maybe you need CCS_NORESIZE (0x0004) and CCS_NOPARENTALIGN (0x0008) styles on your toolbar. Without them the toolbar is positioned and sized automatically to the gui.
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 09:39
by BGM
Say, that simple_toolbar.ahk example is valuable! It provides an easy template to go by and quickly get results using your class script. I recommend posting it at the head of the thread along with the demo!
Pulover, adding the OnNotify fixed the customization window (thank you!).
Pulover, I understand what you mean about not using numbers as labels - but I've build my whole project to work by dynamically cycling through the numbers and then building variables from them. I'm not sure I want to re-figure out my code to undo that...
So I changed the StringToNumber() function to just return the parameter without doing anything to it.
And I also changed the Export function to use "|" as a separator instead of ", ". I'm not sure if that made any difference, but my button text issue seems to have cleared up!
What is happening is that it will detect for "no modifier" and "control" but not for "shift" - when I say it won't detect, I mean that the messagebox doesn't even fire when I push shift. But it works fine for control. Strange, no? But if I try the same function whilst called from a hotkey instead of from the toolbar, it works perfectly. So something with the toolbar is causing shift not to be detected. I suppose it's the same thing that mixes up the button text. (I know this is hard to troubleshoot!)
**edit**
Ah, I've noticed something. If I shift+click the button, it makes certain separators in the toolbar appear and disappear - after that, the shift-function fires fine. So I think what is happening is that shift+click causes the toolbar to enter an editing mode.
Okay, after I removed CCS_ADJUSTABLE then this problem went away!
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 10:54
by Chef
Those options have no effect when it comes to autoSizing width. You can see that yourself by adding +border option in your example.
But since I have TB library I just call TB_AUTOSIZE() which works like a charm.
TB_AUTOSIZE(hToolbar, Align="fit") {
PtrType:= A_PtrSize ? "Ptr" : "UInt" ; use x64-compatible type if running AHK_L
if (align != "") {
dhw:= A_DetectHiddenWindows
DetectHiddenWindows,on
TB_GETMAXSIZE(hToolbar, w, h)
SysGet, f, 8 ;SM_CYFIXEDFRAME , Thickness of the frame around the perimeter of a window that has a caption but is not sizable
SysGet, c, 4 ;SM_CYCAPTION: Height of a caption area, in pixels.
hParent:= DllCall("GetParent", PtrType, hToolbar)
WinGetPos, ,,pw,ph, ahk_id %hParent%
if Align = fit
ControlMove,,,,%w%,%h%, ahk_id %hToolbar%
else if Align = tr
ControlMove,,pw-w-f,c+f+2,%w%,%h%, ahk_id %hToolbar%
else if Align = tl
ControlMove,,f,c+f+2,%w%,%h%, ahk_id %hToolbar%
else if Align = br
ControlMove,,pw-w-f,ph-h-f,%w%,%h%, ahk_id %hToolbar%
else if Align = bl
ControlMove,,,ph-h-f,%w%,%h%, ahk_id %hToolbar%
DetectHiddenWindows, %dhw%
}
else SendMessage,0x0421,,,,ahk_id %hToolbar%
}
TB_GETMAXSIZE(hToolbar, ByRef Width, ByRef Height) {
VarSetCapacity(SIZE, 8)
SendMessage, 0x0453, 0, &SIZE, , ahk_id %hToolbar%
res:= ErrorLevel, Width:= NumGet(SIZE), Height:= NumGet(SIZE, 4)
return res
}
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 11:54
by Pulover
BGM wrote:
Okay, after I removed CCS_ADJUSTABLE then this problem went away!
Good catch! I'll see what I can do about the tooltips when I have more time.
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 12:02
by Pulover
Chef wrote:Those options have no effect when it comes to autoSizing width. You can see that yourself by adding +border option in your example.
But since I have TB library I just call TB_AUTOSIZE() which works like a charm.
I haven't tested yet but maybe there's a bug in the method. This wouldn't be the only bug in Microsoft common controls... I've used more than one workaround by majkinetor.
If you're using the toolbar with a resizable gui you might be interested in using a Rebar.
Upon program launch, the script (in my opinoin) should work like this:
Add all the possible buttons - of course, the coder has to add the routine to do that. That way, if there is an update of the script, the new buttons are available.
Layouts would consist only of visible buttons. The script would load a layout, and when a button is added, the script should check to see if the button exists before adding it - if it exists, the button's properties get updated (visibility, perhaps - whatever is set in the add() function's options).
THEN, since all the buttons are added at the start, there is no reason to save hidden buttons in the export. It seems to be less processing to just save visible buttons in the layout.
What do you think, Pulover?
Re: [Class] Toolbar - Create and modify
Posted: 22 Nov 2013, 14:37
by BGM
Also, what is the difference between using myToolbar.export() and a layout? It seems that a layout is the same thing. If I export the current button set to a different key in the ini file, isn't that the same thing as saving a layout? That's what I understand from the demo, anyway.