分享
 
 
 

Visual C++的程序设计技巧

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Visual C++的程序设计技巧

山东科技大学智能工程研究所 杨在春 何明祥

Microsoft Visual C++是一种可视化编程语言,因功能强大而受到广大程序设计人员的青睐。但是,由于VC++的应用程序框架结构非常复杂,使得许多初学者望而却步。本文通过对设置视图背景颜色和改变对话框标题的几种实现方法的分析研究,揭示了VC++程序代码执行时的一些本质特征和有关的程序设计技巧,对理解MFC库的结构和Windows操作系统的内部工作方式提供了一定的帮助。

设置视图背景颜色

对于VC++文档、视结构中的视图,从用户的角度来看,只是可以改变大小、位置的普通窗口,同其他基于Windows应用程序的窗口是一样的;从程序员的角度来看,视图并不是普通的窗口,而是从MFC库中CView类派生的类对象。像任何VC++对象一样,视图对象的行为由类的成员函数(数据成员)决定,包括派生类中应用程序定义的函数和从基类继承来的函数。

提出问题

视图的背景一般来说是白色的,在缺省情况下,它和系统定义的颜色COLOR_WINDOW是一致的。设计者一般会希望自己的程序可以让用户轻松地改变窗口背景颜色,或是用漂亮的图片来充填背景。我们可以用Windows函数SetSysColors来重新指定COLOR_WINDOW所对应的实际颜色,来达到改变视图背景颜色的目的。但这样会同时改变其他应用程序的视图窗口背景,使得整个Windows系统的颜色设置产生混乱。另外,我们可能会用以下方法来设置视图的背景颜色,即在CView的OnDraw函数中添写如下一段程序代码:

void CTestView::OnDraw(CDC* pDC)

{

CTestDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

CRect rectClient;

CBrush brushBkColor;

GetClientRect(rectClient);

brushBkColor.CreateSolidBrush(RGB(255,0,0));

pDC->DPtoLP(rectClient);

pDC->FillRect(rectClient,&brushBkColor);

}

这样可以达到改变当前应用程序的视图背景的目的,但同时也产生了一些不良影响,使得程序运行效果不尽如人意。

分析问题

我们知道,在VC++的文档、视结构中,CView的OnDraw函数用于实现绝大部分图形绘制的工作。如果用户改变窗口尺寸,或者显示隐藏的区域,OnDraw函数都将被调用来重画窗口。并且,当程序文档中的数据发生改变时,一般必须通过调用视图的Invalidate(或InvalidateRect)成员函数来通知Windows所发生的改变,对Invalidate的调用也会触发对OnDraw函数的调用。正因为OnDraw函数被频繁调用,所以在其执行时,每次都刷新填充一次视图客户区域,便会使屏幕不稳定,产生闪烁现象。

笔者通过对VC++应用程序框架结构和Windows消息映射系统的仔细研究,找到另外一种改变视图背景的方法,其执行效果比上述两种方法都好。其实在程序调用OnDraw函数之前,会触发一个Windows消息:WM_ERASEBKGND,以擦除视图刷新区域。在缺省情况下,Windows系统使用视图窗口注册时窗口类中的成员hbrBackground所描述的画刷来擦除屏幕,这一般会将屏幕刷新成COLOR_WINDOW所对应的颜色。因此,在OnDraw函数中设置背景颜色的执行过程是这样的:先将屏幕刷新成COLOR_WINDOW所对应的颜色,接着又在OnDraw函数中填充其他颜色,这正是产生屏幕闪烁的根本原因。

解决问题

通过上述分析,我们应将视图背景颜色填充移到Windows消息:WM_ERASEBKGND所对应的消息映射函数中,而不是在OnDraw函数中。我们可以通过下列步骤实现这一过程:在文档类中增加一成员变量m_viewBkColor保存当前背景颜色,同时增加两个成员函数GetViewBkColor和SetViewBkColor对其进行读写操作。这样做的好处是可以对m_viewBkColor成员进行序列化,将其和文档联系在一起,打开某一文档时,其背景将和上一次程序操作该文档时的背景保持一致。在视图类中为视图的Windows消息WM_ERASEBKGND增加消息映射函数OnEraseBkgnd,代码如下:

BOOL CTestView::OnEraseBkgnd(CDC* pDC)

{

CRect rect;

CBrush brush;

brush.CreateSolidBrush(GetDocument()->GetViewBkColor());

pDC->GetClipBox(rect);

pDC->FillRect(rect,&brush);

return true;

}

在该函数中不需要对客户区域矩形进行设备坐标到逻辑坐标的转换,并且Windows在调用该函数时会自动进行裁剪区域的计算,使得需要刷新的屏幕面积达到最小。这样我们可以在程序中通过设计下列菜单函数轻松地改变视图背景的颜色,而且运行效果相当令人满意。

void CTestView::OnChangeViewBkcolor()

{

CColorDialog cdlg;

if(cdlg.DoModal()==IDOK)

{

GetDocument()->SetViewBkColor

(cdlg.GetColor());

InvalidateRect(NULL);

}

}

改变对话框标题

提出问题

在VC++程序设计过程中经常会遇到这样的情况:执行程序的多个地方需要调用同一个对话框,但在不同的情况下希望给对话框加上不同的标题。开始我们可能会用下面的一段程序以达到这一目的:

CTestDialog dlg;

dlg.SetWindowText(“标题-1");

dlg.DoModal();

利用上述办法,我们本希望在程序不同的地方,通过设置函数SetWindowText不同的参数,以达到使同一对话框具有不同标题的目的,但这样做是行不通的。

分析问题

利用这种方法,当执行该段程序时,在一个可以忽略的错误之后,对话框的标题不会发生任何改变。这是因为,VC++程序设计中,大部分窗体是动态创建的。比如上述对话框,在对dlg.DoModal的调用之前,虽然已构造了对话框的VC++对象,但窗体对象还没有被创建,显然对一个没有创建窗体对象的对话框设置标题是行不通的。另外,dlg.DoModal的调用结束时,对话框窗体对象将立即被释放,因此在该函数之后设置对话框标题也是不行的。

解决问题

通过对VC++框架结构中函数的调用顺序的分析,我们发现在dlg.DoModal执行的开始时,程序会自动调用对话框的一系列初始化函数,其中包括对对话框成员函数OnInitDialog的调用,从这里入手,将找到改变对话框标题的办法。为此,首先为对话框引进一个类型为CString的公有成员变量m_strCaption,并将上述程序段改为:

CTestDialog dlg;

dlg.m_strCaption = “标题-1";

dlg.DoModal();

然后重载对话框的虚成员函数OnInitDialog如下:

BOOL CTestDialog::OnInitDialog()

{

CDialog::OnInitDialog();

SetWindowText(m_strCaption);

return TRUE;

}

通过这种办法,每次在打开对话框之前,只要将对话框公有成员变量m_strCaption设置为一个不同的值,就可使得对话框有不同的标题。

小 结

本文介绍的2个技巧有一个相似之处,就是用于解决问题的程序实现代码基本上是相同的,只是被放在了程序流程的不同地方。这正是学习和熟练掌握VC++的一个非常重要的方面,是影响其程序执行效率和性能的关键。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有