• 在TabCtrl上放View@MFC


    想搞定之前提到的第9点需求,在TabCtrl上放View,实现多张View的显示。TabCtrl不是个View或其派生出来的,所以不能作为ChildFrame的一张分割视图出现,这是我猜测的,也是后面的依据。所以在之前一个很好的拆分窗口的例子VIEWEX中发现可以用FormView来作为视图,而FormView是支持窗口操作的,就是会跟着生成一个窗体,然后就可以在上面放TabCtrl,那怎么在TabCtrl上放View呢,网上有方法提到现在TabCtrl上放Dialog,然后在Dialog上放View,以上是摘要。

    下面提提基本思路和参考链接,1,2,3提到怎么在Dialog上放View,1比较乱,用的是2中的代码,思路是在Dialog上放一个Static Text,然后在借助它来创建View,3中的方法是不用控件。借助的是CCreateContext,设置一些信息之后,便用它来创建View,见下面代码:

    context.m_pCurrentDoc = pDoc;
    context.m_pCurrentFrame = (CFrameWnd *)this;//设置父窗体指针,将对话框指针强制转换
    context.m_pLastView = NULL;//前一个视图为空
    context.m_pNewDocTemplate = NULL;//文档模板为空
    context.m_pNewViewClass = RUNTIME_CLASS(MView);
    //动态调用CreateObject创建一个对象并获得指针
    m_pView = (MView*)context.m_pNewViewClass->CreateObject();//通过指针创建视图对象

    关于初始化,是一个比较掣肘的问题,当你不知道它们初始化的顺序时。我从CFormView处派生出CRight,并在CRight处添加Dialog和TabCtrl成员,FormView有窗体支持的,在上面放了一个TabCtrl控件,并为它绑定了一个变量,也就是初始化交给MFC去操作了,而该更新是在DoDataExchange函数下的DDX_Control处初始化的。我想在初始化后,对TabCtrl进行大小自适应窗体。在FormView的OnInitialUpdate中进行,但之前写在了父类初始化之前了,导致那个对象为空,不能进行SetWindowPos来设置位置的。因为父类的初始化之后会调用DoDataExchange来初始化TabCtrl的。

    因此,在添加一张图片后,就让CRight为TabCtrl添加一个选项卡上去,在可以参考,方法就是New一个Dialog,添加一个选项卡Item,然后移动窗体位置什么的,可以参考。然后View的创建在Dialog中的OnInitDialog中进行,注意对于窗体是在Init中初始化,对于视图则是在InitUpdate中进行了。||

    有一点需要注意的是,CTabCtrl的一个事件OnTcnSelchangeTab1可以在其父容器的事件中找到相应的子控件里面的函数进行重写。

    以上的方法便可以实现,但会遇到一个我不知道怎么解决的问题,就是拖动FormView后,上面的控件会跟着闪烁,用了网上说的两种方法没有得到改善,并在CSDN上发帖提问,得到相应的提示后有了下面的进展与解决方法。

    (((((((((((((((((((((((((((我是括号)))))))))))))))))))))))))))

    后来又到网上寻找解决方案,在看到个对于“闪烁”这个问题很好的说法,引用如下:

    1. 如果你自己重载过OnPaint之类的消息的话,画图的时候一定要加缓冲,最后一次性画到屏幕DC上。

    2. 如果你界面布局比较复杂,层次很多,那就容易闪烁,层次越多闪的越厉害。

    3. 是否使用了TabCtrl?如果把各个页面的父窗体设为TabCtrl,那么窗体在大小改变或者刷新的时候闪的就比较厉害。UltraEdit配置界面也用到了TabCtrl,但是大小变化的时候不会闪。他的做法是,各个页面的父窗体并不是TabCtrl,各个页面与TabCtrl是平级的,但是TabCtrl的Z-Order被放在最下面。

    4. 适当的根据情况调整ClipSibling和ClipChildren属性,会明显的减少闪烁问题。

    也有个很好的帖子,谈论闪烁的原因,大致如下:

    1. 没在一个周期内把前景和背景都绘制完毕,导致前后差别大。

    2. 窗口层次过多。

    3. 使用MoveWindow或是SetWindowPos来改变窗体大小,需要绘制完毕,才调用这类函数。

    对于闪烁的本质原因,其实还是前后两次的页面的切换,反差过小,被人眼给识别出来了。WS_CLIPCHILDRENWS_CLIPSIBLINGS,在有讲解,其实一个是对兄弟窗口的绘制优化,一个是父子窗口的绘制优化。后来采用了上面的第3种方法,就是用一个View,然后把它和TabCtrl置于同级,需要注意的是要在FormView上,也就是View和TabCtrl的父级窗口上屏蔽掉背景重新绘制,就是那个OnEraseBkgnd函数,要直接返回TRUE。

    到这里,关键问题基本上就解决了,接下来,要继续解决其他问题~

    PS:以上内容由两天分别记录,以||作为分界线,因此前后可能会觉得比较跳跃。

  • 相关阅读:
    hdu 5224 Tom and paper 水题
    2015 UESTC 搜索专题N题 韩爷的梦 hash
    2015 UESTC 搜索专题M题 Palindromic String 马拉车算法
    2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp
    2015 UESTC 搜索专题J题 全都是秋实大哥 kmp
    2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
    2015 UESTC 搜索专题E题 吴队长征婚 爆搜
    2015 UESTC 搜索专题D题 基爷的中位数 二分
    2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
    2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
  • 原文地址:https://www.cnblogs.com/litstrong/p/1984219.html
Copyright © 2020-2023  润新知