C++ 如何使用ATL/WTL创建自己的类本机(可复制)控件?

C++ 如何使用ATL/WTL创建自己的类本机(可复制)控件?,c++,winapi,visual-c++,atl,wtl,C++,Winapi,Visual C++,Atl,Wtl,使用WTL时,可以自由复制表示内置对象的控件: // Notice that CWindow is passed by _copy_, because it only wraps the HWND int OnNotifyFormat(CWindow wndFrom, int nCommand) { ... } 现在,如果我想拥有自己的控件,很容易说: template <class T, class TBase = CWindow, class TWinTraits = CContro

使用WTL时,可以自由复制表示内置对象的控件:

// Notice that CWindow is passed by _copy_, because it only wraps the HWND
int OnNotifyFormat(CWindow wndFrom, int nCommand) { ... }
现在,如果我想拥有自己的控件,很容易说:

template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
struct CMyControlImpl: public CWindowImpl<T, TBase, TWinTraits>
{
    std::vector<int> internal_info;

    BEGIN_MSG_MAP_EX(...)
        ...
    END_MSG_MAP()
};

struct CMyControl : public CMyControlImpl<CMyControl>
{
    DECLARE_WND_CLASS_EX(TEXT("MyControl"), 0, COLOR_WINDOW)
};
因为
CMyControl
不仅仅是一个句柄——它包含数据本身


关于此复制行为,使控件类与内置ATL/WTL类一致的正确方法是什么?

WTL中有一些自定义控件,在
\Include\atlctrlx.h
中:

///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CBitmapButtonImpl<T, TBase, TWinTraits>
// CBitmapButton
// CCheckListViewCtrlImpl<T, TBase, TWinTraits>
// CCheckListViewCtrl
// CHyperLinkImpl<T, TBase, TWinTraits>
// CHyperLink
///////////////////////////////////////////////////////////////////////////////
//此文件中的类:
//
//CBitmapButtonImpl
//CBITMAP按钮
//CCheckListViewCtrlImpl
//CCheckListViewCtrl
//CHyperLinkImpl
//切珀林
除此之外,您还会发现定制的WTL控件是以正确的方式制作的

控件的“可复制性”基于这样一个事实,即您可以通过手柄
HWND
使用标准控件,并且您可以轻松地复制、附加、分离等。此手柄有效,但整个控件良好。包装器类很薄,只包含
HWND
成员变量


另一方面,正如您所注意到的,自定义控件具有附加信息,您无法轻松复制它们。您仍然可以通过控件动态分配/发布这些附加信息,您将实现附加的特定于控件的窗口消息和通知,然后您可以创建一个瘦包装类,将方法转换为消息,将它们发送到实际控件,而实际控件将处理它们,特别是通过将带有参数的消息转换回实际方法。这使您可以复制瘦包装类,但控件本身要复杂得多,也很麻烦(通常不需要这样做)

哇,有意思,我没注意到。所以“自定义”内置控件也不是这样工作的?!(例如,我没有看到
CBitmapButton
的构造函数接受
HWND
;它似乎保存着所有的信息本身。)是的,WTL控件保存着类的信息。但它们相对简单。正如我所说的,你可以按照你想要的方式去做,但这不是最简单的方式。如果您是从标准控件派生自定义控件,您可能会发现创建基本窗口/控件(例如使用对话框模板)很有用,然后在代码中使用现有原始控件窗口的子类初始化自定义控件。这是在参考资料中使用模板控制控件的一种很酷的方法。
///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CBitmapButtonImpl<T, TBase, TWinTraits>
// CBitmapButton
// CCheckListViewCtrlImpl<T, TBase, TWinTraits>
// CCheckListViewCtrl
// CHyperLinkImpl<T, TBase, TWinTraits>
// CHyperLink