【问题标题】:Display child window on fixed position in MFC CScrollView在 MFC CScrollView 中的固定位置显示子窗口
【发布时间】:2013-09-09 13:00:41
【问题描述】:

我有一个从 CScrollView 继承的窗口,它处理 WM_PAINT 并显示一个图形。该图具有不同类型的元素,元素的类型由元素的形状标记。

我想显示一些图例,以便用户知道每个形状的含义。由于用户通常不会查看此图例,因此想法是在视图控件的右上角会有一个小图标。当用户将鼠标移到此图标上时,它将扩展为小矩形,显示图形中使用的形状的图例。当鼠标移出这个矩形时,它会折叠回小图标。

这是我迄今为止尝试过的:

  1. 在视图类的 WM_PAINT 处理程序中使用 GDI 绘制热点图标和图例矩形。
  2. 将热点实现为一个单独的窗口,该窗口创建为滚动视图的子级。
  3. 将热点实现为单独的窗口,但将其创建为没有父窗口的弹出窗口。

如果用户滚动图形视图,版本 1 和 2 的行为会很奇怪。

在版本 1 中,我可以在执行滚动时看到伪影(按钮在视图中被涂抹)我猜在滚动期间现有图像不会失效,而只是移动了。

在版本 2 中没有拖尾,但每当我收到 VM_HSCROLL 和 WM_VSCROLL 消息时,我都需要移动子窗口,而这些消息不够精确,无法以这种方式使用。在滚动过程中,我可以看到我的按钮移动了几个像素,然后跳到了正确的位置。

版本 3 是最令人不安的,因为图例不是图形视图的子视图,我得到一些奇怪的行为,即使未显示图形视图,也会显示图例按钮,我认为这个问题太多了投入时间的可行发展路径。

我认为版本 2 是最有前途的,但我需要找到一种方法让子窗口在滚动期间停留在一个位置。

有没有人成功实施过这样的事情?还有其他一些我可以研究的实现吗?

【问题讨论】:

    标签: c++ windows mfc


    【解决方案1】:

    CScrollViewOnScrollBy 虚拟方法,可以滚动视图控件的整个客户区。您可以重写此方法并实现自己的滚动功能。

    ::ScrollWindowEx 有一个参数prcScroll,可以指定只滚动的客户区的一部分。

    新的OnScrollBy 将客户区分成4 个条带,并为每个条带调用::ScrollWindowEx

    这些条纹是:

    1. 图标上方的客户区(整个客户区的矩形宽度)
    2. 图标左侧的客户区(矩形高度与图标相同)
    3. 图标右侧的客户区(矩形高度与图标相同)
    4. 图标下方的客户区(整个客户区的矩形宽度)

      1 1 1 1 1
      2 2 2 * 3
      4 4 4 4 4
      4 4 4 4 4

    滚动所有单个客户矩形后,只需使图标所在的客户区域无效。

    【讨论】:

    • 一个更简单的解决方案可能也会起作用:在您的 OnScrollBy 覆盖中,您可以 ::ScrollWindowEx 整个客户区,然后使图标所在的矩形加上上方/下方的区域无效或它的左/右,取决于滚动方向和距离。
    • 其实IInspectable,你的答案是正确的。我的过度工程导致 ::ScrollWindowEx 调用的顺序出现一些问题。如果窗口向上滚动,则滚动应按以下顺序进行:1、2、3、4。但如果窗口向下滚动应按此顺序进行:4、3、2、1。您可以单独回复这样我就可以将其标记为已回答?
    【解决方案2】:

    你可以简单地使用

    CPoint GetScrollPosition( ) const;
    

    获取滚动视图当前滚动位置并相应地重新计算“静态”标签偏移量的方法。

    顺便说一句:使用 CScrollView 的方法代替 WM_PAINT

    virtual void OnDraw( CDC* pDC );
    

    这很重要

    【讨论】:

    • OnDraw WM_PAINT 处理程序。
    • IInspectable,当您使用 Printer DC 时,您会记得 OnDraw。特别是对于 CSCrollView :)
    • 哇...我不知道你在这里想说什么。 OnDraw 是否被传递给绘图 DC、窗口 DC、打印机 DC 或元 DC 与我的评论完全无关,即 OnDraw WM_PAINT 处理程序。因此,如果您说“使用 X(当 Y 发生时调用),而不是调用 X 来响应 Y”表明您缺乏对 MFC 的基本了解。
    • 那么,为什么你认为微软在 CView 中公开了 OnDraw 方法,而不是告诉人们直接使用 WM_PAINT?我的意见是最好使用标准的 MFC 方式来执行此操作,并在真正需要时返回 WinAPI。
    • @IInspectable OnDraw 和 WM_PAINT 不一样。 OnDraw 发生在 DC 设置之后,这在 CScrollView 中很重要,因为它正在设置其视口。查看 CScrollView::OnPrepareDC 了解更多信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    相关资源
    最近更新 更多