Can't figure out ControlBars collection

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

According to the VBA help guide I should be able to change a button's .state property so I can toggle it from "pressed" or down to up. I see that those states, which are really 0 or 1 are referenced (right word?) via constants msoButtonPressUp and msoButtonPressDown. But when I get the object (which I can see in the watch window of the debugger) and try to change to state I get a message that the method failed. Does Outlook treat command bars and buttons differently than other VBA apps?

I hope my message makes sense, since I'm really knew to this...

Thanks.
 
It might help if you showed a code snippet.
--
Sue Mosher, Outlook MVP
Author of
Microsoft Outlook Programming - Jumpstart for
Administrators, Power Users, and Developers



DaveH said:
According to the VBA help guide I should be able to change a button's
..state property so I can toggle it from "pressed" or down to up. I see that
those states, which are really 0 or 1 are referenced (right word?) via
constants msoButtonPressUp and msoButtonPressDown. But when I get the
object (which I can see in the watch window of the debugger) and try to
change to state I get a message that the method failed. Does Outlook treat
command bars and buttons differently than other VBA apps?
 
The help file says that the State property of built-in command bar buttons
is read-only; this is for all Office apps, Outlook included. Sorry man!

--
Eric Legault, B.A., MCP, MCSD, MVP - Outlook
Job: http://www.imaginets.com
Blog: http://blogs.officezealot.com/legault


DaveH said:
According to the VBA help guide I should be able to change a button's
..state property so I can toggle it from "pressed" or down to up. I see that
those states, which are really 0 or 1 are referenced (right word?) via
constants msoButtonPressUp and msoButtonPressDown. But when I get the
object (which I can see in the watch window of the debugger) and try to
change to state I get a message that the method failed. Does Outlook treat
command bars and buttons differently than other VBA apps?
 
Well, like I said, I'm new at this, but I think we must be reading two different help files... here is a cut/paste from the MS Visual Basic Help "State Property" page...

"State property as it applies to the CommandBarButton object

Returns or sets the appearance of a command bar button control. Read/write MsoButtonState.

The example shown on this page has the following snippet
"Set myControl1 = CommandBars("Custom").Controls(1
myControl1.State = msoButtonUp

But the error I get when I try this is
"Run-time error '-2147467259 (80004005)'
Method 'State' of object '_CommandBarButton' failed

So, I suspect Eric is right, and the Help file is wrong! However, wouldn't you agree the state of a button should be able to be programmatically set

Thanks...
 
Sorry... to clarify -- the buttons I'm trying to set are not default buttons. I created the toolbar and have the code I'm running attached to the buttons. Basically, I'm trying to toggle to status to provide visual status of the action the macro code invokes

Again, I apologize for what I'm sure are incorrect usages of terms..

----- DaveH wrote: ----

Well, like I said, I'm new at this, but I think we must be reading two different help files... here is a cut/paste from the MS Visual Basic Help "State Property" page...

"State property as it applies to the CommandBarButton object

Returns or sets the appearance of a command bar button control. Read/write MsoButtonState.

The example shown on this page has the following snippet
"Set myControl1 = CommandBars("Custom").Controls(1
myControl1.State = msoButtonUp

But the error I get when I try this is
"Run-time error '-2147467259 (80004005)'
Method 'State' of object '_CommandBarButton' failed

So, I suspect Eric is right, and the Help file is wrong! However, wouldn't you agree the state of a button should be able to be programmatically set

Thanks...
 
..Controls(1) will return a CommandBarControl object, which according
to the Object Browser has no .State property. You want to use a
CommandBarButton object, which does have a .State property, which is
read/write.

Make sure you always declare your object fully qualified so you get
the item type you want. If you don't declare fully qualified objects
you might get the wrong item type. Almost all of the examples in Help
don't properly declare their objects so they are subject to being the
wrong type, Variants or referencing the wrong object entirely
depending on what's available in your project references and the order
of the references in the project. For example if you are referencing
both CDO 1.21 and Outlook then AddressEntry is an ambiguous object.

When properly coded you can control the .State of a CommandBarButton.




DaveH said:
Sorry... to clarify -- the buttons I'm trying to set are not default
buttons. I created the toolbar and have the code I'm running attached
to the buttons. Basically, I'm trying to toggle to status to provide
visual status of the action the macro code invokes.
Again, I apologize for what I'm sure are incorrect usages of terms...

----- DaveH wrote: -----

Well, like I said, I'm new at this, but I think we must be
reading two different help files... here is a cut/paste from the MS
Visual Basic Help "State Property" page....
"State property as it applies to the CommandBarButton object.

Returns or sets the appearance of a command bar button control. Read/write MsoButtonState."

The example shown on this page has the following snippet:
"Set myControl1 = CommandBars("Custom").Controls(1)
myControl1.State = msoButtonUp"

But the error I get when I try this is:
"Run-time error '-2147467259 (80004005)':
Method 'State' of object '_CommandBarButton' failed"

So, I suspect Eric is right, and the Help file is wrong!
However, wouldn't you agree the state of a button should be able to be
programmatically set?
 
Thanks, Ken... I understand why this doesn't work now... But, I'm having trouble figuring out how to get a CommandBarButton object that is updateable. As you said, the help guide seems a little skimpy, but here's where I "think" I have to go, based on the Outlook Visual Basic Reference Help

"CommandBars Propert
Returns a CommandBars collection object that represents all the menus and toolbars in the Explorer or Inspector.
expression.CommandBar
expression Required. An expression that returns an Explorer or Inspector object.

Okay... but, the rest of that help page seems to get me in a loop (Explorer and Inspector are hyperlinks that keep referring back to themselves...). When I use the regular VB reference and look at Office Objects I see there is a CommandBars collection that has a CommandBarControls child collection, which in turn has three child objects (one of which is CommandBarButton). However, from there it appears to say I should use the Controls(1) to get the first button per the following

"Using the CommandBarButton Objec
Use Controls(index), where index is the index number of the control, to return a CommandBarButton object. (The Type property of the control must be msoControlButton.)

I set watches on all my objects and they appear to be the correct types right up thru the end, but I still get the failure in the last line of this code snippet
Dim objCommandBar As CommandBa
Dim myCmdBarBtn As CommandBarButto
Dim myOlApp As Applicatio
Set myOlApp = GetObject(, "Outlook.Application"
Set objCommandBar = myOlApp.ActiveInspector.CommandBars("Messages"
Set myCmdBarBtn = objCommandBar.Controls(1
If myCmdBarBtn.State = msoButtonUp The
myCmdBarBtn.State = msoButtonDow

Where do I go next




----- Ken Slovak - [MVP - Outlook] wrote: ----

..Controls(1) will return a CommandBarControl object, which accordin
to the Object Browser has no .State property. You want to use
CommandBarButton object, which does have a .State property, which i
read/write

Make sure you always declare your object fully qualified so you ge
the item type you want. If you don't declare fully qualified object
you might get the wrong item type. Almost all of the examples in Hel
don't properly declare their objects so they are subject to being th
wrong type, Variants or referencing the wrong object entirel
depending on what's available in your project references and the orde
of the references in the project. For example if you are referencin
both CDO 1.21 and Outlook then AddressEntry is an ambiguous object

When properly coded you can control the .State of a CommandBarButton
 
I tested a quickie Sub that creates a button on a toolbar and toggles
its .State property. No errors and no problems.

See if this helps you at all:

Sub testbutton()
Dim objCommandBar As Office.CommandBar
Dim myCmdBarBtn As Office.CommandBarButton
Dim myOlApp As Outlook.Application

Set myOlApp = GetObject(, "Outlook.Application")

Set objCommandBar =
myOlApp.ActiveInspector.CommandBars.Add("Messages", , , True)
objCommandBar.Visible = True
objCommandBar.Enabled = True

Set myCmdBarBtn = objCommandBar.Controls.Add(msoControlButton)
myCmdBarBtn.Caption = "test button"
myCmdBarBtn.Enabled = True
myCmdBarBtn.Visible = True

Set myCmdBarBtn = Nothing

Set myCmdBarBtn = objCommandBar.Controls(1)
If myCmdBarBtn.State = msoButtonUp Then
myCmdBarBtn.State = msoButtonDown
End If

End Sub





DaveH said:
Thanks, Ken... I understand why this doesn't work now... But, I'm
having trouble figuring out how to get a CommandBarButton object that
is updateable. As you said, the help guide seems a little skimpy, but
here's where I "think" I have to go, based on the Outlook Visual Basic
Reference Help:
"CommandBars Property
Returns a CommandBars collection object that represents all the
menus and toolbars in the Explorer or Inspector.
expression.CommandBars
expression Required. An expression that returns an Explorer or Inspector object."

Okay... but, the rest of that help page seems to get me in a loop
(Explorer and Inspector are hyperlinks that keep referring back to
themselves...). When I use the regular VB reference and look at
Office Objects I see there is a CommandBars collection that has a
CommandBarControls child collection, which in turn has three child
objects (one of which is CommandBarButton). However, from there it
appears to say I should use the Controls(1) to get the first button
per the following:
"Using the CommandBarButton Object
Use Controls(index), where index is the index number of the control,
to return a CommandBarButton object. (The Type property of the control
must be msoControlButton.)"
I set watches on all my objects and they appear to be the correct
types right up thru the end, but I still get the failure in the last
line of this code snippet:
 
Thanks, again, Ken... naturally, your code works without a hitch! And mine still doesn't..

There are two differences I see (for which there is no logical reason they would impact things)... (1) your command bar and buttons are built at run-time, and I'm referring to existing items (a bar and buttons I added manually using the View|Toolbars|Customize menu), and (2) the code I'm executing is launched by clicking on the button for which I'm trying to change the appearance.

This is my whole routine (seems simple enough)..
Sub SetReadReceipt(
Dim objCommandBar As Office.CommandBa
Dim myCmdBarBtn As Office.CommandBarButto
Dim myOlApp As Outlook.Applicatio
Dim myItem As MailIte
Set myOlApp = GetObject(, "Outlook.Application"
Set myItem = myOlApp.ActiveInspector.CurrentIte
Set objCommandBar = myOlApp.ActiveInspector.CommandBars("Messages"
Set myCmdBarBtn = objCommandBar.Controls(1) 'this is the button called 'Read Receipt
If myCmdBarBtn.State = msoButtonUp The
myCmdBarBtn.State = msoButtonDow
myItem.ReadReceiptRequested = "True
Els
myCmdBarBtn.State = msoButtonU
myItem.ReadReceiptRequested = "False
End I

End Su
 
So is the SetReadReceipt procedure called from the myCmdBarBtn Click
event (or the Click event of that button)?

If you are truly getting the handle for the correct toolbar and button
(check on that when you step the code) then I'd suggest trying passing
the button (Ctrl) to the SetReadReceipt procedure ByRef from the Click
event or just putting the SetReadReceipt procedure code inline to the
Click event handler. See if that helps.

Another thing to check is whether there might be more than 1
"Messages" toolbar in the CommandBars collection. That could throw
things off.




DaveH said:
Thanks, again, Ken... naturally, your code works without a hitch! And mine still doesn't...

There are two differences I see (for which there is no logical
reason they would impact things)... (1) your command bar and buttons
are built at run-time, and I'm referring to existing items (a bar and
buttons I added manually using the View|Toolbars|Customize menu), and
(2) the code I'm executing is launched by clicking on the button for
which I'm trying to change the appearance.
 
Well, I finally got it to work... and thought you'd be interested to know how..

I discovered, while watching objects during code step thru, that the two buttons I had assigned the macros to both had a .BuiltIn value of True, while the button created by running your code snippet had a .BuiltIn value of False. I had used the View|Toolbars|Customize menu selection to create my toolbar and then had dragged the names of the my routines from the Macros list box on to the bar. As you know, your code snippet built a bar and a button at run-time

So, I simply modified your code to build a new bar, with two buttons, to which I assigned the routines (via the .OnAction property). I stepped through your code once to actually generate the bar and buttons, and then I made a change to my original routines to reference this new bar by name and voila! All is good with the world

Thanks for your patience in this. I'm not sure WHY a toolbar created using the menu is considered BuiltIn, but at some point I just figure I got what I needed

Dave
 
The code I showed used the Temporary = True argument in creating the
new toolbar.

You always want to do that so in case your code isn't running there
isn't an orphaned toolbar sitting around. So in my COM addins where I
create toolbars or add menus or whatever I do 3 things. I create the
toolbar or menu as temporary, I call a routine in my code to create
the item when the code starts running or when a new Explorer or
Inspector is shown or however I want to control visibility and
existence of the item, and before I create the item in my code I
iterate the collection and make sure that it doesn't exist already. If
it does I delete it. Orphans can be created if Outlook crashes and the
temporary item wasn't correctly deleted by Outlook.

I also add code in my UnInitHandler procedure to check for the custom
item and delete it if it exists when Outlook is shutting down. A real
belt and suspenders solution but it prevents things from going haywire
in most situations.




DaveH said:
I suppose you're getting a good laugh from my last post... Seems as
soon as I exited the form I had open (and on which I done my "testing"
(using that word lightly), I discovered that the next time I opened a
similar form, the toolbar no longer exists....!!!! I guess I have
something else to figure out now. DOH!
 
Back
Top