在进行ATL/WTL项目开发时,经常需要实现类似于Microsoft Outlook的导航栏功能。本文将介绍如何将Iuri Apollonio开发的MFC Outlook Bar控件移植到WTL项目中,并提供详细的使用指南。
Iuri Apollonio开发的Outlook Bar控件原本是基于MFC的。本文将介绍如何将这个控件移植到WTL项目中。移植工作主要涉及三个ATL文件:
标题栏可以在atlcaptionbar.h中找到,包含了主要的CCaptionBar类。而flatbutton类可以在atlflatbutton.h中找到,包含了主要的CButtonST类。
COutlookSplitterWindow类是从WTL的CSplitterWindow类继承而来,为了实现左侧面板固定宽度的功能,需要添加额外的功能。这种功能在基类中对于右侧面板是存在的,但需要进行一些调整以使其表现得像Outlook的分隔器。原始的CGfxSplitterWindow并没有被移植,因为MFC和WTL的分隔器类存在差异。
要使用这个控件,需要WTL库。这些库可以从Microsoft的官方网站下载。网上有许多文章介绍了如何下载和使用WTL库,因此本文不再赘述。
注意:这个控件使用了WTL的CString类和STL的std::list模板类。
确保在项目中包含以下ATL文件:
#include "stdafx.h"
#include "atlwin.h"
#include "atlctrls.h"
#include "atlmisc.h"
atlmisc.h是必须的,因为它包含了WTL CString类的定义。
在主框架类中添加头文件atloutbarctrl.h和atloutbarsplit.h,并声明Outlook Bar控件、Outlook Bar分隔器对象以及在Outlook Bar中使用的图像列表的实例。
COutBarCtrl wndBar;
CImageList imaLarge, imaSmall;
COutlookSplitterWindow m_splitter;
创建Outlook分隔器类,例如:
m_hWndClient = m_splitter.Create(m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE);
在MainFrame类的OnCreate函数中创建Outlook Bar控件,并设置图像列表,例如:
DWORD dwf = COutBarCtrl::fDragItems | COutBarCtrl::fEditGroups |
COutBarCtrl::fEditItems | COutBarCtrl::fRemoveGroups |
COutBarCtrl::fRemoveItems | COutBarCtrl::fAddGroups |
COutBarCtrl::fAnimation;
if (!wndBar.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), m_splitter.m_hWnd, 1234, dwf)) {
DWORD word = GetLastError();
return 0;
}
wndBar.SetOwner(m_hWnd);
imaLarge.Create(IDB_IMAGELIST, 32, 0, RGB(128, 128, 128));
imaSmall.Create(IDB_SMALL_IMAGELIST, 16, 0, RGB(0, 128, 128));
wndBar.SetImageList(&imaLarge, COutBarCtrl::fLargeIcon);
wndBar.SetImageList(&imaSmall, COutBarCtrl::fSmallIcon);
wndBar.SetAnimationTickCount(20);
wndBar.SetAnimSelHighlight(200);
wndBar.AddFolder("Folder 1", 0);
wndBar.AddFolder("Folder 2", 1);
wndBar.AddFolder("Folder 3", 2);
wndBar.InsertItem(0, 0, "Item 1", 0, 0);
wndBar.InsertItem(0, 1, "Item 2", 1, 0);
wndBar.InsertItem(0, 2, "Item 3", 2, 0);
为了使分隔器表现得像Outlook分隔器,需要设置一些分隔器方法:
m_splitter.m_bFullDrag = false; // Draws the Ghost bar instead
m_splitter.SetSplitterExtendedStyle(SPLIT_LEFTALIGNED); // Aligns the outlook bar to the left
m_splitter.SetSplitterPanes(wndBar, m_list); // Set the outlook bar on the left pane
m_splitter.SetSplitterPos(120); // width of the initial outlook bar
为了接收标签被选中时的事件,需要在消息映射中添加宏:
MESSAGE_HANDLER(WM_OUTBAR_NOTIFY, OnOutbarNotify)
在onNotify处理器中,捕获事件:
LRESULT OnOutbarNotify(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
switch (wParam) {
case NM_OB_ITEMCLICK: {
int index = (int)lParam;
CString cs, cs1;
cs1 = wndBar.GetItemText(index);
cs.Format("Clicked on %d - <%s>", (int)lParam, cs1);
MessageBox(cs, "Outlook Bar", MB_OK);
return 0;
}
case NM_OB_ONLABELENDEDIT: {
OUTBAR_INFO *pOI = (OUTBAR_INFO *)lParam;
return 1;
}
case NM_OB_ONGROUPENDEDIT: {
OUTBAR_INFO *pOI = (OUTBAR_INFO *)lParam;
return 1;
}
case NM_OB_DRAGITEM: {
OUTBAR_INFO *pOI = (OUTBAR_INFO *)lParam;
return 1;
}
}
return 0;
}