提供无窗口激活

窗口创建代码(即在调用 CreateWindow 时发生的一切事情)的执行成本很高。 用来维护屏幕上的窗口的控件必须管理窗口的消息。 因此,无窗口控件比有窗口控件更快。

无窗口控件的进一步好处是,与有窗口控件不同,无窗口控件支持透明绘制和非矩形屏幕区域。 透明控件的常见示例是带有透明背景的文本控件。 该控件将绘制文本,但不会绘制背景,因此文本下的任何内容都将显露出来。 更新的窗体通常使用非矩形控件,如箭头按钮和圆形按钮。

通常,控件不需要自己的窗口,相反,它可以使用其容器的窗口服务,前提是该容器已被编写为支持无窗口对象。 无窗口控件与早期的容器向后兼容。 在未编写为支持无窗口控件的早期容器中,无窗口控件将在活动时创建窗口。

由于无窗口控件没有自己的窗口,因此容器将负责提供本应由控件自己的窗口提供的服务。 例如,如果控件需要查询键盘焦点、捕获鼠标或获取设备上下文,这些操作将由容器管理。 容器将使用 IOleInPlaceObjectWindowless 接口将发送给其窗口的用户输入消息传送到相应的无窗口控件。 (有关此接口的说明,请参阅 ActiveX SDK。)COleControl 成员函数将从容器中调用这些服务。

若要让控件使用无窗口激活,请将 windowlessActivate 标志包含在由 COleControl::GetControlFlags 返回的一组标志中。 例如:

DWORD CMyAxOptCtrl::GetControlFlags()
{
   DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}

如果你选择了 MFC ActiveX 控件向导的控件设置页上的“无窗口激活”选项,则会自动生成包含此标记的代码。

启用无窗口激活后,容器会将输入消息委托给控件的 IOleInPlaceObjectWindowless 接口。 在相应地调整鼠标坐标后,COleControl 的此接口的实现将会在控件的消息映射中调度消息。 您可以通过将对应的项添加到消息映射来处理普通窗口消息之类的消息。 在这些消息的处理程序中,应避免在使用 m_hWnd 成员变量(或使用它的任何成员函数)时不首先检查它的值是否不是 NULL。

COleControl 提供了根据需要从容器中调用鼠标捕获、键盘焦点、滚动和其他窗口服务的成员函数,包括:

在无窗口控件中,您应总是使用 COleControl 成员函数而不是对应的 CWnd 成员函数或其相关的 Win32 API 函数。

您可能希望无窗口控件是 OLE 拖放操作的目标。 通常,这需要将该控件的窗口注册为放置目标。 由于该控件没有自己的窗口,容器将使用自己的窗口作为放置目标。 该控件提供了 IDropTarget 接口的实现,容器可在适当时向其委托调用。 若要将此接口公开到容器,请重写 COleControl::GetWindowlessDropTarget。 例如:

IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
   m_DropTarget.m_xDropTarget.AddRef();
   return &m_DropTarget.m_xDropTarget;
}

另请参阅

MFC ActiveX 控件:优化