最近碰到要根据已定义的模板动态创建控件的难题,需求如下:
1. 提供几种可输入的数据类型,每个类型对应一种控件用来输入该类型
2. 可自定义输入模板,某个模板包括1种或几种数据类型
blog.csdn.net/flyback
由上面的需求可以得出结论,要实现的功能是可以动态创建各种输入控件并把它们排列在一起。
动态创建控件没啥问题,只是控件多了以后怎么办?应该需要一个可以上下滚动的窗口显示动态创建的控件
万能的网络没有告诉我答案,它只说要有光,于是就有了光,我说要有上下滚动的窗口,于是...什么都没有发生。
blog.csdn.net/flyback
过程:
1. 窗口本身是可以通过SetStyle(WS_xxx...)设置滚动条的,但是需要自己根据滚动条发出的事件对控件的位置进行调整,这个网上是有的,但是实现得比较琐碎,不愿看,可能也比较容易出错
2. 用别人的控件,网上没找到,有显示图片的,不合适
3. 用wtl自带的, 网上只说有这个东西,至于怎么用,没有人发例子,可能好简单
4. 于是只能自己上,自己好简单一下,留个念想
解题:
atlscrl.h 里
WTL有个实现模板叫做CScrollWindowImpl
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits> class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
CScrollImpl模板类WTL已经给我们实现了所有需要操作滚动条的功能,用的话就用一个特化的类 CScrollContainer
class CScrollContainer : public CScrollContainerImpl<CScrollContainer> { public: DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1) }; // blog.csdn.net/flyback
它是一个容器,那么就需要给它加上容器的内容,这个容器可以设置内容的大小,这样看来就相当于容器的大小是一个窗口,而内容的大小就是滚动条的滚动范围
所以:
在自己的窗口上加上两个对象
CScrollContainer m_wndParameters; CInternalWnd m_wndInternal;
m_wndParameters是容器,而m_wndInternal就是容器要显示的内容
class CInternalWnd:public CWindowImpl<CInternalWnd> 你懂的
初始化:
m_wndParameters.Create(m_hWnd, &rt, 0, WS_VISIBLE|WS_CHILD|WS_BORDER|..., ..., ...); m_wndParameters.ShowWindow(SW_SHOW); m_wndParameters.UpdateWindow(); // blog.csdn.net/flyback
rt是容器的大小,即要显示的窗口大小
那么,因为我们要动态创建窗口控件,所以需要选择合适的时机创建内容窗口
RECT rt = {0}; ::GetWindowRect(GetDesktopWindow(), &rt); m_wndInternal.Create(m_wndParameters.m_hWnd, &rt, "", WS_VISIBLE|WS_CHILD/*|WS_CLIPCHILDREN|WS_CLIPSIBLINGS*/); m_wndInternal.SetParent(m_wndParameters.m_hWnd); m_wndInternal.ShowWindow(SW_SHOW); m_wndInternal.UpdateWindow(); SIZE sz = {0}; sz.cy = rt.bottom; // 设置内容的高度和屏幕显示的高度一样,其实不一定够 m_wndParameters.GetClientRect(&rt); sz.cx = rt.right; m_wndParameters.SetClient(m_wndInternal.m_hWnd); m_wndParameters.SetScrollSize(sz); // blog.csdn.net/flyback
完鸟!