本以为,能把之前那个诡异的异常搞定,怀疑是因为没有设置图像的字节排列方式,从而导致的读取、绑定失败,可最后还是未果,先不管了,还是。

昨晚+今天一直在弄滑动条( CSliderCtrl ),有两种方式,静态的和动态的,静态的就是直接往窗口上拖一个控件,然后怎么搞啊搞(现在还不会),动态的是,也是我这次需要的,就是想往工具栏上放一个滑动条, 这里 给出了两种基本思路:

  • 方法1:用Rebar,然后把Slider创建在DIalogBAr上,最后ReBar.AddBar(.......)
  • 方法2:在TOOLBAR上建一个按狃,然后找到这个ID,创建CSlidertrl,最后Show
  • 我采用了第二种方法,因为在 这里 看到了现成的代码和方法描述,但也不详尽,消息的响应没怎么提(对于我这种初学者就惨了),在工具栏上插入一个滑动条的方法是,在对应的ToolBar处新建一个按钮,并带有了一个ID,设成IDC_SLIDERXX,然后在相应的ToolBar上找到这个控件,把它设置成滑动条的形状就可以。可是怎么响应相应的读取和写入的动作呢,网上提到的比较流行的一种方法是去找到 WM_HSCROLL 这个消息,重写 OnHScroll 函数,但一个控件的动作是它的父容器去捕获的,这时,在 这里 看到了一个很强大的方法,学习下了。方法是重新封装下 ToolBar ,我这里从CToolBar继承了一个类:CMToolBar,这个工具栏指的就是放有CSliderCtrl的工具栏,然后OnHScroll函数从CMToolBar处重写就可以了,赞。

    本来以为问题解决了,谁知道又衍生出一个这样的问题,我弄的是多文档的,多个Doc,每个Doc对应多个View,发现他们共享一个Slider,也难怪,这个Slider是在MainFrm下的ToolBar里的,我想了个这样的方法,解决了这个问题,感觉比较山寨,凑合着用了,在Doc里添加一个Pos变量,用来记录当前文档下的滑动条的值,CMToolBar的成员函数OnHScroll响应滑动的操作,这里,当值发生改变的时候,去获取MainFrm指针,获取View指针,获取Doc指针,然后修改Doc的值,由于修改后,需要对View选择性的进行重绘操作(我的程序有两个View),又遍历了所有的View,找到了想要的View之后,重绘后就可以了,遍历View的代码, 这里 可以看到。至于在View中如何使用这个滑动条,就直接根据Pos进行操作就可以了,至此,问题解决大半。

    还有个比较棘手的问题,怀疑是我那山寨的方法的后遗症,由于这个Slider控件是个动态出现,和其他的按钮不同步,比如,没有Doc出现的时候,这个Slider应该不可用才更合理,在 这里 ,还有 这里 知道了设置Slider不可用就是要设置它的Style,通过 GetWindowLong 函数和 SetWindowLong 函数实现,获取到Style后,并进行修改,然后加载进去就可以了。我在Doc的构造函数中实现了这个方法,即获取了MainFrm指针,根据控件的ID,找到该控件,然后修改风格,可是会报错,怎么也找不出原因,又是个诡异的错误,对那之间的指针不是很懂得,调起来也就很麻烦了。之后这样实现就可以了,把设置不可用,设置可用写成MToolBar的一个方法,这样就在Doc构造函数中,就可以直接通过MainFrm指针调用,在析构函数中同理加上设置不可用。

    除上述之外,还要响应一个消息, WM_NCACTIVATE ,它指的是ChildFrm激活,重写 OnNcActivate 函数,每当激活某个ChildFrm的时候,就用Doc中的值来更新ToolBar上的slider,也就实现了多文档下的工具栏上的插入slider控件。至此,目前的问题全部解决了。

    获取指针, 这里 写的不错,摘抄些代码如下,至于重绘的话,有InvalidateRect,还有Invalidate什么的,看了不是很懂得,就知道,优先级比较低,等到该Paint的时候,才Paint出来,相关内容可以参考 这里 ,感觉写的比较好。

    CMainFrame* pFrame = (CMainFrame *)AfxGetMainWnd();   
    CChildFrame* pChildFrame = (CChildFrame *)pFrame->GetActiveFrame();
    CFDSFrameView* pView = (CFDSFrameView *)pChildFrame->GetActiveView();
    CDC* pDC = pView->GetDC();

    下面上一些我的代码,首先是 MToolBar 中的 OnHScroll 函数和 CanUse、CanNotUse 函数:

    void CMToolBar::CanNotUse()
        long style = GetWindowLong(m_slider.m_hWnd, GWL_STYLE);    //获取样式
        style ^= WS_DISABLED;
        SetWindowLong(m_slider.m_hWnd, GWL_STYLE, style);    //设置样式
    if (!m_wndToolBar1.m_slider.Create(WS_CHILD|WS_VISIBLE | TBS_HORZ | TBS_AUTOTICKS |TBS_BOTTOM ,  
        rect, &m_wndToolBar1, IDC_SLIDER99))  
        TRACE( "Failed to create slider ctrl\n ");  
        return FALSE;  
    m_wndToolBar1.CanNotUse();    //设置不可用
    m_wndToolBar1.m_slider.SetRange(0,10);  
    m_wndToolBar1.m_slider.SetPos(2);  
    m_wndToolBar1.m_slider.ShowWindow(SW_SHOW);  

    下面是 CXXXDoc 的构造函数中的初始化部分:

    pos = 0;
    //设置可用
    CMainFrame* pFrame = (CMainFrame *)AfxGetMainWnd();   
    pFrame->m_wndToolBar1.CanUse();

    下面是 CChildFrame OnNcActivate 函数:

    BOOL CChildFrame::OnNcActivate(BOOL bActive)
        // TODO: 在此添加消息处理程序代码和/或调用默认值
        COpenGLPlatDoc* pDoc = (COpenGLPlatDoc*)this->GetActiveView()->GetDocument();
        CMainFrame* pFrame = (CMainFrame *)AfxGetMainWnd();   
        pFrame->m_wndToolBar1.m_slider.SetPos(pDoc->pos);
        return CMDIChildWnd::OnNcActivate(bActive);

    关键的代码(核心/实现的代码的80%部分)就上面这些,别看这些,折腾的可够呛的,上张图纪念下:

    这次的内容都是关于MFC的,没有涉及到OpenGL的知识,算是对MFC又掌握了些知识吧,要做的还蛮多的,继续~