一个静态分割器,具有隐藏/显示多个列/行的能力






4.75/5 (12投票s)
2002年8月7日
2分钟阅读

133053

2888
一个静态分割器,具有隐藏/显示多个列/行的能力
引言
当我在开发一个应用程序时,我意识到它需要一个静态分割器,能够同时隐藏/显示多个行或列。 令人惊讶的是,我找不到这样的组件。 最接近的解决方案是 Oleg Galkin 在这里 提出的。 他的分割器可以隐藏/显示分割器的一行(列),但只能一个。 本文提出了一个静态分割器,具有隐藏/显示多个列/行的能力。
算法扩展的问题
MFC CSplitterWnd
通过 ID 访问其窗格,ID 定义了窗格在分割器中的位置。 假设要隐藏第 n 列。 在 Oleg Galkin 的算法中,第 n 列获得了最后一列的 ID。 第 n 列之后的列向左移动 1,即 n+1 控件的 ID 被分配给控件 n,n+2 的 ID 被分配给 n+1,依此类推。 尝试将这种方法扩展到隐藏多列导致算法过于复杂。 每次隐藏列时,之前隐藏的操作中隐藏的列的 ID 都会再次更改。 因此,如果您隐藏三列,则某些控件的 ID 将更改三次。 追踪所有这些变化是一个不简单的问题。
新方法
CExtSplitter
类使用绝对地址和相对地址来操作分割器窗格。 绝对列地址是初始列号,相对地址是分割器中的当前列号。 HideColumn
和 ShowColumn
public
函数使用绝对地址。 相对地址在内部使用。 CExtSplitter
类将指向所有控件的指针保存在内部数组中。 该数组在创建分割器时初始化一次,并且在分割器的存在期间不会更改。 此数组的行和列用于按绝对 ID 访问分割器窗格。 如果分割器使用 m 行和 n 列初始化,那么隐藏第 k 列(0 < k < n),意味着隐藏最初是第 k 列的列。 请注意,在多次隐藏操作之后,第 k 列可以出现在分割器中小于 k 的任何位置。
实现细节
CExtSplitter
类具有一个显示和隐藏列的列表。 列表成员的值是一个绝对列地址,位置是相对列地址。
class CExtSplitter : public CSplitterWnd
{
public:
typedef std::list < int > LIST_INT;
CExtSplitter();
virtual ~CExtSplitter();
BOOL CreateStatic(CWnd* pParentWnd,
int nRows, int nCols,
DWORD dwStyle = WS_CHILD | WS_VISIBLE,
UINT nID = AFX_IDW_PANE_FIRST);
virtual BOOL CreateView( int row, int col,
CRuntimeClass* pViewClass, SIZE sizeInit,
CCreateContext* pContext );
void HideColumn(int colHide);
void ShowColumn(int colShow);
void HideRow(int colRow);
void ShowRow(int row);
public:
LIST_INT m_shown_cols; //shown column list
LIST_INT m_hid_cols; //hidden column list
LIST_INT m_shown_rows; //shown rows list
LIST_INT m_hid_rows; //hidden rows list
protected:
//array of pointers to splitter panes
C2DArray m_pane_ptr_array;
};
函数 HideColumn
将列从显示列的列表移动到隐藏列的列表,并重新枚举分割器窗格。 重新枚举规则的 C++ 代码如下所示
void CExtSplitter::RenumeratePanes()
{
int i,j,id;
for(i=0; i < m_nMaxRows; i++)
{
for(j=0; j < m_nMaxCols; j++)
{
CPoint pos = RelToAbsPosition(i,j);
CWnd* pPane =
(CWnd*) m_pane_ptr_array(pos.x, pos.y);
ASSERT(pPane != NULL);
id=AFX_IDW_PANE_FIRST + i * 16 + j;
int r=pPane->SetDlgCtrlID(id);
ASSERT(r);
if(IsPaneVisible(pos.x,pos.y))
pPane->ShowWindow(SW_SHOW);
else
pPane->ShowWindow(SW_HIDE);
}
}
}
其中 RelToAbsPosition
函数将相对窗格位置转换为绝对窗格位置。
演示项目
在演示项目中,您可以通过“视图”子菜单调用隐藏和显示函数。 CExtSplitter
类依赖于 C2DArray
,它包含在项目中。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。