How to add toolbar to MailEditor for outlook?

Status
Not open for further replies.
R

ryotyankou

When we compose a new message, or "reply", "reply all", "forward" a message,

the message is in edit mode, i want to add a toolbar in this mode, and put

two buttons on the toolbar(just like the encrypt and signarture buttons),

then DispEventAdvise on the buttons. How could i do this? In OnConnection

method, i think i couldn't get the inspector to work with. May i add toolbar

and advise on button in NewInspector event? If i advise in NewInspector event,

when should i Unadvise on buttons?? Any tips or ideas? TIA.


 
I found my solution can work, but i don't know if it is safe or not. My

solution is as follow:

1.) In OnConnection method, DispEventAdvise on NewInspector event.

2.) In NewInspector advise function, Create the two buttons and

DispEventAdvise the two buttons and InspectorClose event.

3.) In InspectorClose event, UnAdvise InspectorClose event itself and two

buttons event.

4.) In OnDisconnection method, UnAdvise NewInspector event.

So everytime the user open mail or create mail, those codes should be

executed, i think this will cause low efficiency. Is there a common idea for

my purpose?

By the way, How could i judge if current inspector is in edit mode(new mail,

relpy, forward etc.) but read-only mode(user open an existing mail). I found

the "Sent" property of MailItem may do this work, if "Sent == false", it must

be in edit mode, otherwise in read-only mode, am i right?Thanks in advance.


 
That's pretty much the routine you use, although you may want to store your

pointers in some sort of list or whatever to keep them alive and to be able

to handle multiple open Inspectors at a time.

To do that you need to provide a unique Tag value for any buttons you create

so Click() events don't fire in every open Inspector.

In general, you may also find that the new Inspector and its CurrentItem

object aren't fully populated (weak object reference) during NewInspector().

For example, even though it's always WordMail in Outlook 2007 you get

Inspector.IsWordMail() == false during that event. The only CurrentItem

properties you should work with then are .Class and .MessageClass.

I usually wait until the first Inspector.Activate() event fires on an

Inspector before I try to create UI or to access most of the Inspector and

CurrentItem properties.

A new item has a null EntryID value. Any item that pre-exists or has been

saved has an EntryID value.

"ryotyankou " <u48591@uwe> wrote in message

news:95458ab39e550@uwe...
> I found my solution can work, but i don't know if it is safe or not. My
> solution is as follow:
> 1.) In OnConnection method, DispEventAdvise on NewInspector event.
> 2.) In NewInspector advise function, Create the two buttons and
> DispEventAdvise the two buttons and InspectorClose event.
> 3.) In InspectorClose event, UnAdvise InspectorClose event itself and two
> buttons event.
> 4.) In OnDisconnection method, UnAdvise NewInspector event.
> So everytime the user open mail or create mail, those codes should be
> executed, i think this will cause low efficiency. Is there a common idea
> for
> my purpose?
> By the way, How could i judge if current inspector is in edit mode(new
> mail,
> relpy, forward etc.) but read-only mode(user open an existing mail). I
> found
> the "Sent" property of MailItem may do this work, if "Sent == false", it
> must
> be in edit mode, otherwise in read-only mode, am i right?Thanks in
> advance.

> >
>
>
 
Thank you for your reply, Ken.

Do you mean it is better to Create UI and DispEventAdvise in Activate event

than NewInspector event?

I think entryid is not very good to judge if it is in edit mode, consider

there is a draft mail, user already save it, it have an entry id, when user

open it again in draft box, it is still in edit mode. So i think get "Sent"

property should be better, draft is not sent yet, so it is in edit mode. My

purpose is simple:

If (1): New, reply, relpy all, forward == create buttons

(2): Open exist mail == no create buttons

Just like outlook's encrypt and signature button.

By the way, how do i change button style? click it, down, click again, up.

Like encrypt and signature button too.
- wrote:
> That's pretty much the routine you use, although you may want to store your
> pointers in some sort of list or whatever to keep them alive and to be able
> to handle multiple open Inspectors at a time.

> To do that you need to provide a unique Tag value for any buttons you create
> so Click() events don't fire in every open Inspector.

> In general, you may also find that the new Inspector and its CurrentItem
> object aren't fully populated (weak object reference) during NewInspector().
> For example, even though it's always WordMail in Outlook 2007 you get
> Inspector.IsWordMail() == false during that event. The only CurrentItem
> properties you should work with then are .Class and .MessageClass.

> I usually wait until the first Inspector.Activate() event fires on an
> Inspector before I try to create UI or to access most of the Inspector and
> CurrentItem properties.

> A new item has a null EntryID value. Any item that pre-exists or has been
> saved has an EntryID value.
>
> >I found my solution can work, but i don't know if it is safe or not. My
> > solution is as follow:

> [quoted text clipped - 16 lines]
> > be in edit mode, otherwise in read-only mode, am i right?Thanks in
> > advance.



 
Hi, Ken, i have a problem here.

About the multiple Inspector, How could i Unadvise inspector event and two

button click event correctly? Say there are two Inspector, therefore there

are 6 pointers were saved. But i don't know which Inspector the user close

first, that is i don't know which inspector pointer and buttons' pointer

should be passed to DispEventUnadvise. My application flow now is:

1.) In OnConnection Advise NewInspector event.

2.) In NewInspector if item is not mailitem return failed directly.

A.) if(it is not wordeditor) CreateUI

B.) if(item is wordeditor && item.wordeditor.activewindow.envolopevisible

is ture) CreateUI

C.) After CreateUI successfully, Advise InspectorClose and two button

click event and Save

pointers.

3.) In InspectorClose event////////////////////////<------------ Here i don't

know how to Unadvise correct

inspector. Could you help me please?

4.) In OnDisconnection UnAdvise NewInspector event.


 
I searched through the internet via google, found two code snippets, but

one's in VB another's in C#. I almost know nothing on both language.

c#: http://www.outlookcode.com/codedetail.aspx?id=797

I don't understand what does "XEventHandler"do in the code.

VB: http://outlookcode.com/codedetail.aspx?id=1344

and this, while KillInsp, What's happen on variable "_intID"? How could i do

this in C++?

In a word, my purpose is only one: When user close Inspector, i want to do

DispEventUnadvise correctly, so i must know correct inspector pointer for the

closing Inspector window.

Thanks for your help!!!

 
Yes, it's better to create UI in Activate(), as I said.

I can't help you with any specific C++ code, I don't do C++. There are

plenty of examples, some from me, in VB6 or VB.NET or C#. You can search at

www.outlookcode.com and see if any C++ samples have been posted.

If EntryID is null then the item is new. That's all it tells you. Sent is

not a good way to tell if the item is in edit mode, you can edit a received

message or one you already sent, so it doesn't tell you that. It will tell

you if you are working with a draft and that's about it for reliable

information.

You can also check the ConversationIndex properties on an item. A new item,

not saved already, has a null ConversationIndex value. A reply or forward

will have a value for that property, each item in a conversation will

increment the length of that property by 1 date/time struct length.

Checking Subject for any prefixes such as RE: or FWD: can also be done.

A toggle button is set up as a normal CommandBarButton, you set the State

property to determine if the button appears to be pushed in. State ==

MsoButtonState.msoButtonDown looks pushed in, State ==

MsoButtonState.msoButtonUp looks not pushed in.

"ryotyankou " <u48591@uwe> wrote in message

news:954ed6b1f83ba@uwe...
> Thank you for your reply, Ken.
> Do you mean it is better to Create UI and DispEventAdvise in Activate
> event
> than NewInspector event?
> I think entryid is not very good to judge if it is in edit mode, consider
> there is a draft mail, user already save it, it have an entry id, when
> user
> open it again in draft box, it is still in edit mode. So i think get
> "Sent"
> property should be better, draft is not sent yet, so it is in edit mode.
> My
> purpose is simple:
> If (1): New, reply, relpy all, forward == create buttons
> (2): Open exist mail == no create buttons
> Just like outlook's encrypt and signature button.
> By the way, how do i change button style? click it, down, click again, up.
> Like encrypt and signature button too.
 
If you handle the Inspector.Close() event you know exactly which Inspector

is being closed.

The general algorithm for an Inspector (or Explorer) wrapper is to keep an

int variable that is incremented for each new Inspector or Explorer that is

opened. That is the Key value for that object. When the item is opened and

you determine you want to handle it using wrappers you create a new instance

of a wrapper class. That is added to the list/collection/whatever with the

Key value as the key property of the list entry for that wrapper class.

Then you instantiate a class that handles the Inspector, its events and

buttons and so on. In that class is the code for Inspector.Close(),

Activate() and whatever other events you want, plus events for the item in

the Inspector. It also holds a reference to the Inspector and item and the

Key property. The UI code is called and the Key value is used to add to a

string or GUID to create a unique Tag property for each button.

The button handler code is also in that wrapper class, it gets called for

that Inspector instance only because of the unique Tag.

When Inspector.Close() fires you handle that in the wrapper class and in

your dispose code you remove the wrapper class from the list.

"ryotyankou " <u48591@uwe> wrote in message

news:95514d02ab7d5@uwe...
> Hi, Ken, i have a problem here.
> About the multiple Inspector, How could i Unadvise inspector event and two
> button click event correctly? Say there are two Inspector, therefore there
> are 6 pointers were saved. But i don't know which Inspector the user close
> first, that is i don't know which inspector pointer and buttons' pointer
> should be passed to DispEventUnadvise. My application flow now is:
> 1.) In OnConnection Advise NewInspector event.
> 2.) In NewInspector if item is not mailitem return failed
> directly.
> A.) if(it is not wordeditor) CreateUI
> B.) if(item is wordeditor &&
> item.wordeditor.activewindow.envolopevisible
> is ture) CreateUI
> C.) After CreateUI successfully, Advise InspectorClose and two button
> click event and Save
> pointers.
> 3.) In InspectorClose event////////////////////////<------------ Here i
> don't
> know how to Unadvise correct
> inspector. Could you help me please?
> 4.) In OnDisconnection UnAdvise NewInspector event.

> >
>
>
 
- wrote:
> If you handle the Inspector.Close() event you know exactly which Inspector
> is being closed.


I don't quite understand this, the Close event have no parameter, how could i

get the right Inspector pointer??

for instance:

typedef IDispEventSimpleImpl<1, CMyAddin, &__uuidof(Outlook::InspectorEvents)
> InspCloseEvent;


void __stdcall CMyAddin::OnNewInspector(IDispatch * pInspector)

{

m_Inspector = pInspector;//m_Inspector is a Outlook::_InspectorPtr.

InspCloseEvent::DispEventAdvise(m_Inspector);

//other codes.

}

and close event is:

void __stdcall CMyAddin::OnCloseInspector()

{

InspCloseEvent::DispEventUnadvise(???);//What should i pass in here??

}

Every time i open a new inspector, m_Inspector is changed, when i close one

of opened inspector, how could i know which InspectorPtr should be use???Of

course, i should save m_Inspector in a list.

Thanks!


 
- wrote:
> Yes, it's better to create UI in Activate(), as I said.


Every time the inspector is focused, this function is called, it may create

multiple toolbar. Do you mean use FindControl to find the toolbar created, if

exist then do not create again?


> I can't help you with any specific C++ code, I don't do C++. There are
> plenty of examples, some from me, in VB6 or VB.NET or C#. You can search at
> www.outlookcode.com and see if any C++ samples have been posted.


OK, i will check it, 3Q.


> If EntryID is null then the item is new. That's all it tells you. Sent is
> not a good way to tell if the item is in edit mode, you can edit a received
> message or one you already sent, so it doesn't tell you that. It will tell
> you if you are working with a draft and that's about it for reliable
> information.


I think Sent property can work for me, although a received message or sent

message can be edit, i needn't show my button for these case, my button is

just for setting our program before sent message.(just like encrypt and

signature button)


> A toggle button is set up as a normal CommandBarButton, you set the State
> property to determine if the button appears to be pushed in. State ==
> MsoButtonState.msoButtonDown looks pushed in, State ==
> MsoButtonState.msoButtonUp looks not pushed in.


OK, got it, thanks again.

 
If you have a wrapper class that holds the Inspector, current item, Key,

etc., it also handles the Inspector and item events. I mentioned that. So

when Inspector.Close() fires it fires only in that one wrapper class

instance. The class instance knows who it is from the stored Key value. It

can access it's own UI that way, and access it's place in the list. So it

can also remove itself from the list.

As far as not creating multiple copies of the UI, that's what flags are for.

You set one flag in the wrapper class when the class is created, call it

_startup. You can also create another flag _uiCreated. You check the flag

logic to see if startup initializations and UI creation need to be done. You

can also combine both flags into one if you only need one flag.

"ryotyankou " <u48591@uwe> wrote in message

news:9555354b0ac4e@uwe...
> - wrote:
> >Yes, it's better to create UI in Activate(), as I said.

> Every time the inspector is focused, this function is called, it may
> create
> multiple toolbar. Do you mean use FindControl to find the toolbar created,
> if
> exist then do not create again?
>
> >I can't help you with any specific C++ code, I don't do C++. There are
> >plenty of examples, some from me, in VB6 or VB.NET or C#. You can search
> >at
> >www.outlookcode.com and see if any C++ samples have been posted.

> OK, i will check it, 3Q.
>
> >If EntryID is null then the item is new. That's all it tells you. Sent is
> >not a good way to tell if the item is in edit mode, you can edit a
> >received
> >message or one you already sent, so it doesn't tell you that. It will tell
> >you if you are working with a draft and that's about it for reliable
> >information.

> I think Sent property can work for me, although a received message or sent
> message can be edit, i needn't show my button for these case, my button is
> just for setting our program before sent message.(just like encrypt and
> signature button)
>
> >A toggle button is set up as a normal CommandBarButton, you set the State
> >property to determine if the button appears to be pushed in. State ==
> >MsoButtonState.msoButtonDown looks pushed in, State ==
> >MsoButtonState.msoButtonUp looks not pushed in.

> OK, got it, thanks again.

> >
>
 
Hi, ken, thank you for your help. I write a wrapper class, and flow is change

to:

1.) In OnConnection, NewInspector::DispEventAdvise.

2.) In NewInspector event: CInspWrapper * pInsp = new CInspWrapper(Outlook::

Inspector);

then add pInsp to a list, say "InspList".

3.) In CInspWrapper, CloseInspector::DispEventAdvise, and create UI. when

user click close,

UnAdvise current inspector and remove UI .(here i don't know how to

remove the killed

CInspWrapper in "InspList",

so i decide to free all memory in OnDisconnection method).

4.) User close outlook, then in OnDisconnection, UnAdvise NewInspector event,

and free all pointer

(hold memory) from new CInspWrapper.

If wordedit is not use, this work fine, else it is sees quite unexcept. From

your previous post, i got an idea, that's is wordedit is in use, i should

find the commandbar, if it is exist, just put it visiable, else create it, am

i right?

Here i have i little trouble, how to find exist CommandBar in CommandBars??

it seems that CommandBars only have FindControl method, Should i use

CommandBars::GetItem(index)??

Sorry for so much questions, and thanks very much for your help.
- wrote:
> If you have a wrapper class that holds the Inspector, current item, Key,
> etc., it also handles the Inspector and item events. I mentioned that. So
> when Inspector.Close() fires it fires only in that one wrapper class
> instance. The class instance knows who it is from the stored Key value. It
> can access it's own UI that way, and access it's place in the list. So it
> can also remove itself from the list.

> As far as not creating multiple copies of the UI, that's what flags are for.
> You set one flag in the wrapper class when the class is created, call it
> _startup. You can also create another flag _uiCreated. You check the flag
> logic to see if startup initializations and UI creation need to be done. You
> can also combine both flags into one if you only need one flag.
>
> >>Yes, it's better to create UI in Activate(), as I said.

> > Every time the inspector is focused, this function is called, it may

> [quoted text clipped - 25 lines]
> >>MsoButtonState.msoButtonUp looks not pushed in.

> > OK, got it, thanks again.



 
If the list of wrapper classes is available globally to you in the code you

can access it from the Inspector wrapper class and find the related wrapper

entry using the Key value as the key for that list entry. That allows you to

remove the wrapper from the list from within the wrapper class.

The CommandBars.FindControl() method will find a top level control in that

CommandBars collection. If you are creating your own toolbar for your UI,

something that's necessary for WordMail, then you already know the name of

your toolbar and you can get it using CommandBars.FindControl().

"ryotyankou " <u48591@uwe> wrote in message

news:955f8c5e59e79@uwe...
> Hi, ken, thank you for your help. I write a wrapper class, and flow is
> change
> to:
> 1.) In OnConnection, NewInspector::DispEventAdvise.
> 2.) In NewInspector event: CInspWrapper * pInsp = new
> CInspWrapper(Outlook::
> Inspector);
> then add pInsp to a list, say "InspList".
> 3.) In CInspWrapper, CloseInspector::DispEventAdvise, and create UI. when
> user click close,
> UnAdvise current inspector and remove UI .(here i don't know how to
> remove the killed
> CInspWrapper in "InspList",
> so i decide to free all memory in OnDisconnection method).
> 4.) User close outlook, then in OnDisconnection, UnAdvise NewInspector
> event,
> and free all pointer
> (hold memory) from new CInspWrapper.
> If wordedit is not use, this work fine, else it is sees quite unexcept.
> From
> your previous post, i got an idea, that's is wordedit is in use, i should
> find the commandbar, if it is exist, just put it visiable, else create it,
> am
> i right?
> Here i have i little trouble, how to find exist CommandBar in
> CommandBars??
> it seems that CommandBars only have FindControl method, Should i use
> CommandBars::GetItem(index)??
> Sorry for so much questions, and thanks very much for your help.
 
Thanks very much, ken, Wished you had a good labor day. I make my solution

work now. In a word, outlook editor have multiple instance for the toolbar,

but the wordeditor have only one, right? Thanks again in advance.
- wrote:
> If the list of wrapper classes is available globally to you in the code you
> can access it from the Inspector wrapper class and find the related wrapper
> entry using the Key value as the key for that list entry. That allows you to
> remove the wrapper from the list from within the wrapper class.

> The CommandBars.FindControl() method will find a top level control in that
> CommandBars collection. If you are creating your own toolbar for your UI,
> something that's necessary for WordMail, then you already know the name of
> your toolbar and you can get it using CommandBars.FindControl().
>
> > Hi, ken, thank you for your help. I write a wrapper class, and flow is
> > change

> [quoted text clipped - 25 lines]
> > CommandBars::GetItem(index)??
> > Sorry for so much questions, and thanks very much for your help.



 
When using WordMail 2003 or earlier all toolbars you create are stored using

a CustomizationContext. If the CustomizationContext is the same, which is

usually is, they all will be there and have to be manipulated as to

visibility based on Envelope.Visible (email and not document), and on which

Inspector is currently the active one.

"ryotyankou " <u48591@uwe> wrote in message

news:959dfaab9f694@uwe...
> Thanks very much, ken, Wished you had a good labor day. I make my solution
> work now. In a word, outlook editor have multiple instance for the
> toolbar,
> but the wordeditor have only one, right? Thanks again in advance.
 
Status
Not open for further replies.
Similar threads
Thread starter Title Forum Replies Date
V How to add 'Previous Item' and 'Next Item' to the Quick Access Toolbar Using Outlook 1
G How to add a folder shortcut to outlook quick access toolbar? Using Outlook 6
N Combobox in outlook add ons toolbar not firing event on main window resized Using Outlook 3
P Can't add a custom hyperlink to toolbar in OL 2010 Using Outlook 1
D How can I add a user created template to the toolbar Outlook VBA and Custom Forms 1
P Problem in permanent type add-in toolbar Outlook VBA and Custom Forms 6
H Add an item to the "new" - option in outlook toolbar Outlook VBA and Custom Forms 6
G Add Map It button to Custom Contacts Form in Outlook Outlook VBA and Custom Forms 1
G Outlook 2021 Add Picture to Custom Contact Form Outlook VBA and Custom Forms 2
P Can't add custom field to custom Outlook form, it always adds to the Folder instead Outlook VBA and Custom Forms 2
P VBA to add email address to Outlook 365 rule Outlook VBA and Custom Forms 0
S Outlook 2019 Custom outlook Add-in using Visual Studio Outlook VBA and Custom Forms 0
G automatically choosing "add to autocorrect" option Using Outlook 0
F Want to add second email to Outlook for business use Using Outlook 4
K Add an entry to a specific calendar Using Outlook 1
F Add a category before "Send an Email When You Add an Appointment to Your Calendar" Outlook VBA and Custom Forms 0
J Want to create a button on the nav bar (module add-in) to run code Outlook VBA and Custom Forms 2
M "Attachment Detacher for Outlook" add in, does it update the server copy of the email? Using Outlook 1
J Outlook 365 Add keywords from Listbox to the message body where cursor is placed Outlook VBA and Custom Forms 0
O Add Day Number of the year for 2023-2033 Outlook VBA and Custom Forms 5
J GoDaddy migrated to Office365 - Outlook Wont Add Account Exchange Server Administration 21
F Outlook 2019 Outlook 2019 Add and Sync to New computer Comcast server Using Outlook 2
Witzker Add a text line at the end of the note field in all selected Contacts Outlook VBA and Custom Forms 7
A iCloud Outlook Add In is causing Outlook 2021 to crash and got disabled Using Outlook 10
N How to add or delete items to Move dropdown Menu Using Outlook 0
G Add contacts birthday to calendar Using Outlook 4
Commodore Safe way to add or update holidays; Windows Notifications issue Using Outlook 8
kkqq1122 How would I add Search for attachment name Outlook VBA and Custom Forms 3
L did MS ever add way to text via Outlook Using Outlook 5
P How to add a column named categories when searching in Outlook Using Outlook 0
M add new attendee to existing meetings with VBA Outlook VBA and Custom Forms 5
N Can't create NEW GROUP and add/remove a member from existing Group in Outlook Using Outlook 1
Witzker Outlook 2019 Pls. add a Prefix for OUTLOOK 2019 here Using Outlook 1
P Add inanimate objects to meetings? Using Outlook 1
O Outlook 2010 Add delete button to the side of the message list Using Outlook 1
BartH Add a string to the conditions in .Conditions.BodyOrSubject.Text Outlook VBA and Custom Forms 2
A "Get Add-Ins" - Which Version of Outlook to use Using Outlook 1
D Do I need Exchange Add-In? Using Outlook 6
C-S-R Manage Add-ins (Remove Wunderlist) Using Outlook 6
A iCloud add in problems Using Outlook 4
L Macro to add Date & Time etc to "drag to save" e-mails Outlook VBA and Custom Forms 17
C Looking for feedback on new Outlook Add-in Using Outlook 0
L isn't there an OL add-on that flags addressee before sending Using Outlook 3
S Add VBA save code Using Outlook 0
P Shortcut Pane - add shortcut to Office365 group mailbox Using Outlook 1
Z Add ComboBox Value to Body of Email Outlook VBA and Custom Forms 1
G Add to Outlook Contacts - Point to non-default contacts folder Using Outlook 0
M Automatically add senders first name to a greeting Outlook VBA and Custom Forms 1
C Add Form to Appointments Received, Automatically Outlook VBA and Custom Forms 6
O Outlook tasks - Add text column with multiple lines Using Outlook 3

Similar threads

Back
Top