PDA

View Full Version : Solved: Custom Floating Menu Bar



Anne Troy
09-23-2004, 09:42 AM
How can I edit the code in this KB entry to make a floating menu bar, instead of one that sits on the default menu bar?

http://www.vbaexpress.com/kb/getarticle.php?kb_id=14

:)

Anne Troy
09-23-2004, 09:48 AM
I did try:

CommandBars("St&andards").Position = msoBarFloating


But it didn't change anything when I closed and reopened the doc.

mdmackillop
09-23-2004, 11:12 AM
A workaround.

Add the following at the end of the DocumentOpen sub

CommandBars.Add(Name:="MyMacros").Visible = True
CommandBars("Menu Bar").Controls(11).Copy Bar:=CommandBars("MyMacros")

mdmackillop
09-23-2004, 11:44 AM
BTW, The signature macros would not run in 2000 until the extraneous spaces were deleted.

eg
from
A(1) = Array("Suat's Signature " , " Ozgur " , 92)
to
A(1) = Array("Suat's Signature", "Ozgur", 92)

Were the spaces deliberate, or created by the KB?

MD

Anne Troy
09-23-2004, 12:03 PM
I don't know, but I'm not using those anyway...

mdmackillop
09-23-2004, 02:57 PM
Hi DB,
This should do the trick. I knew nothing about toolbar manipulation before, so well worth the effort! Replace the Document Open macro as follows:

Private Sub Document_Open()
'The Dim statements make the rest of the code easier to create.

Dim Mybar As CommandBar
Dim cmd As CommandBarPopup
Dim i As Integer
Dim A(12) As Variant
Dim Check

CustomizationContext = ActiveDocument.AttachedTemplate

On Error Resume Next
'This checks if the menu already exists. If it does, it does not create a new one.

Check = CommandBars("MyMacros").Position

Set Mybar = CommandBars.Add(Name:="MyMacros", _
Position:=msoBarFloating, Temporary:=True)

If Not Err.Number = 0 Then

'Note that the parts of the array are ( " Title of menu option " , " Macro to Run " , FaceID for toolbar button)

A(1) = Array("Suat's Signature", "Ozgur", 92)
A(2) = Array("Anne's Signature", "Smith", 85)
A(3) = Array("Nancy's Signature", "Johnson", 89)
A(4) = Array("Dreamboat's Signature", "Dreamboat", 80)
A(5) = Array("Mickey's Signature", "Mouse", 98)
A(6) = Array("Insert Photo", "InsPic", 280)
A(7) = Array("Fix Picture", "FixPix", 1363)
A(8) = Array("Add Photo Heading", "PhotoCont", 314)
A(9) = Array("Insert Stopping Point", "StopPoint", 2528)
A(10) = Array("Find Last Stopping Point", "StartHere", 2526)
A(11) = Array("Print Just This Page", "PrtPg", 159)
A(12) = Array("Insert Landscape Page", "InsertLand", 6)


Mybar.Visible = True
Set Mytasks = Mybar.Controls.Add(Type:=msoControlPopup)
Mytasks.Caption = "Te&mplates"

'The ampersand (&) in the name of the menu underlines the letter that follows it to give
'it a keyboard command (Alt-m) as many menus have.

With CommandBars("MyMacros").Controls("Te&mplates").Controls
For i = 1 To UBound(A)
Set myButton = .Add(Type:=msoControlButton)
With myButton
.Caption = A(i)(0)
.OnAction = A(i)(1)
.FaceId = A(i)(2)
End With
Next i
End With

Else
End If


End Sub

and change Document Close to
Private Sub Document_Close()

'This closes the MyMacros toolbar when the document is closed. It also keeps the user from
'changing the template. This is what we call an *on-event* procedure (macro) because it is
'run when the document is closed.

On Error Resume Next
CommandBars("MyMacros").Delete
ActiveDocument.AttachedTemplate.Saved = True

End Sub

Anne Troy
09-23-2004, 03:15 PM
Thank you, sweetie! Tho I prolly won't get to check it until late, late tonight or tomorrow. :(

But I will letcha know!

Jacob Hilderbrand
09-23-2004, 04:03 PM
I prolly won't get to check it until late, late tonight or tomorrow.

Unacceptable!! Check it now!! :whip

:)

mdmackillop
09-23-2004, 04:19 PM
My email read:

Here is the message that has just been posted:
Unacceptable!! Check it now!! ;Whip

I thought it was a comment on my coding!!!!:yes

TonyJollans
09-23-2004, 04:50 PM
I was going to post some code but when I came back MD had already done it, so all I have to say is that the code doesn't run with Option Explicit - it needs (at least) a declaration of myButton. Should we change it in the KB?

Anne Troy
09-23-2004, 05:30 PM
No. Let's leave it wrong.

ROFL!!

Don't worry. I'll fix it tomorrow. I do recall having problems...

Jacob Hilderbrand
09-23-2004, 06:27 PM
Yeah, all variables should be declared and Option Explicit used in all code.

EricFletcher
09-24-2004, 04:50 AM
Very nice code mdmackillop! I have wondered if it would be possible to bring together bits and pieces of various toolbars I've cadged together from assorted projects over the years. Seeing this gives me hope.

So how should the Mytasks and myButton variables be defined? I wasn't sure what data type to use (Dim myButton As ???). It does work without specifying a data type and I assume (by process of elimination mainly) that it would be either Variant or Object. Is there any advantage to using an explicit data type?

mdmackillop
09-24-2004, 06:07 AM
Hi Eric,
All credit goes to Smozgur (see link in fist thread).
Re the variable, I would go along with defining them, with the correct values if known, but I'm a bit unclear on some of these also. Trial and error!
MD

TonyJollans
09-24-2004, 06:40 AM
Hi Eric,

It's almost always better to use explicit data types.
In this case myButton could be CommandBarControl or, better, CommandBarButton (the Type:=msoControlButton is a bit of a giveaway).

If you don't know what type to use for an object, you can use the TypeName Function after it's been set, for example

Dim myObject
Set myObject = CommandBars(1).Controls(1)
Msgbox TypeName(myObject)

Zack Barresse
09-24-2004, 09:09 AM
Don't forget about the popup ...

CommandBarPopup

:)

Anne Troy
09-24-2004, 09:18 AM
Okay. I'll be working on the menu this weekend. May need some other code help too. If anybody is going to be around and wants to make a few sheckles... it'd be nice to know who's willin'. :)

mdmackillop
09-24-2004, 10:24 AM
I've added Option Explicit and split off the button naming to another sub to give some menu options on the toolbar.

TonyJollans
09-24-2004, 10:45 AM
Well, if there's sheckels in it .... :)

Seriously, I'll be around

Anne Troy
09-24-2004, 10:46 AM
Cool. :D

Anne Troy
09-27-2004, 06:46 AM
Okay. The Grandson decided to stay this weekend so, of course, I didn't get much done. He's 19 months old. :)

I'm back on it now. (No whip-cracking, Jake!)

Anne Troy
09-27-2004, 07:21 AM
According to the MVPs, I ought to be able to use a dialog:

With Dialogs(wdDialogFormatBordersAndShading)
.ApplyTo = 3
.Shadow = 0
.Shading = 0
.Foreground = 0
.Background = 0
.LeftStyle = 0
.RightStyle = 0
.TopStyle = 0
.BottomStyle = 0
.HorizStyle = 0
.VertStyle = 0
.Execute
End With

instead of this:
With .Borders(wdBorderLeft)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderRight)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderTop)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderBottom)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderHorizontal)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderVertical)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth050pt
.Color = wdColorAutomatic
End With
.Borders(wdBorderDiagonalDown).LineStyle = wdLineStyleNone
.Borders(wdBorderDiagonalUp).LineStyle = wdLineStyleNone
.Borders.Shadow = False
End With

But I don't see how to edit the dialogs to provide the formatting I want, prolly 'cause I wanna put borders on, not take them off.

Anybody care to help me figure out how to do that? :D

Anne Troy
09-27-2004, 07:36 AM
Okay. I want to set the heading rows on the first row of a table, but all I can find is toggle:

Selection.Rows.HeadingFormat = wdToggle

:(

Anne Troy
09-27-2004, 07:41 AM
The users of this template may sometimes be working with the document already unprotected. How can I make a macro like the following do something like "if protected, unprotect, otherwise...don't unprotect first":

Sub SetTblTxt()
ActiveDocument.Unprotect Password:="password"
Selection.Style = ActiveDocument.Styles("TableText")
ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:="password"
End Sub

TonyJollans
09-27-2004, 07:43 AM
OK, the easy one fiirst.

Use True (or False) in place of wdToggle to set, rather than switch, the heading rows.

Anne Troy
09-27-2004, 07:49 AM
Thanks!! :D

Anne Troy
09-27-2004, 08:39 AM
How can I add some error handling? I.e., if the document is protected, "the doc is protect, you gotta unprotect before you can do this", ok/cancel.

It's yelling at me when I try this:
Sub InsTable()
' Application.ScreenUpdating = False
' ActiveDocument.Unprotect
If ActiveDocument.Protection = True Then MsgBox ("You must unprotect the document first.")
Else
Selection.TypeText Text:=" intable"
Selection.Range.InsertAutoText
End If

End Sub

I know it's something stupid!

TonyJollans
09-27-2004, 08:45 AM
I'm trying to answer as quickly as you ask!

You can use some of the same constants with the dialog that you can with the individual borders, so ...

With Dialogs(wdDialogFormatBordersAndShading)
.ApplyTo = 3

.Shadow = False

.LeftWeight = wdLineWidth050pt
.LeftStyle = wdLineStyleSingle

.RightWeight = wdLineWidth050pt
.RightStyle = wdLineStyleSingle

.TopWeight = wdLineWidth050pt
.TopStyle = wdLineStyleSingle

.BottomWeight = wdLineWidth050pt
.BottomStyle = wdLineStyleSingle

.TL2BRStyle = wdLineStyleNone
.TR2BLStyle = wdLineStyleNone

.HorizWeight = wdLineWidth050pt
.HorizStyle = wdLineStyleSingle

.VertWeight = wdLineWidth050pt
.VertStyle = wdLineStyleSingle

.Execute
End With

... will do something. :rofl

Most of this, however, is not documented and I don't know the values for the ApplyTo (wdTable doesn't seem to work).

Note, also, that invoking the dialog changes ALL the settings that the dialog can change and there is no simple default value for many of the options - they may reflect the characteristics of the selection, or they may remember what they were last time they were used so you may find you have to explicitly set many or all of them, whereas with the individual property settings you only set the ones you want, so it's a bit of gain on the one hand and loss on the other.

Good to see the grandson's firmly in charge, by the way. ;)

TonyJollans
09-27-2004, 08:55 AM
I think you want


ActiveDocument.ProtectionType

but I'm not sure of all the values off the top of my head

Anne Troy
09-27-2004, 08:56 AM
I also have some code that formats the table at the insertion point. How can I tell it to throw up a message box "you gotta have your cursor in a table first, you dumbass"? if the cursor isn't in a table. Do I just do an On Error thingee? Will that cover it okay?

mdmackillop
09-27-2004, 09:39 AM
Hi DB,
You have to insert a break after "Then" otherwise the If line is regarded as complete (no end if required). The next bit is then being seen as missing a stating "If".




Sub InsTable()
Dim MyAutoText As String
MyAutoText = "Val" 'Amend as required

If Not ActiveDocument.ProtectionType = wdNoProtection Then
MsgBox ("You must unprotect the document first.")
Else
Selection.TypeText Text:=" intable"
NormalTemplate.AutoTextEntries(MyAutoText).Insert Where:=Selection.Range
End If
End Sub

Anne Troy
09-27-2004, 10:00 AM
That makes it look for autotext where it doesn't exist?
I have many autotext entries RIGHT IN the template.
Do I have to dim every time?

Anne Troy
09-27-2004, 10:34 AM
Phew. Okay. I've got the IF working right.

But now, when I run the autotext entry normally, I get what I want.

When I run it with the macro, I get a space, a paragraph return, and THEN the autotext entry. Anybody know why?
Here's the code I'm using:

Sub InsTable()

If Not ActiveDocument.ProtectionType = wdNoProtection Then
MsgBox ("You must unprotect the document first.")
Else
Selection.TypeText Text:=" intable"
Selection.Range.InsertAutoText
End If
End Sub

TonyJollans
09-27-2004, 11:05 AM
OK, we'll go for the easy one first again :)

To tell if the cursor is in a table, use

selection.Information (wdWithInTable)

it returns True or False - I'm sure you can work out which is which - lol

mdmackillop
09-27-2004, 12:16 PM
Sorry DB,
I misunderstood your autotext entry (been a long day):blush . However, I don't get your behavior with your revised coding. The space I understand, but not the paragraph mark. Can you attach your Doc, and I'll see if it replicates here.
MD

Anne Troy
09-27-2004, 03:02 PM
Okay. I've got this thing sorted, I think. I'll share the code with anybody who wants it, but don't want to put it in the open forum.

The only problem I have now is that, while I want the toolbar to float, it's smack-dab in the middle of the document window. Any way I can get it to be off to the side or something? I've tried moving it in the template and everything. Doesn't seem to matter much. For the most part, I'm using MD's code for the toolbar--close enough.

mdmackillop
09-27-2004, 03:34 PM
A small addition to allow setting of the toolbar position
Add the following at the head of the code:
Option Explicit
Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1

Function ScrWidth() As Long
ScrWidth = GetSystemMetrics(SM_CXSCREEN)
End Function

Function ScrHeight() As Long
ScrHeight = GetSystemMetrics(SM_CYSCREEN)
End Function




Insert the following at the MyBar.Visible line

Mybar.Visible = True
With Mybar
.Top = ScrHeight * 0.3 'Set fraction as appropriate
.Left = ScrWidth * 0.3
End With


You can, if preferred, omit the first code and insert integer positions for the toolbar.

TonyJollans
09-27-2004, 03:46 PM
You can position a floating command bar with the .Top and .Left properties (possibly combined with the .Width or .Height ones). These are in pixels from the top and left of the screen (not the window) so if you want thm in a non-full screen window you'll need to check the window co-ordinates first (and the screen resolution). For example, running at 1280*1024, this creates a vertical commandbar at the side of a full screen document for me:

CommandBars("MyMacros").Left = 1220
CommandBars("MyMacros").tOP = 160
CommandBars("MyMacros").Width = 40

Depending on your ultimate requirement you may need to experiment to find what suits you.

Anne Troy
09-27-2004, 03:47 PM
Too cool. :D
Worked like a charm.
I'm marking this one solved.

Anne Troy
09-27-2004, 03:48 PM
Oops. Didn't even try yours, Tony... :)

TonyJollans
09-27-2004, 03:52 PM
You don't need an API to get screen resolution. You can use ...

System.HorizontalResolution and
System.VerticalResolution

TonyJollans
09-27-2004, 03:54 PM
I like the idea of using a fraction of the screen though - I never thought of that :)

mdmackillop
09-27-2004, 03:54 PM
If you want the "tall" toolbar, as per Tony's example, add MyBar.Width = 40 as the last line in the macro, otherwise it gets reset when buttons are added

mdmackillop
09-27-2004, 03:56 PM
Having opened some of my UserForms on an 800 x 600 display, I knew I had to find a flexible solution!

TonyJollans
09-27-2004, 03:58 PM
Incidentally, toolbar settings are user-level, held in the registry - you can't control their location by template, except by using code to position them at document new or document open.

Anne Troy
09-27-2004, 04:03 PM
That's when we're implementing the toolbars, Tony.

I don't know how to change MD's code to *not* be an API call though.

mdmackillop
09-27-2004, 04:05 PM
I never noticed your previous post Tony; I must look into these System items, I searched the help for ages to find the API method. I would go with Tony's Version and delete the API

With Mybar
.Top = System.VerticalResolution * 0.3
.Left = System.HorizontalResolution * 0.3
End With

Anne Troy
09-27-2004, 04:14 PM
Sweet. 0.2 was perfect

mdmackillop
09-27-2004, 04:17 PM
Interested to see the "final product"! Will you email me a copy please.
MD

Bilby
09-27-2004, 11:14 PM
Grits 'n Sals

I must admit that when I began my project the traditional Toolbar was easier for me than to learn than creating commandbars in code. But I was just wondering if their was an advantage of creating them in code, given that mine a templates operating in Word as distinct from a VB program using Application.Word

Anne Troy
09-27-2004, 11:20 PM
I just know that when they're NOT built using code, people complain "the toolbar doesn't go with the template" and "the toolbar is left after I close the doc" and stuff like that. I have just always understood that building toolbars in code is much more stable.

MD, I didn't see your post before, sorry. Sending. :)

mdmackillop
09-28-2004, 12:15 AM
Looks good DB!