【问题标题】:Implementing scroll in custom drawn control in WTL在 WTL 中实现自定义绘制控件的滚动
【发布时间】:2013-08-12 22:26:32
【问题描述】:

我已经用 WTL 中的复选框创建了我自己的自定义绘制列表,我现在想让它可滚动,问题是我正在继承我绘制的静态文本控件。我不知道静态控件是否支持以任何方式滚动.. 无论如何,我的问题是如何使我的自定义控件可滚动,我是否必须自己实现该机制?

【问题讨论】:

    标签: winapi visual-c++ atl wtl


    【解决方案1】:

    是的,您必须完全手动实现它。这是不使用内置控件的缺点。从 ListBox 开始,然后根据您的需要对其进行自定义可能是一个更好的主意。这样一来,您就可以免费获得所有的滚动、选择和其他逻辑。

    步骤大致如下(其中部分或全部可能有 ATL/WTL 惯用语,但任何 ATL/WTL 程序员都可以从原始 Win32 来回转换):

    1. WS_HSCROLL 和/或WS_VSCROLL 窗口样式添加到您的自定义静态控件中,具体取决于您是否需要水平、垂直或两个滚动条。您可以将这些添加到传递给 CreateWindow/CreateWindowEx 函数的窗口样式列表中。

    2. 默认情况下,这些滚动条根本不会做任何事情。您需要使用SetScrollInfo 函数告诉他们该做什么。在你的情况下:

      • 第一个参数 (hwnd) 将是您的控制窗口的句柄。
      • 第二个参数(fnBar)应该是SB_HORZ来调整水平滚动条,或者SB_VERT来调整垂直滚动条。
      • 第三个参数(lpsi)是一个指向SCROLLINFO结构的指针,填充了所需的滚动参数,包括拇指的当前位置、最小值和最大值,以及使用的“页面”大小设置比例滚动条。
      • 第四个参数(fRedraw)可能应该设置为TRUE

    3. 您还需要EnableScrollBar 函数来根据需要启用/禁用滚动条。和之前的函数一样,

      • hwnd 是控制窗口的句柄
      • wSBflagsSB_HORZSB_VERTSB_BOTH
      • wArrowsESB_* 值之一,具体取决于您想要什么

    4. 最后,您需要在自定义控件的窗口过程中编写代码来处理WM_HSCROLL 和/或WM_VSCROLL 消息。每当滚动条移动时,它们就会发送到窗口。在这些消息的处理程序中,您需要执行以下操作来更新控件的状态:

      • 调用SetScrollInfo 函数将拇指更新到新位置
      • 根据滚动距离重绘控件的内容。有多种方法可以做到这一点,但我可能会使用ScrollWindowEx 函数。

      自定义控件的窗口过程需要处理WM_SIZE消息来更新滚动条状态(通过调用SetScrollInfo和/或EnableScrollBar)以响应变化窗口的大小。

    【讨论】:

    • 这一切都很好,但是 WTL 中还有 CScrollImpl,它涵盖了自定义控件的大量复杂性。
    • 我也尝试过这种方法,我按照步骤 1、2、3 和 4,现在当我得到 WM_VSCROLL 时,我执行 SetSCrollInfo 并调用 ::ScrollWindowEx(m_hWnd, 0, value,空,空,空,空,SW_INVALIDATE | SW_ERASE);但还没有,我没有正确调用它?在那个 func 调用之前我做了一个 SetRedraw(FALSe) 和它之后一个 SetRedraw(TRUE)
    • GetLastError() 返回 0;
    • 我正在使用 CMemoryDC 和 gdiplus 绘制我的控件
    • 我已经感觉到了 WM_PAINT.. ScrollWindowEx 是否应该简单地滚动静态控件内的文本?
    【解决方案2】:

    Cody Gray 为添加滚动支持提供了出色的介绍,但是您还拥有 WTL 本身的帮助。

    WTL 的atlscrl.h 为您提供类来继承和实现带有滚动的自定义窗口/控件。

    // Classes in this file:
    //
    // CScrollImpl<T>
    // CScrollWindowImpl<T, TBase, TWinTraits>
    // CMapScrollImpl<T>
    // CMapScrollWindowImpl<T, TBase, TWinTraits>
    // CFSBWindowT<TBase>
    // CZoomScrollImpl<T>
    // CZoomScrollWindowImpl<T, TBase, TWinTraits>
    // CScrollContainerImpl<T, TBase, TWinTraits>
    // CScrollContainer
    

    没有太多的代码/sn-ps 来演示使用,但仍然有一个涵盖基础知识的 WTL 示例,它也应该是一个很好的起点。 \Samples\BmpView 有一个可滚动位图的类:

    class CBitmapView : 
      public CScrollWindowImpl<CBitmapView>
    {
    public:
    

    您会发现它非常小,而且涵盖了大部分复杂性。

    【讨论】:

    • 太好了,感谢您发布此信息。你能告诉我不使用 WTL 吗? :-)
    • 感谢两位出色的回答!
    • 目前我正在看 CScrollImpl,因为它看起来更容易。
    • @CodyGray:这是可以理解的 :) WTL 被放逐和放弃,仍然可以滚动。
    • “如今人们使用什么来在 C++ 中创建完全自定义的界面”。我喜欢WTL,但它绝对不是主流。我想主流是跨平台的 UI 框架,通常会产生丑陋的 UI 和糟糕的 UX,而 .NET 与 C++ 相去甚远。
    猜你喜欢
    • 2014-12-06
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多