Newbie get_CurrentItem() question

  • Thread starter R2FicmllbA
  • Start date Views 1,806
Status
Not open for further replies.
R

R2FicmllbA

Hello,

I am still brand new to ATL/COM add-in development so I assume there is an

obvious answer to this. I'm using VC++ 6 and the add-in is for Outlook 2003.

I am attempting to add the body of the currently selected message to a new

message I create. The new message creation/sending part works fine, but I get

a fatal error every time I use the get_CurrentItem() method. Here's the

relevant code (I got almost all of this from tutorials):

CComPtr <Outlook::_MailItem> mailPtr;

m_spApp->CreateItem(Outlook::eek:lMailItem, (IDispatch**)&mailPtr);

CComPtr<Outlook::_Inspector> spInspector;

hr = m_spApp->ActiveInspector(&spInspector);

if (FAILED(hr)){

MessageBox(NULL,"Error retrieving inspector","Inspector",MB_OK);

return;

}

CComPtr<IDispatch> spCurrentItem;

CComPtr<Outlook::_MailItem> mailPtr2;

spInspector->get_CurrentItem(&spCurrentItem);

Any input is greatly appreciated. Let me know if you need any more info.
 
S

SvenC

Hi Gabriel,


> I am attempting to add the body of the currently selected message to a new
> message I create. The new message creation/sending part works fine, but I
> get
> a fatal error every time I use the get_CurrentItem() method. Here's the
> relevant code (I got almost all of this from tutorials):

> CComPtr <Outlook::_MailItem> mailPtr;
> m_spApp->CreateItem(Outlook::eek:lMailItem, (IDispatch**)&mailPtr);


Did you try to create the new item *after* retrieving the current item,

just to make sure the CreateItem does not set a new CurrentItem


> CComPtr<Outlook::_Inspector> spInspector;
> hr = m_spApp->ActiveInspector(&spInspector);


Are you sure that spInspector != NULL?


> CComPtr<IDispatch> spCurrentItem;
> CComPtr<Outlook::_MailItem> mailPtr2;

> spInspector->get_CurrentItem(&spCurrentItem);


Does the call fail or crash?

Can you call any other method on the inspector?

SvenC
 
R

R2FicmllbA

Hi Sven,

"SvenC" wrote:


> Are you sure that spInspector != NULL?
>


That was it. I erroneously made the assumption that since hr wasn't failing,

spInspector was getting set. Which leads me to my next question. I think I'm

confusing the Inspector object and the Selection object. If I have one or

more messages in my inbox selected, I'd access them with

ActiveExplorer->Selection, correct? I tried this instead (with extra checks

to see where things went awry):

CComPtr <Outlook::_Explorer> spExplorer;

m_spApp->ActiveExplorer(&spExplorer);

if (spExplorer == NULL){

MessageBox(NULL,"Explorer not set","No Explorer",MB_OK);

}

CComPtr <Outlook::Selection> spSelection;

spExplorer->get_Selection(&spSelection);

if (spSelection == NULL){

MessageBox(NULL,"Selection not set","No Selection",MB_OK);

}

VARIANT v;

v.intVal = 1;

CComPtr<IDispatch> mailPtr2;

spSelection->Item(v,&mailPtr2);

if (mailPtr2 == NULL){

MessageBox(NULL,"mailPtr2 not set","No MailPtr2",MB_OK);

}

When run, it displays the "mailPtr2 not set" message box. Thanks for your

help!

-Gabriel
 
S

SvenC

Hi Gabriel,


> I think I'm confusing the Inspector object and the Selection object.


Inspector gives you access to a single item shown by Outlook in its

own window.


> If I have one or more messages in my inbox selected, I'd access
> them with ActiveExplorer->Selection, correct?


Yes.


> CComPtr <Outlook::Selection> spSelection;
> spExplorer->get_Selection(&spSelection);

> if (spSelection == NULL){
> MessageBox(NULL,"Selection not set","No Selection",MB_OK);
> }

> VARIANT v;
> v.intVal = 1;


You must set the type of the variant.

v.vt == VT_I4.

Alternatively you can use a variant class like CComVariant

which has assignment overloads which set the type

automatically.

CComVariant v = 1L; // use L to indicate long constant


> CComPtr<IDispatch> mailPtr2;
> spSelection->Item(v,&mailPtr2);


Get the returned HRESULT as well. I expect that you should

get E_INVALIDARG when passing an incorrect VARIANT.

SvenC
 
R

R2FicmllbA

Thanks again, Sven!

I actually caught the VARIANT issue. The HRESULT returned from

spSelection->Item() doesn't fail and mailPtr2 is set now, however I run into

issues when calling mailPtr2's methods. I DID change the declaration to

CComPtr<Outlook::_MailItem> from CComPtr<IDispatch> because I couldn't figure

out how to convert between the two afterward. Here's what I'm currently

working with:

CComVariant nItem = 1L;

CComPtr<Outlook::_MailItem> mailPtr2;

hr = spSelection->Item(nItem,(IDispatch**)&mailPtr2);

if (FAILED(hr)){

char buf[30];

sprintf(buf,"HResult: %d",hr);

MessageBox(NULL,buf,"HResult",MB_OK);

}

if (mailPtr2 == NULL){

MessageBox(NULL,"mailPtr2 not set","No MailPtr2",MB_OK);

}

OlObjectClass cls;

mailPtr2->get_Class(&cls);

char buf[30];

sprintf(buf, "mailPtr2's class is: %d",cls);

MessageBox(NULL,buf,"Class",MB_OK);

CComPtr <Outlook::_MailItem> mailPtr;

m_spApp->CreateItem(Outlook::eek:lMailItem, (IDispatch**)&mailPtr);

long size = 0;

mailPtr2->get_Size(&size);

sprintf(buf,"mailPtr2 Size: %d",size);

MessageBox(NULL,buf,"Size", MB_OK);

BSTR vSubject = ::SysAllocString(OLESTR("test"));

BSTR vBody = ::SysAllocStringLen(NULL,size);

get_Class() seems to work fine (returns 43, which I looked up in the

ITypeLib Viewer as being olMail). get_Size() doesn't set size though, and

get_Body() crashes Outlook. Any ideas?

-Gabriel
 
S

SvenC

Hi Gabriel,


> I DID change the declaration to
> CComPtr<Outlook::_MailItem> from CComPtr<IDispatch> because I couldn't
> figure
> out how to convert between.


Use QueryInterface to "cast" between two COM interfaces:

CComPtr<IDispatch> disp;
> CComVariant nItem = 1L;



> CComPtr<Outlook::_MailItem> mailPtr2;
> hr = spSelection->Item(nItem, &disp);


if(disp != NULL)

hr = disp->QueryInterface(&mailPtr2);

Also be sure to release the smart pointers before

you use their address operator to assign a new

object to them. So if you did another:

hr = spSelection->Item(nItem, &disp);

you would leak the first interface pointer.

This would be the correct way:

disp = NULL;

hr = spSelection->Item(nItem, &disp);


> long size = 0;
> mailPtr2->get_Size(&size);
> get_Size() doesn't set size though


What is the value of size? Please retry with the

mailPtr2 retrieved through QueryInterface


> BSTR vSubject = ::SysAllocString(OLESTR("test"));
> BSTR vBody = ::SysAllocStringLen(NULL,size);


If you use hungarian notation you should use helpful

prefixes. v for BSTRs is confusing, looks more like VARIANT.

Why do you allocate them at all? Are they relevant for

your problem?


> get_Body() crashes Outlook. Any ideas?


how do you call it?

SvenC
 
R

R2FicmllbA

Hi Sven,

Thanks so much, I just needed to use QueryInterface to cast between the two

interfaces. Works like a charm now. I'll also implement your other "pointers"

to avoid issues in the future.

Thanks again. You've gotten me well on my way!

-Gabriel
 
Status
Not open for further replies.
Top