本以为,能把之前那个诡异的异常搞定,怀疑是因为没有设置图像的字节排列方式,从而导致的读取、绑定失败,可最后还是未果,先不管了,还是。
昨晚+今天一直在弄滑动条(
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又掌握了些知识吧,要做的还蛮多的,继续~