学习VC也有一段时间了,总体感觉“太难、太复杂”,和C#、VB等其他可视化开发环境相比,上手比较难。正好有同学让我帮忙做一个VC作业,答应了,不过真没什么信心,不过花了一天的时间总算搞定。好了,闲话少说,来看看具体是什么东东。
题目:建一个单文档窗口,将视口切分成两个,一个放滑动条,另一个画图(随便画,矩形什么的都行),用窗口中的滑动条控制另一个窗口图形的大小和颜色。
分析:该题目主要是运用VC6.0的单文档拆分技术然后两个视图之间进行通信,一个View控制另一个View,另外还要用到滑动条类CSliderCtrl,绘图功能等。这还挺有难度。
下面先看我做的Demo:
下面介绍具体的实现过程:
一、实现单文档的拆分
1、首先创建一个单文档工程Demo
在利用类向导创建一个CControlView类,由于我们要添加如滑动条之类的控件,所以我们让CControlView类派生自CFromView类。
2、切分窗口
使用CSplitterWnd类进行切分,关于CSplitterWnd类的用法可参考VC6.0实现窗口的任意分割及视图间通信(转载)一文,这里不作具体讲解。在CMainFrame类中添加一个成员变量(具体数量视你拆分的窗口数量而定)CSplitterWnd m_wndsplitter,然后在OnCreateClient函数中添加如下代码
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的具体实现:
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函数。
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 单文档拆分与多视图通信(含滑动条改变图像颜色实例)
相关文章:
VC6.0实现窗口的任意分割及视图间通信(转载)