Controls Articles and Tutorials

Outlook Style Menu and Pager Control

Author: Kirk Stowell
Platform: Visual C++ MFC
Downloads:
PagerDemo.zip - Source Files with Demo Project [ 45.87 Kb ]
PagerDemoSrc.zip - Source Files Only [ 8.66 Kb ]

The CXTOutlookBar class is a CListBox derived class that implements a Outlook style control. The CXTPagerCtrl class is used to contain and scroll the CXTOutlookBar window. This class wraps the windows pager API. Both classes are fairly easy to use and can be used the same way you would any standard MFC control.

Outlook Style Menu and Pager Control

This example was created using a standard MFC SDI application, two CView derived classes COutbarView ( the left view ) and CPagerView and a splitter window. The left view is used to contain the pager and Outlook style controls. To use these controls, add a member variable for each to the COutbarView class, for example:

 // Attributes
 protected:
     CXTOutlookBar m_wndOutlookBar;
     CXTPagerCtrl  m_wndPager;

Next add a WM_CREATE message handler to COutbarView. This is where we will create the pager and Outlook menu. Here we will also initialize the Outlook menu by adding menu items to the control and set pager button size and child window.

 int COutbarView::OnCreate(LPCREATESTRUCT lpCreateStruct)
 {
     if (CView::OnCreate(lpCreateStruct) == -1)
         return -1;

     // Create the pager control.
     if (!m_wndPager.Create(WS_CHILD|WS_VISIBLE|PGS_VERT,
         CRect(0,0,0,0), this, IDC_PAGER_CTRL ))
     {
         TRACE0("Failed to create CPagerCtrl...\n");
         return -1;
     }

      // Create the OutlookBar control using m_wndPager as the
      // parent.
      if (!m_wndOutlookBar.Create( WS_CHILD | WS_VISIBLE |
          WS_TABSTOP, CRect(0,0,0,0), &m_wndPager, IDC_OUTBAR))
      {
          TRACE0("Failed to create COutlookBar...\n");
          return -1;
      }

      // Set the CWnd object you want messages sent to.
      m_wndOutlookBar.SetOwner(this);
      m_wndOutlookBar.SetColors(RGB(0xff,0xff,0xff),
          RGB(0x3a,0x6e,0xa5));

      // Add items to the Outlook Bar control.
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_OUTLOOK, _T("Outlook Today"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_CONTACTS, _T("Contacts"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_TASKS, _T("Tasks"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_JOURNAL, _T("Journal"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_NOTES, _T("Notes"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_DELETED, _T("Deleted Items"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_PUBLIC, _T("Public"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_DRAFTS, _T("Drafts"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_OUTBOX, _T("Outbox"));
      m_wndOutlookBar.AddMenuItem(
          IDI_ICON_SENT, _T("Sent"));

      // Insert menu items at a specific index.
      m_wndOutlookBar.InsertMenuItem(
          1, IDI_ICON_INBOX, _T("Inbox"));
      m_wndOutlookBar.InsertMenuItem(
          2, IDI_ICON_CALENDAR, _T("Calendar"));

      // Set the child HWND to COutlookBar, and button size to 15.
      m_wndPager.SetChild(m_wndOutlookBar.GetSafeHwnd());
      m_wndPager.SetButtonSize(15);

      return 0;
  }

Next we will add a WM_SIZE message handler, this will ensure that our pager control will be correctly positioned whenever the view is resized. You can use the class wizard to do this.

 void COutbarView::OnSize(UINT nType, int cx, int cy)
 {
     CView::OnSize(nType, cx, cy);
     if(m_wndPager.GetSafeHwnd()) {
         m_wndPager.MoveWindow(0,0,cx,cy);
     }
 }

Our final task will be to add the PGN_SCROLL and PGN_CALCSIZE message handlers for the pager control. This will notify us when the pager is being scrolled and allow us to set the scrollable size of the Outlook menu window. In addition to the PGN_ handlers, we will need to add a XTWM_OUTBAR_NOTIFY message handler. This will notify us whenever the user clicks an item in the Outlook menu. In the .cpp file for COutbarView, add the following to the message map:

 BEGIN_MESSAGE_MAP(COutbarView, CView)
      //{{AFX_MSG_MAP(COutbarView)
      ON_WM_SIZE()
      ON_WM_CREATE()
      ON_MESSAGE( XTWM_OUTBAR_NOTIFY,  OnOutbarNotify )
      //}}AFX_MSG_MAP
      ON_NOTIFY(PGN_SCROLL, IDC_PAGER_CTRL, OnPagerScroll)
      ON_NOTIFY(PGN_CALCSIZE, IDC_PAGER_CTRL, OnPagerCalcSize)
 END_MESSAGE_MAP()

And the following member functions to the .cpp...

 void COutbarView::OnPagerCalcSize(
     NMHDR* pNMHDR, LRESULT* pResult)
 {
     NMPGCALCSIZE* pNMPGCalcSize = (NMPGCALCSIZE*)pNMHDR;
     *pResult = 0;

     switch(pNMPGCalcSize->dwFlag)
     {
      case PGF_CALCWIDTH:
          break;

      case PGF_CALCHEIGHT:
          pNMPGCalcSize->iHeight = m_wndOutlookBar.GetCount()
              *(::GetSystemMetrics(SM_CYICON)*2);
          break;
      }
  }

 void COutbarView::OnPagerScroll(NMHDR* pNMHDR, LRESULT* pResult)
 {
    NMPGSCROLL* pNMPGScroll = (NMPGSCROLL*)pNMHDR;
      *pResult = 0;
 }

 LRESULT COutbarView::OnOutbarNotify(UINT lParam, LONG wParam)
 {
    switch( wParam ) // control id.
    {
      case IDC_OUTBAR:
      {
         // Get the menu item.
         XT_CONTENT_ITEM* pContentItems =
                m_wndOutlookBar.GetMenuItem((int)lParam);
         ASSERT(pContentItems);

         AfxMessageBox(pContentItems->m_strText);
       }
       break;
     }
     return 0;
 }

and header file.

 // Generated message map functions
 protected:
     //{{AFX_MSG(COutbarView)
     afx_msg void OnSize(UINT nType, int cx, int cy);
     afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
     afx_msg LRESULT OnOutbarNotify(UINT lParam, LONG wParam);
     //}}AFX_MSG
     afx_msg void OnPagerScroll(
         NMHDR* pNMHDR, LRESULT * pResult);
     afx_msg void OnPagerCalcSize(
          NMHDR* pNMHDR, LRESULT* pResult);
     DECLARE_MESSAGE_MAP()

And that should just about do it. If you are using Visual C++ 5 you will need to install the latest platform SDK for Visual C++ 5 to use the pager control...have fun!