MFC程序员WTL指南(8)分隔窗口
2008-01-19 20:26:47 来源:WEB开发网在分隔窗口的窗格中使用ActiveX控件与在对话框中使用ActiveX控件类似,使用CAxWindow类的方法在运行是创建控件,然后将这个CAxWindow指定给分隔窗口的窗格。下面演示了如何在水平分隔窗口下面的窗格中使用浏览器控件:
// Create the bottom pane (browser)
CAxWindow wndIE;
const DWORD dwIEStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
WS_HSCROLL | WS_VSCROLL;
wndIE.Create ( m_wndHorzSplit, rcDefault,
_T("http://www.codeproject.com"), dwIEStyle );
// Set the horizontal splitter as the client area window.
m_hWndClient = m_wndHorzSplit;
// Set up the splitter panes
m_wndPaneContainer.SetClient ( m_wndFormatList );
m_wndHorzSplit.SetSplitterPanes ( m_wndVertSplit, wndIE );
m_wndVertSplit.SetSplitterPanes ( m_wndPaneContainer, m_wndDataViewer );
特殊绘制
如果你想改变分隔条的外观,例如在上面使用一些材质,你可以从CSplitterWindowImpl派生新类并重载DrawSplitterBar()函数。如果你只是想调整一下分隔条的外观,可以复制CSplitterWindowImpl类的函数,然后稍做修改。下面的例子就在分隔条中使用了斜交叉线图案。
template <bool t_bVertical = true>
class CMySplitterWindowT :
public CSplitterWindowImpl<CMySplitterWindowT<t_bVertical>, t_bVertical>
{
public:
DECLARE_WND_CLASS_EX(_T("My_SplitterWindow"),
CS_DBLCLKS, COLOR_WINDOW)
// Overrideables
void DrawSplitterBar(CDCHandle dc)
{
RECT rect;
if ( m_br.IsNull() )
m_br.CreateHatchBrush ( HS_DIAGCROSS,
t_bVertical ? RGB(255,0,0)
: RGB(0,0,255) );
if ( GetSplitterBarRect ( &rect ) )
{
dc.FillRect ( &rect, m_br );
// draw 3D edge if needed
if ( (GetExStyle() & WS_EX_CLIENTEDGE) != 0)
dc.DrawEdge(&rect, EDGE_RAISED,
t_bVertical ? (BF_LEFT | BF_RIGHT)
: (BF_TOP | BF_BOTTOM));
}
}
protected:
CBrush m_br;
};
typedef CMySplitterWindowT<true> CMySplitterWindow;
typedef CMySplitterWindowT<false> CMyHorSplitterWindow;
这就是结果(将分隔条变宽是为了更容易看到效果):
窗格容器内的特殊绘制
CPaneContainer也有几个函数可以重载,用来改变窗格容器的外观。你可以从CPaneContainerImpl派生新类并重载你需要的方法,例如:
class CMyPaneContainer :
public CPaneContainerImpl<CMyPaneContainer>
{
public:
DECLARE_WND_CLASS_EX(_T("My_PaneContainer"), 0, -1)
//... overrides here ...
};
一些更有意思的方法是:
void CalcSize()
调用CalcSize()函数只是为了设置m_cxyHeader,这个变量控制着窗格容器的顶部区域的宽度和高度。不过SetPaneContainerExtendedStyle()函数中有一个BUG,导致窗格从水平切换到垂直时没有调用派生类的CalcSize()方法,你可以将CalcSize()调用改为pT->CalcSize()来修补这个BUG。
HFONT GetTitleFont()
这个方法返回一个HFONT,它被用来画顶部区域的文字,默认的值是调用GetStockObject(DEFAULT_GUI_FONT)得到的字体,也就是MS Sans Serif。如果你想改称更现代的Tahoma字体,你可以重载GetTitleFont()方法,返回你创建的Tahoma字体。
BOOL GetToolTipText(LPNMHDR lpnmh)
重载这个方法提供鼠标移到Close按钮时弹出的提示信息,这个函数实际上是TTN_GETDISPINFO的相应函数,你可以将lpnmh转换成NMTTDISPINFO*,并设置这个数据结构内相应的成员变量。记住一点,你必须检查通知代码,它可能是TTN_GETDISPINFO或TTN_GETDISPINFOW,你需要有区别的访问这两个数据结构。
void DrawPaneTitle(CDCHandle dc)
你可以重载这个方法自己画顶部区域,你可以用GetClientRect()和m_cxyHeader来计算顶部区域的范围。下面的例子演示了在水平容器的顶部区域画一个渐变填充的背景:
void CMyPaneContainer::DrawPaneTitle ( CDCHandle dc )
{
RECT rect;
GetClientRect(&rect);
TRIVERTEX tv[] = {
{ rect.left, rect.top, 0xff00 },
{ rect.right, rect.top + m_cxyHeader, 0, 0xff00 }
};
GRADIENT_RECT gr = { 0, 1 };
dc.GradientFill ( tv, 2, &gr, 1, GRADIENT_FILL_RECT_H );
}
例子工程代码中演示了对这几个方法的重载,使得结果看起来是这个样子的:
从上面的图中可以看到,这个演示程序有一个Splitters菜单,通过它可以在各种风格的分隔条(包括自画风格)和窗格容器之间切换,比较它们之间的异同。你还可以锁定分隔条的位置,这是通过设置和取消SPLIT_NONINTERACTIVE扩展风格来实现的。
在状态栏显示进度条
正如我在前几篇文章中做得保证那样,新的ClipSpy也演示了如何在状态条上创建进展条,它和MFC版本得功能一样,几个相关得步骤是:
- 得到状态条第一个窗格得坐标范围RECT
- 创建一个进展条作为状态条得子窗口,窗口大小就是哪个状态条窗格得大小
- 随着edit控件被填充的同时更新进展条的位置
这些代码在CMainFrame::CreateProgressCtrlInStatusBar()函数中。
继续
在第八章我将介绍属性页和向导对话框的用法
参考
WTL Splitters and Pane Containers by Ed Gadziemski
修改记录
July 9, 2003: 文章第一次发布。
更多精彩
赞助商链接