Introduction
These codes are written with VC++ ATL/COM . Creating an Outlook addin and performing various tasks related to Outlook. One who is familiar with Outlook operations can understand and can extend these codes to perform other tasks. It holds Creating an Outlook Addin, creating buttons and various controls, creating appointments, retrieving all appointments, connecting to database and take values to and from the database.
I assure that I would work in the future to enhance various other operations with clear codes.
Using the code
- Start Visual Studio, Click on New Project-> Extensibility and choose Shared Addin from it.
- Make sure to check "Create an Add-in using Visual C++/ATL" and "I
would like my Add-in to load when the host application loads."
- Build the solution to ensure that it compiles good.
- Next, open up Class View, right-click on your CConnect class and select
"Add -> Implement Interface…" In the dialog that pops up, select the
"Microsoft Office 12.0 Object Library <2.4>" type library and add
the "
IRibbonExtensibility" interface from it. If your library is not listed in the drop down. Choose file and click on browse button to choose the MSO.dll file from Office folder. Click Finish once you are done.
- Navigate to Connect.h file and you should see the auto generated
GetCustomUI() function. Delete its "return E_NOTIMPL;" And try to make your own code here.
- Next step is to import a XML resource file having codes to create buttons or any other control you want to see on Outlook Tabs.
- Right Click on .rc file and choose Add Resource and select import from it. Add the xml file to the project. For instance Ribbon.xml. Add these codes inside
GetCustomUI() function.
if (!RibbonXml)
return E_POINTER;
*RibbonXml = GetXMLResource(IDR_XML1);
return (*RibbonXml ? S_OK : E_OUTOFMEMORY); return S_OK; Ribbon.xml
="1.0" ="utf-8"
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab idMso="TabCalendar" >
<group id="Customer" label="Customer">
<button id="ReportButton"
size="large"
label="Report Button"
imageMso="SetLanguage"
onAction="OnReportButtonClicked"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
The following codes are used to parse the xml and sends the values to GetCustomUI() function:
HRESULT HrGetResource(int nId, LPCTSTR lpType, LPVOID* ppvResourceData, DWORD* pdwSizeInBytes)
{
HMODULE hModule = _AtlBaseModule.GetModuleInstance();
if (!hModule)
return E_UNEXPECTED;
HRSRC hRsrc = FindResource(hModule, MAKEINTRESOURCE(nId), lpType);
if (!hRsrc)
return HRESULT_FROM_WIN32(GetLastError());
HGLOBAL hGlobal = LoadResource(hModule, hRsrc);
if (!hGlobal)
return HRESULT_FROM_WIN32(GetLastError());
*pdwSizeInBytes = SizeofResource(hModule, hRsrc);
*ppvResourceData = LockResource(hGlobal);
return S_OK;
}
BSTR GetXMLResource(int nId)
{
LPVOID pResourceData = NULL;
DWORD dwSizeInBytes = 0;
HRESULT hr = HrGetResource(nId, TEXT("XML"),
&pResourceData, &dwSizeInBytes);
if (FAILED(hr))
return NULL;
CComBSTR cbstr(dwSizeInBytes, reinterpret_cast<LPCSTR>(pResourceData));
return cbstr.Detach();
}
SAFEARRAY* GetOFSResource(int nId)
{
LPVOID pResourceData = NULL;
DWORD dwSizeInBytes = 0;
if (FAILED(HrGetResource(nId, TEXT("OFS"),
&pResourceData, &dwSizeInBytes)))
return NULL;
SAFEARRAY* psa;
SAFEARRAYBOUND dim = {dwSizeInBytes, 0};
psa = SafeArrayCreate(VT_UI1, 1, &dim);
if (psa == NULL)
return NULL;
BYTE* pSafeArrayData;
SafeArrayAccessData(psa, (void**)&pSafeArrayData);
memcpy((void*)pSafeArrayData, pResourceData, dwSizeInBytes);
SafeArrayUnaccessData(psa);
return psa;
}Add the above functions in Connect.h.
- Open up "stdafx.h" and move the #import statement for MSO.dll from
the bottom of the file up next to the #import statement for the
Extensibility library inside the #pragma blocks (remove any
'no_namespace' annotations from that line as well)
- Add "using namespace Office;" to the top of the Connect.h file.
- Now build the solution with either Static or shared libraries.
- You can see the button in the Outlook Calender screen and you can use any other value to place various controls in Outlook.
Adding button click event
- Right click on the project and choose Add Class and select ATL Simple Object" in the ATL category, name it as
ButtonCallBack.
- Now in Class View we have several new objects: an ATL interface called
"
IButtonCallBack" and an implementation class called
"CButtonCallBack." We don't need the implementation, so go ahead and
delete all the ButtonCallBack.* files from the Solution Explorer.
- Under Class view, Right click on
IButtonCallBack and select Add Method. In the Add Method Wizard, add a method named "ButtonClicked" with one [in] parameter of type IDispatch* called RibbonControl:
- Right click on the CConnect class and select "Implement Interface…"
again to add
IButtonCallBack .
Double-click the ButtonClicked function in Class View to be taken to the
auto-generated implementation.
- Write codes under the auto generated function
ButtonClicked().
STDMETHOD(ButtonClicked)( IDispatch * RibbonControl){
- Now right click on project, choose Add Existing item and import AddIn_i.c from the project folder. And make sure that the file is "Not Using Precompiled Headers" under Configuration Properties. (Just right click the file and selecting properties).
- In Connect.h, switch the IDispatch line in the COM_MAP to IButtonCallBack instead of
IRibbonExtensibility:
- Now just Clean the solution and Build it.
- You will see the button in Outlook Calendar screen and if you click on the button, you will get the MessageBox as added before.
Working with Appointments, Sending Mails,Saving Contacts and Accessing Database ATL COM
.1) Add these two in stdafx.h file.
#import "C:\Program Files\Microsoft Office\Office14\MSOUTL.OLB" raw_interfaces_only, raw_native_types, named_guids, auto_search
#import "C:\Program Files\Common Files\System\ado\msado28.tlb" no_namespace rename("EOF", "EndOfFile")
And in Connect.h, add using namespace Outlook;.
Add these codes whereever you want on the button click event or under OnConnection function.
3) _ApplicationPtr pApp(pApplication);_NameSpacePtr pNamespace;pApp->GetNamespace(L"MAPI",&pNamespace);MAPIFolderPtr pFolder;pNamespace->GetDefaultFolder(olFolderContacts,&pFolder);_ItemsPtr pItems;
Create and open a new contact
_ContactItemPtr pNewContact;pApp->CreateItem(olContactItem,(IDispatch**)&pNewContact);pNewContact->put_LastName(OLESTR("India"));pNewContact->put_FirstName(OLESTR("Gokulnath"));pNewContact->Save();
You can use any values of folder names to retrieve values from those folders (olFolderContacts).
Next is to get an appointment
_AppointmentItemPtr pGetApptt;
pNamespace->GetDefaultFolder(olFolderCalendar,&pFolder);
pFolder->get_Items(&pItems);
long count =5;
pItems->get_Count(&count);
int wd = (int)count;
VARIANT lpVar;
lpVar.vt = VT_INT;
lpVar.intVal = wd;
pItems->Item(lpVar,(IDispatch**)&pGetApptt);
BSTR subject = L"location";
pGetApptt->get_Subject(&subject);
BSTR body;
pGetApptt->get_Body(&body);
ConnectionPtr pConn = NULL;
_CommandPtr pCmdSelect = NULL;
_RecordsetPtr pRstValue = NULL;
_bstr_t strCon("DRIVER={SQL Server};SERVER=localhost;DATABASE=Client;");
_bstr_t strSQLSelect("SELECT City FROM Table1 WHERE ICode = '7'");
hr = pConn.CreateInstance((__uuidof(Connection)));
hr = pConn->Open(strCon,"","",0);
hr=pCmdSelect.CreateInstance(__uuidof(Command));
pCmdSelect->ActiveConnection = pConn;
pCmdSelect->CommandText = strSQLSelect;
VARIANT rowsaffected;
VARIANT param;
long optl = 0;;
pConn->Execute(strSQLSelect,NULL,adCmdText);
hr=pRstValue.CreateInstance(__uuidof(Recordset));
pRstValue->Open (strSQLSelect, _variant_t((IDispatch *) pConn, true), adOpenForwardOnly, adLockOptimistic, adCmdText);
pRstValue->MoveFirst();
if ( pRstValue->EndOfFile ){
}
else
{
_bstr_t bstrType;
bstrType = pRstValue->Fields->GetItem("City ")->Value; }
pConn->Close();
Sending Mails to various accounts and operations.
_MailItemPtr pNewMailItem;
pApp->CreateItem(olMailItem,(IDispatch**)&pNewMailItem);
pNewMailItem->put_BCC(L"mailid1");
pNewMailItem->put_Body(L"Mail Send from Visual C++/ATL");
pNewMailItem->put_To(L"mailid2");
pNewMailItem->Send();
DATE pStart;
SYSTEMTIME sysTime;
memset(&sysTime, 0, sizeof(SYSTEMTIME));
sysTime.wYear = 2013;
sysTime.wMonth = 1;
sysTime.wDay = 4;
SystemTimeToVariantTime(&sysTime, &pStart);
Creating the appointments
_AppointmentItemPtr pGetAppt;
pApp->CreateItem(olAppointmentItem,(IDispatch**)&pGetAppt);
pGetAppt->put_Body(L"Sample Appointment from ATL COM");
pGetAppt->put_Location(L"Coimbatore");
pGetAppt->put_Start(pStart);
pGetAppt->Save();
Points of Interest
These tasks are really interesting and challenging. Enjoyed it.
History
Version 1.0
Am a Computer Science and Engineering Graduate.
Currently I am working as a software developer in VC++.