November 19, 2018
Hot Topics:

Developing Pocket Outlook Add-Ins

  • July 19, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

If you take a closer look at standard Pocket PC Pocket Outlook applications like Calendar, Contacts or Tasks, you will notice that they all contain a Tools menu. Moreover, through this menu you are able to, for example, beam selected items. Pocket Outlook provides an opportunity for external applications to embed their commands into the Tools menu. As easily as you can imagine, your application may manipulate Outlook items by all the ways POOM offers you, directly from standard Pocket PC software.

To get there, you need to perform only a few simple steps. Actually, this whole task can be broken into the following steps:

  • Implement a DLL that exports the CePimCommand function.
  • Register the Add-In for the desired application (Calendar, Contacts, or Tasks).

The next sections will describe these tasks in more detail.

Implementing an Add-In DLL

As noted above, your DLL has to implement and export the following function:

void EXPORT CePimCommand(HWND hWnd, PIMTYPE ptData,
                         UINT uDataCount, HANDLE *rghData,
                         void *pReserved)

When a user selects your command, this function will be called automatically. So, the DEF-file may look like the following:

; POOM2.def : Declares the module parameters for the DLL.
;DESCRIPTION  'POOM2 Windows CE Dynamic Link Library'
   ; Explicit exports can go here

Now, take a closer look at the CePimCommand function and its parameters. The first two parameters are a window handle and type of calling application; in other words, Calendar, Contacts, or Tasks. In case your program will want to perform some actions upon a caller, it is very well set up. PIMTYPE should be declared as follows:

typedef enum tagPIMTYPE

Earlier versions of Windows CE have had different ordering of these applications; hence, this enumeration will work just fine on Pocket PC 2000 and later.

The next two parameters, uDataCount and rghData, bring us items selected in the caller application; for example, the specific Contact Item and so forth. To manipulate those items, you should pass the standard Pocket Outlook initialization sequence to obtain a POOM Application object (see the previous article, "How to Add Pocket Outlook Features to Your Mobile Application"). Once you've done this, you can continue operating in a regular POOM manner. rghData keeps object identifiers for selected items, so you may get actual objects by calling the IPOutlookApp.GetItemFromOid method:

ITaskPtr pTask;
CComBSTR bstrText;
for (int i = 0; i < uDataCount; i++)
   hr = pPOOMApp->GetItemFromOid((long)rghData[i],
   if ( SUCCEEDED(hr) )

The code snippet above performs the simplest loop over passed Task Items and displays their subjects. You may be required to carry out more complicated operations; for example, displaying a Contact's photo or other additional information, but nevertheless you have full control over what's going on.

Below, you will find a slightly more complicated sample illustrating that you are free to implement any required behavior in terms of GUI or functionality (see Figure 1 as an example):

void DoAction(HWND hWnd,PIMTYPE ptData,UINT uDataCount,
              HANDLE *rghData,void *pReserved)
   HRESULT hr = 0;
   CLSID clsid;
   LPOLESTR pProgID = L"PocketOutlook.Application";
   hr = CLSIDFromProgID(pProgID,&clsid);
   IPOutlookAppPtr pPOOMApp;
   hr = pPOOMApp.CoCreateInstance(clsid, NULL,
   if ( FAILED(hr) )
      AfxMessageBox(L"Failed to CreateInstance");
      AfxMessageBox(L"Failed to Logon");
   CArray<ITask*,ITask*> arrTasks;
   CComBSTR bstrText;
   for (int i = 0; i < uDataCount; i++)
      ITask *pTask = NULL;
      hr = pPOOMApp->GetItemFromOid((long)rghData[i],
      if ( SUCCEEDED(hr) )
   if ( arrTasks.GetSize() )
      CAddInDlg dlg(&arrTasks);
      for (int i = 0, s = arrTasks.GetSize(); i < s; i++)
BOOL CAddInDlg::OnInitDialog()
   CComBSTR bstrSubject;
   COleDateTime dtDueDate;
   DATE date;
   CString sLine;
   for (int i = 0, s = m_pArrTasks->GetSize(); i < s; i++)
      ITaskPtr pTask = m_pArrTasks->GetAt(i);
      if ( 0 == pTask->get_DueDate(&date) && date != DATE_NONE )
         dtDueDate = date;
         sLine.Format(L"%s Due %02d/%02d/%02d",
                      dtDueDate.GetYear() % 2000);
         sLine.Format(L"%s Due None",
   return TRUE;

Figure 1

As a bottom line, CePimCommand just serves as an entry point for your application; you are totally free to develop software as complicated as only you can imagine.

Page 1 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.


Thanks for your registration, follow us on our social networks to keep up-to-date