学习VC也有一段时间了,总体感觉“太难、太复杂”,和C#、VB等其他可视化开发环境相比,上手比较难。正好有同学让我帮忙做一个VC作业,答应了,不过真没什么信心,不过花了一天的时间总算搞定。好了,闲话少说,来看看具体是什么东东。
题目:建一个单文档窗口,将视口切分成两个,一个放滑动条,另一个画图(随便画,矩形什么的都行),用窗口中的滑动条控制另一个窗口图形的大小和颜色。
分析:该题目主要是运用VC6.0的单文档拆分技术然后两个视图之间进行通信,一个View控制另一个View,另外还要用到滑动条类CSliderCtrl,绘图功能等。这还挺有难度。
下面先看我做的Demo:

下面介绍具体的实现过程:
一、实现单文档的拆分
1、首先创建一个单文档工程Demo
在利用类向导创建一个CControlView类,由于我们要添加如滑动条之类的控件,所以我们让CControlView类派生自CFromView类。
2、切分窗口
使用CSplitterWnd类进行切分,关于CSplitterWnd类的用法可参考VC6.0实现窗口的任意分割及视图间通信(转载)一文,这里不作具体讲解。在CMainFrame类中添加一个成员变量(具体数量视你拆分的窗口数量而定)CSplitterWnd m_wndsplitter,然后在On
2.{ 3. // TODO: Add your specialized code here and/or call the base class 4. m_wndsplitter.CreateStatic(this,1,2); 5. m_wndsplitter.CreateView(0,0,RUNTIME_CLASS(CControlView),CSize(300,300),pContext); 6. m_wndsplitter.CreateView(0,1,RUNTIME_CLASS(CDemoView),CSize(150,200),pContext); 7. return TRUE; 8.}Build 运行,我们可以看到这是程序会报错,错误提示如下:
C:\Users\Outshine\Desktop\Demo\MainFrm.cpp(114) : error C2653: 'CControlView' : is not a class or namespace name
C:\Users\Outshine\Desktop\Demo\MainFrm.cpp(114) : error C2065: 'classCControlView' : undeclared identifier
C:\Users\Outshine\Desktop\Demo\MainFrm.cpp(115) : error C2653: 'CDemoView' : is not a class or namespace name
C:\Users\Outshine\Desktop\Demo\MainFrm.cpp(115) : error C2065: 'classCDemoView' : undeclared identifier
Error executing cl.exe.
Creating browse info file...
Demo.exe - 4 error(s), 0 warning(s)
为什么呢?主要是缺少包含文件,我们在MainFrm.cpp文件中加入#include "DemoView.h"、#include "ControlView.h"即两个View类的头文件,这时我们在Build,仍然会出现错误,这个原因我在以前的博文中已经说明过,大家可参考VC中出现error C2143: syntax error : missing ';' before '*'错误的解决方案一文,有详细说明。好了,这些问题都解决了Build成功,运行就出现了单文档的拆分效果。
二、在CDemoView类中添加画图程序
由于最后实现的是CControlView类视图控制CDemoView类视图画图改变图形属性的效果,所以我们只需要在CDemoView中添加一个画图函数,在CControlView类中根据消息响应来调用这个画图函数即可,考虑一下,程序需要实现改变图形形状,图形大小,图形颜色等熟悉,所以画图函数需要三个参数UINT DrawType,CRect Rect,COLORREF RGB。下面是画图函数DrawImage的定义:
02.{ 03. this->Invalidate(); 04. this->UpdateWindow(); 05. CClientDC dc(this); 06. CPen pen(PS_SOLID,10,RGB); 07. dc.SelectObject(&pen); 08. CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); 09. dc.SelectObject(pBrush); 10. switch(DrawType) 11. { 12. case 1: 13. dc.Rectangle(Rect); 14. break; 15. case 2: 16. dc.Ellipse(Rect); 17. break; 18. } 19.}三、在CControlView类中添加滑动条等控件

具体添加控件如上图所示,单选按钮控制画图形状,滑动条控制图形大小和图形颜色。
四、添加消息响应事件关联
为了实现CControlView类视图控制CDemoView类视图改变图形的属性。我们需要为单选按钮、滑动条添加消息响应。单选按钮具体见源文件,我们来看一下滑动条消息响应事件的添加:
1、添加相关变量
利用ClassWizard添加相关变量,滑动条添加CSliderCtrl类型的变量,如CSliderCtrl m_Slider_Len等,具体变量类型如下图所示:

2、关联一个消息响应事件
同样利用ClassWizard添加消息响应,选中Objects ID 中选择 IDC_SLIDER_LEN,Message Map中选中NM_CUSTOMDRAW 添加编辑,下面是消息响应函数OnCustomdrawSliderLen的具体实现:
01.void CControlView::OnCustomdrawSliderLen(NMHDR* pNMHDR, LRESULT* pResult) 02.{ 03. // TODO: Add your control notification handler code here 04. m_Slider_Len.SetRange(150,500); 05. m_Slider_Wid.SetRange(150,500); 06. m_Slider_R.SetRange(0,255); 07. m_Slider_G.SetRange(0,255); 08. m_Slider_B.SetRange(0,255); 09. UpdateData(true); 10. m_len=m_Slider_Len.GetPos(); 11. m_wid=m_Slider_Wid.GetPos(); 12. m_red=m_Slider_R.GetPos(); 13. m_green=m_Slider_G.GetPos(); 14. m_blue=m_Slider_B.GetPos(); 15. Rect=CRect(100,100,m_len,m_wid); 16. RGB=RGB(m_red,m_green,m_blue); 17. UpdateData(false); 18. *pResult = 0; 19.}注意:为了使多个滑动条同时关联OnCustomdrawSliderLen函数,需要修改映射表,将controlView.cpp中的映射表
BEGIN_MESSAGE_MAP(CControlView, CFormView)
//{{AFX_MSG_MAP(CControlView)
ON_BN_CLICKED(IDC_RECT, OnRect)
ON_BN_CLICKED(IDC_ELLI, OnElli)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER_LEN,IDC_SLIDER_WID, OnCustomdrawSliderLen)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
修改为
BEGIN_MESSAGE_MAP(CControlView, CFormView)
//{{AFX_MSG_MAP(CControlView)
ON_BN_CLICKED(IDC_RECT, OnRect)
ON_BN_CLICKED(IDC_ELLI, OnElli)
ON_NOTIFY_RANGE(NM_CUSTOMDRAW, IDC_SLIDER_LEN,IDC_SLIDER_WID, OnCustomdrawSliderLen)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这时,我们Build运行程序,发现,拖动滑动条已经能够改变编辑框中的数字了,说明消息响应添加成功。但如何控制CDemoView类视图实现画图呢?
四、实现视图间通信
视图间通信方式有多种,可参考VC6.0实现窗口的任意分割及视图间通信(转载)一文,下面是具体源码,不多说了。
2.CDemoView *m_this = (CDemoView*)pMainFrm->m_wndsplitter.GetPane(0,1); 3.m_this->DrawImage(m_nDrawType,Rect,RGB); //为CDemoView设置图像样式,当然了要在CDemoView类中添加一个DrawImage函数实现视图通信后的OnCustomdrawSliderLen函数。
01.void CControlView::OnCustomdrawSliderLen(NMHDR* pNMHDR, LRESULT* pResult) 02.{ 03. // TODO: Add your control notification handler code here 04. m_Slider_Len.SetRange(150,500); 05. m_Slider_Wid.SetRange(150,500); 06. m_Slider_R.SetRange(0,255); 07. m_Slider_G.SetRange(0,255); 08. m_Slider_B.SetRange(0,255); 09. UpdateData(true); 10. m_len=m_Slider_Len.GetPos(); 11. m_wid=m_Slider_Wid.GetPos(); 12. m_red=m_Slider_R.GetPos(); 13. m_green=m_Slider_G.GetPos(); 14. m_blue=m_Slider_B.GetPos(); 15. Rect=CRect(100,100,m_len,m_wid); 16. RGB=RGB(m_red,m_green,m_blue); 17. UpdateData(false); 18. CMainFrame * pMainFrm = (CMainFrame*)AfxGetMainWnd(); 19. CDemoView *m_this = (CDemoView*)pMainFrm->m_wndsplitter.GetPane(0,1); 20. m_this->DrawImage(m_nDrawType,Rect,RGB); //为CDemoView设置图像样式,当然了要在CDemoView类中添加一个DrawImage函数好了就写到这里了,欢迎大家批评留言。
最后是Demo的下载地址:VC++6.0 单文档拆分与多视图通信(含滑动条改变图像颜色实例)
相关文章: