MS Office Forum / Word / Programming / October 2005
Toggle macro button
|
|
Thread rating:  |
Guillermo - 17 Oct 2005 17:47 GMT Hello all,
I'd like to know how a macro button can be turned into a toggle, like the bold button in the format bar, for example.
TIA,
Guillermo
Greg - 17 Oct 2005 18:12 GMT Guillermo,
I has nothing to do with the button but with the code the button causes to execute. For example, if you assigned the following code to a macrobutton, toolbar button, menu item, shortcut key, etc., it would toggle text formatted with automatic font color to red font color or red font color to automatic.
Sub Toggle() Dim oState As Long oState = Selection.Range.Font.Color If oState = -16777216 Then Selection.Range.Font.Color = 255 ElseIf oState = 255 Then Selection.Range.Font.Color = -16777216 End If End Sub
The numbers associated with font colors can be determined using the object browser and search for wdColor.
Guillermo - 17 Oct 2005 21:48 GMT I see, so it all comes down to a conditional statement. I thought it was something else.
Thank you very much, Greg.
> Sub Toggle() > Dim oState As Long [quoted text clipped - 5 lines] > End If > End Sub Charles Kenyon - 17 Oct 2005 23:43 GMT You _can_ also change the appearance of the button, but this is a real change in your toolbar, not just the button state.
 Signature Charles Kenyon
Word New User FAQ & Web Directory: http://addbalance.com/word
Intermediate User's Guide to Microsoft Word (supplemented version of Microsoft's Legal Users' Guide) http://addbalance.com/usersguide
See also the MVP FAQ: http://word.mvps.org/FAQs/ which is awesome! --------- --------- --------- --------- --------- --------- This message is posted to a newsgroup. Please post replies and questions to the newsgroup so that others can learn from my ignorance and your wisdom.
>I see, so it all comes down to a conditional statement. I thought it was >something else. [quoted text clipped - 10 lines] >> End If >> End Sub Klaus Linke - 19 Oct 2005 22:47 GMT I wouldn't put it that way ;-)
With CommandBars.ActionControl .State = Not (.State) End With
Regards, Klaus
> You _can_ also change the appearance of the button, but this is a real > change in your toolbar, not just the button state. [quoted text clipped - 12 lines] >>> End If >>> End Sub Charles Kenyon - 20 Oct 2005 02:46 GMT Guess I don't know how to create buttons that have multiple states. I know it works with the built-in ones.
 Signature Charles Kenyon
Word New User FAQ & Web Directory: http://addbalance.com/word
Intermediate User's Guide to Microsoft Word (supplemented version of Microsoft's Legal Users' Guide) http://addbalance.com/usersguide
See also the MVP FAQ: http://word.mvps.org/FAQs/ which is awesome! --------- --------- --------- --------- --------- --------- This message is posted to a newsgroup. Please post replies and questions to the newsgroup so that others can learn from my ignorance and your wisdom.
>I wouldn't put it that way ;-) > [quoted text clipped - 21 lines] >>>> End If >>>> End Sub Greg - 20 Oct 2005 12:40 GMT Klaus,
If you don't mind, have a look at the pictures of the toolbar I created for an addin. There are three images at the bottom of the page:
http://gregmaxey.mvps.org/Bookmark_Tool.htm
Before these I had one tool bar with all four buttons. Helmut suggested that I "dim" the "show" and "hide" buttons when the form was closed. I couldn't figure out how to do this so opted with the interactive style as shown. Unfortunately (and dimming may result the same) everytime the addin is used and then I closed Word it would trigger the "Do you want to save changes to BlahBlah.dot"
I got around that by adding a blahblah.dot Saved flag in the close routine.
Can you explain to us masses ;-) how to dim a command bar button and if that would eliminate the problem of Word asking to save changes to the addin?
Thanks
Klaus Linke - 24 Oct 2005 21:49 GMT Hi Greg,
DIMming the button won't get rid of your code "dirtying" the template, I'm afraid. If you want to ignore just the greying or toggling of the button, you can save/reset the .Saved state just for that piece of code.
If you don't know the template you'll put the code in (or want to be free to move it), this will get a bit difficult though, because you'll have to find out the template that's responsible for that special button.
Maybe I missed an easy way to determine the template that created the button (and saves any changes to it)... Anyway, the code below, looping all active templates, should work:
Dim myCBB As CommandBarButton Dim myButtonTemplate As Template, myTemplate As Template Dim boolSaved As Boolean ' If the code is in the macro is the one that is run by the button: Set myCBB = CommandBars.ActionControl ' Which template put that button there anyway? For Each myTemplate In Application.Templates If myCBB.Parent.Context = myTemplate.FullName Then Set myButtonTemplate = myTemplate End If Next myTemplate boolSaved = myButtonTemplate.Saved ' Do your dirty work... myCBB.State = Not (myCBB.State) ' myCBB.Enabled = Not (myCBB.Enabled) ' ... and then reset the .Saved state: myButtonTemplate.Saved = boolSaved
It would be nice if you could wrap that in a macro that toggles any button: Call ToggleButtonState(myCBB) (without changing the .Saved state of the template it comes from) ... but I don't think you can pass controls as arguments. Would be great if someone knows how to do that!
Regards, Klaus
> Klaus, > [quoted text clipped - 18 lines] > > Thanks Greg Maxey - 24 Oct 2005 23:17 GMT Klaus,
Thanks.
Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Hi Greg, > [quoted text clipped - 59 lines] >> >> Thanks Tony Jollans - 25 Oct 2005 00:53 GMT Hi Klaus,
1. Providing the CommandBar belongs to a Template you can (using your variable names) ..
Set myButtonTemplate = Templates(myCBB.Parent.Context)
(If it belongs to a document then use Documents(myCBB.Parent.Context) of course)
2. I don't have any problem passing a button to a procedure something like this (to toggle any boolean property)
Sub ToggleState(myControl As CommandBarControl, myState As String)
Dim SavedState As Boolean Dim OldState As Boolean Dim ControlTemplate As Template
Set ControlTemplate = Templates(myControl.Parent.Context) SavedState = ControlTemplate.Saved
OldState = CallByName(myControl, myState, VbGet) CallByName myControl, myState, VbLet, Not OldState
ControlTemplate.Saved = SavedState Set ControlTemplate = Nothing
End Sub
which can be called like
ToggleState myCBB, "Enabled"
Greg .. Note (if you didn't pick it up from Klaus' post) it is the Enabled property which controls dimming.
-- Enjoy, Tony
> Hi Greg, > [quoted text clipped - 60 lines] > > > > Thanks Greg Maxey - 25 Oct 2005 01:15 GMT Tony,
Yes I did pick that up. I decided that for my purposes I liked the show/hide approach better.
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Hi Klaus, > [quoted text clipped - 99 lines] >>> >>> Thanks Greg Maxey - 25 Oct 2005 01:44 GMT Tony,
Your code is a bit over my head. Could you provide a little more detail as to how I would create the toolbar with a button to be enabled and disabled and then actually enabled and disabled using your code?
Thanks.
 Signature Greg Maxey/Word MVP (who freely admits he still has a lot to learn) See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Hi Klaus, > [quoted text clipped - 99 lines] >>> >>> Thanks Tony Jollans - 25 Oct 2005 02:14 GMT Hi Greg,
You create the toolbar as normal. You can use my code with your existing toolbar.
Drop the Sub into your template somewhere (do you have a module for common routines? No, you don't - I've just looked so drop it into the Bookmarker module)
Then when you want to change one of your buttons call it. For example, you could change your Sub Hide() like this:
Sub Hide() oFrm.Hide ToggleState CommandBars("Bookmarker").Controls("Show"), "Visible" ToggleState CommandBars("Bookmarker").Controls("Hide"), "Visible" End Sub
That simply toggles the visible state of each of the two controls - assuming the Hide one is visble and the Show one isn't, then it will change it so that the Show one is visible and the Hide one isn't.
What the code does is grab a reference to the template which 'owns' the control and saves the "Saved" setting. Then it gets the (in this example, Visible) setting of the control and sets it to the opposite. Then it resets the Saved property of the template to what it saved before, releases the template object and that's it. All you have to do is pass it a reference to the control and the name of the property as a string - it will work for any boolean property of a control (Visible, Enabled, State, etc.). The CallByName construct is just a way of using a string for a property name instead of having to code a reference to it - the string gets resolved at runtime instead of compile time.
-- Enjoy, Tony
> Tony, > [quoted text clipped - 113 lines] > >>> > >>> Thanks Greg Maxey - 25 Oct 2005 03:08 GMT Tony,
Ok thanks. I see how I could use this to toggle the show and hide buttons
Sub ToggleShowHide() ToggleState CommandBars("Bookmarker").Controls("Show"), "Visible" If CommandBars("Bookmarker").Controls("Hide").Visible = True Then oFrm.Hide Else oFrm.Show vbModeless End If ToggleState CommandBars("Bookmarker").Controls("Hide"), "Visible" End Sub
Sub ToggleState(myControl As CommandBarControl, myState As String) Dim SavedState As Boolean Dim OldState As Boolean Dim ControlTemplate As Template Set ControlTemplate = Templates(myControl.Parent.Context) SavedState = ControlTemplate.Saved OldState = CallByName(myControl, myState, VbGet) CallByName myControl, myState, VbLet, Not OldState ControlTemplate.Saved = SavedState Set ControlTemplate = Nothing End Sub
With both the Open/Close and Show/Hide buttons being set to toggle, I think I am going to play it safe and leave my code as is in this case. In the future I can keep this method in mind. For now I am going to stick with old saw "If it isn't broke, don't fix it." Thanks again.
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Hi Greg, > [quoted text clipped - 151 lines] >>>>> >>>>> Thanks Tony Jollans - 25 Oct 2005 09:45 GMT I agree - if it ain't broke don't fix it.
I'm not sure I'd actually use it in its current form - I just posted it in response to Klaus' post saying he didn't know how to do it.
-- Enjoy, Tony
> Tony, > [quoted text clipped - 188 lines] > >>>>> > >>>>> Thanks Greg Maxey - 25 Oct 2005 10:59 GMT Tony,
One more question. In setting up a toggle from scratch, I noticed that it is a little tough to get the initial conditions set up (i.e., one showing and one hidden). I created a new toolbar with two buttons, one "hide" and one "show" (of course) they are both showing and applied your code. When I clicked on either both are hidden. To get around this, I stetted out one of the calls, executed the code and the cleared the stet ('). Is there a more standard procedure?
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
>I agree - if it ain't broke don't fix it. > [quoted text clipped - 200 lines] >> >>>>> >> >>>>> Thanks Tony Jollans - 25 Oct 2005 11:10 GMT Hi Greg,
When you creat the buttons you need to create the initail state - one hidden and one shown.
That said, however, I think an optional parameter to my routine (True/False) to force a setting rather than simply toggle might be helpful, something like this (done quickly and not tested)
Sub ToggleState(myControl As CommandBarControl, myState As String, Optional mySetting)
Dim SavedState As Boolean Dim OldState As Boolean Dim ControlTemplate As Template
Set ControlTemplate = Templates(myControl.Parent.Context) SavedState = ControlTemplate.Saved
OldState = CallByName(myControl, myState, VbGet) ' .Enabled = Not cc.Enabled If Not IsMissing(mySetting) Then If TypeName(mySetting) = "Boolean" Then OldState = Not mySetting End If CallByName myControl, myState, VbLet, Not OldState
ControlTemplate.Saved = SavedState
End Sub
This will (I hope!) force True or False if given as a third parameter.
-- Enjoy, Tony
> Tony, > [quoted text clipped - 215 lines] > >> >>>>> > >> >>>>> Thanks Greg - 25 Oct 2005 14:30 GMT Tony,
<When you creat the buttons you need to create the initail state - one hidden <and one shown.
I created them by dragging then to a new toolbar. I suppose I could create the toolbar and the buttons with VBA and then achieve your statement.
You lost me with your new code. What is cc? What is mySetting?
Using the following as an example, how would you apply your new code?
Sub ToggleShowHide() ToggleState CommandBars("MyToggle").Controls("Bold On"), "Visible" If CommandBars("MyToggle").Controls("Bold Off").Visible = True Then ActiveDocument.Range.Bold = True Else ActiveDocument.Range.Bold = False End If
ToggleState CommandBars("MyToggle").Controls("Bold Off"), "Visible" End Sub Sub ToggleState(myControl As CommandBarControl, myState As String) Dim SavedState As Boolean Dim OldState As Boolean Dim ControlTemplate As Template Set ControlTemplate = Templates(myControl.Parent.Context) SavedState = ControlTemplate.Saved OldState = CallByName(myControl, myState, VbGet) CallByName myControl, myState, VbLet, Not OldState ControlTemplate.Saved = SavedState Set ControlTemplate = Nothing End Sub
Thanks
Tony Jollans - 25 Oct 2005 15:50 GMT Hi Greg,
Apologies - the cc is an overflow of a comment on the previous line which I should have deleted - it's the remnants of earlier code and not relevant at all. mySetting is also an overflow due to the line breaks added by the system. I have reformatted in the code below to stop that happening (I hope).
I just assumed you created your toolbar with VBA but if you've done it via the UI then you can't make a control hidden. I guess I'd do it with a one-off statement in the immediate window - whatever, it needs VBA.
The new code adds an optional override to the toggle setting so, for example, you could do ..
ToggleState CommandBars("Bookmarker").Controls("Hide"), "Visible", False
to force the setting of visible to false (i.e. hide the control) instead of toggling what was there before. myOverride might have been a better choice of name than mySetting.
The extra parameter is optional so that the original still worked, in other words ..
ToggleState CommandBars("Bookmarker").Controls("Hide"), "Visible"
still toggled the setting.
To use it (somewhat artificially) in your example you could be explicit in what you set rather than toggling. I think you've got the check wrong so I've changed it in this ..
Sub ToggleShowHide() ToggleState CommandBars("MyToggle").Controls("Bold On"), "Visible", False If CommandBars("MyToggle").Controls("Bold Off").Visible = False Then ActiveDocument.Range.Bold = True Else ActiveDocument.Range.Bold = False End If
ToggleState CommandBars("MyToggle").Controls("Bold Off"), "Visible", True End Sub
Sub ToggleState(myControl As CommandBarControl, _ myState As String, _ Optional mySetting)
Dim SavedState As Boolean Dim OldState As Boolean Dim ControlTemplate As Template
Set ControlTemplate = Templates(myControl.Parent.Context) SavedState = ControlTemplate.Saved
OldState = CallByName(myControl, myState, VbGet) If Not IsMissing(mySetting) Then If TypeName(mySetting) = "Boolean" Then OldState = Not mySetting End If CallByName myControl, myState, VbLet, Not OldState
ControlTemplate.Saved = SavedState
End Sub
It's your code, but I would actually do it more simply ..
Sub ToggleShowHide() With CommandBars("MyToggle") ActiveDocument.Range.Bold = .Controls("Bold On").Visible ToggleState .Controls("Bold On"), "Visible" ToggleState .Controls("Bold Off"), "Visible" End With End Sub
The possible permutations are endless - you could, perhaps, make the ToggleState procedure automatically toggle two buttons at a time (as that's what you're always doing - and probably always will) - or you could give it two buttons and tell it to ensure one is true, the other false, etc., etc. - the world, as they say, is your lobster (or something of the sort). As already agreed, if it works don't fix it.
-- Enjoy, Tony
> Tony, > [quoted text clipped - 33 lines] > > Thanks Greg - 25 Oct 2005 16:26 GMT Klaus Linke - 26 Oct 2005 00:18 GMT Hi Tony,
> Set myButtonTemplate = Templates(myCBB.Parent.Context) Aah, bingo! Thank you, I knew my code was overly complicated!
Though it probably had a logical error, too: Say an attached template or global template has added a button to some built-in toolbar, then the Parent would be Normal.dot, not that template. And I would want keep the template's .Saved flag clean, not Normal.dots.
> Sub ToggleState(myControl As CommandBarControl, myState As String) Strange, that is exactly what I tried yesterday. Not sure what I did wrong, but glad it does work as expected.
Thanks! Klaus
|
|
|