您好,欢迎来到微智科技网。
搜索
您的当前位置:首页VC编程实现多交互绘图程序的设计技术

VC编程实现多交互绘图程序的设计技术

来源:微智科技网


VC编程实现多交互绘图程序的设计技术

一 ,概述 的设计技术 林军

摘要本文对DOS和Windows下的蝙程模式进行了比较,并闱VisualC++通过重 写消息循环完全实现了类似于AutoCAD操作方式的多交互的绘图程序 MINIGIS

关键词命令交互.多交互.消息循环

在众多的工程软件中.AutoCAD交互功能是公认摄强大 的,它的每一个功能都能够以多种方式完成:菜雌项,边菜 单,工具条按钮,命令行输入.其中的命令行输入是其一大特 色.从Dos下的版本到Windows下的版本,其界面做了很大的 改动,但是这一方式一直沿用,其优点电是人所共知的,如果 我们自己没计的绘图程序也能够采用这种多交互技术,无疑会 板大地提高程序地易用性.本文将对这一技术作一探讨 二,分析

AutoCAD的命令交互方式与DOS时代的基于字符串提示 的交互方式十分相象,编程模式电相对简单.用结构化程序设 计语言设计这种程序R需鬻三种基本结构:顺序结构,分支结 构循环结构就可以实现.但是Window下设计程序却是另一 种完全不同的模式:整个程序都是在一十消息循环中进行,系 统不断向应用程序发送各种消息.程序的任务就是处理自己感 兴趣的消息.来一个处理一个这样一来.程序似乎永远都在 \"被动\"的处理这些消息.而不是象DOS下的命令行程序l不 断的\"主动\"要求用户输入自己要求的数据.

那么.我们如何要求用户输人巢种格式的数据呢?以绘制

个圆为例,执行绘制圆的消息响应函数中,我们要求输入圆 心坐标,用户除了鼠标点取及命令窗口中敲坐标值外,其他的 消息统统耍过滤掉,换句话说.在用户输入了圆心坐标之前, 不让用户进行其他的活动.一种办法就是设置一个标志标示现 在是嘶唧的状态.画直线时再设置现在的状态是画直线状态等 等在各?}!l息相应函数中均根据当前状态决定不同的动作,但 是这种方法势必造成程序冗长,控制卜分复杂;男种办法就 是在需要用户输入数据或进行选择时.让程序进人一个数据输 人消息循环.正常传送备种Windows?I!f息.直到有符合要求的 消息时才退出循环这种控制方式在早期用Wlndo~.sAPI编 程时较酱邋,但用MFC编程中并不多下面的讨论就是在 MFC中用这种方式实现绘图过程的多交互.

以F讨论方法是重新编写程序的消息循环,程序在响应消 息时就向自定义的事件队列中加入一个事件,执行绘图的函数 在进人自己的数据输人消息循环中检索该事件队列,只对满足 当前需要的事件进行处氆,而数据输入消息循环只有在当用户 有输人或者取消输人时才退出. _ -- ,数据结构

本算法涉及到的有关数据结构:

对于各命令分别有一个对应的命令响应函数.为此设计 COMMAND结构,并用此结构体定义了一个全局的命令/函 数对照表,当辅入一条命令后就查询该表并诵用相应的命令响 应函数:,

事件结构EVENT的设计要尽量考虑其完整性和可扩充

性.完整性就是要能描述尽量多的事件.可扩充性主要备以

后舔加新的事件用.

事件队列封装在类CQueneEvent中,其节点元索是 EVENT结构体变量.队列中的最大的事件数目可以自行设 置.至于添加元索到队列尾部及取队列头元素等操作都是队 列操作的最基本算法. 四,系统实现

系统主界面与AutoCADR14十分类似:框架的下部是一 个命令行窗口,有命令行输人窗口和信息输出窗口. 系统实现的关键是对应用程序消息循环的控制.其基本 思路如下.应用程序消息循环只负责完成系统消息的获取和 分发.并仅仅在消息队列为空时才会退出循环;而数据输入 消息循环同样也要完成系统消息的获取和分发外,不过它在 有事件到达时也退出循环,让调用它的事件响应函数作进一 步的处理.应用程序类的Run函数的循环体中,除了词用应 用程序消息循环外,还负责检索事件队列(这时进程空闲或者 有事件到达),一旦发现有事件到达就在命令表中查找事件对 应的命令响应函数.

程序中数据输入消息循环中,我们没有直接从应用程序的 消息队列里取出井处理到来的Windows消息.之所以这样做是 因为Windows系统消息众多,而且参数复杂.处理起来不方便 不直观我们将能够产生输入的Windows消息(鼠标点取,命 令行键人,ESC链消息等)转化为事件添加到另外的事件队 列.通过检查队列中的元素就可以知道有没有输入 另外,为了使菜单命令和命令行输人命令的效果一致.只 需在菜单项的命令消息处理中加入相应的命令行键人事件.让 消息循环检索此事件并统一处理.以输入绘直线命令llne为 例.当点取菜单项时:①Run()函数PickMeasage()到

WMCOMMAND消息并分发:=>②CmyView::OnLine()响应 消息.向事件队列中加人事件{DEVMENU,ID上INE.\"line\

0}==)⑧Run()函数检索到此事件井执行相成的事件响应函 数cmdjine().当键人命令\"line\"时.直接从第三步开始. 再看看事件响应函数在有数据输入时的算法: //c输^不台法} lf{InLegal(Input)) continue; //c输人合法} \"fLegalIInput}】 break;

//c用户要求退出} ifIOuitMsgIInput¨ 始赫returi3; 一 I

//(3)根据用户的输人或选择作进~步的处理 PostProceaslInput}: }

以绘直线为例,给出实现命令交互的实际代码它所调用 的子程序没有列出.可以看到,其实现过程时非常线性,直豌 的.就像DOS下的程序一样:

intcm叫Ine【I {

CPaintptstart.ptend;

GXieseno3\"oInput(Specifystartpointerofline:}: fntret=get.point(ptstart): I/进人用户交互,获取输人点 州rat;;BREAKI//用户取消 returnO:

GXieSendTalnputcSpeci~endpointerofline:): ret=geoint(ptend);//进^用户交互,获取输人点 if[rat=BREAK)//用户取消 return0:

DrawLine(ptstart,ptendJ: return1; }

可以看得出遣一处理H栏与传统的【fi『向过程的槔设汁的 操作方式完全样,这仃利]拽f¨控制程序fl{】过程晰给Hj Ru.【)函数,应用程序消息循环数据输人消包循环的宴现过 程:

//Run函数.除了负责运行消患循环之外 //时负责调用事件处理函数 intCMiniGisApp::Run《} (

ASSERT_VALIDcthis): far1::} {

还在事件到达

lflEventQuane.HasEventl1)

DealwithEvent(EventOuene.GetEventi}}: if(XieOuitAppI retumExi~lnstance【】: RunMessageLoop(I: )

ASSERTIFALSE)://不可到达I returnTRUE; J

//消息循环:仅改动程序退出处代码

voidCMiniGisApp::RunMessageLoapI】 {

BOOLbldle=TRUE: L0NG『IdleCaunt=0:

whileIbldle&&l::PeekMessege(8Lmj'nsgCur NULL,NULLNULL.PM-NOREMeVE}】 {

if(1Onldle{IldleCount++I】 bidle=FALSE;

秤i黧《i嚣l,-JIu..,'?lfII if【IDumDMessage¨) {

XieQuitApp=TRUE;//returnExltlnstancec】: }

ifcIsldleMessagec&ms口Cur}) {

b}dle=TRUE; IldleCount=0: }

1whilel::PeekMessagec8cmj'nsgCur.NULL,NULL. NULLPMOREMOVE}): )

//等待用户输人事件.需篓获取用户的交互输A时调用. //如上爵get_Point【】就要调用它Il intCMiniGisApp::WaitEvent() (

BOOLbldte;TRUE; LONGMleCaunt=O: forc::} (

whilecbldle&&:PeekMessage(&mJ呻sgCuri NULL.NULL.NULL.PMOREMeVEIl {

If【IOntdlecIldleCQunt++j】 bldle=FALSE;

lfIEventQueneHasEventc\"

returnEventQuene.event10】ExtraCode: } dol

if(EventOuene.HasEvantI】)

returnEventQuaneevent【01.ExtraCode; ¨PumpMessage(I) {

XieOuitAPP=TRUE; return0: )

iflIsldleMessegel&mjllsgCur)I {

bldle=TRUE; 『Id]eCount=0: l

}while(::PeekMessegel&mj'nsgCur.NULL. NULL.NULL.PMOREMeVE)l: ) )

intWaitMsg()

//后面经常耍调用,*方便起见编写了此全局函数i {

CMiniG!sApppApp;LCMiniGisAppjAfxGet~pp ASSERTlpApp):

人,下面的函数获取用户输人一点.按照同样的办法,当输人 一

个圆心点后.可以通过鼠标点击或者命令行输入来决定圆半 径从而域圆.我们也可以写出获取半径输人的函数get~ircler (int&radius) 五,小结

文中程序通过编写应用程序消息循环和数据箱人消息循 环,实现了绘图程序的多交互方式.程序运行后.在提示输入 数据的过程中可以通过命令行输人;在要求用户输人一个点时 即可以通过命令行输入窗口.电可以用鼠标点取一点作为输 人;在输入的过程中,用户可以黻时按ESC键取消,也以 再点菜单取消当前的命令并执行新的菜单消息响应函数,其效 果可以与AutoGAD相媲美.

本文通过数据输入消息循环实现的多交互绘图程序的原理 具有很强的通用性,用这种方式完全可以实现各种命令的多种 交互方式.可供读者在开发交互式CAD,GIS等的绘图摸块时 参考.本文源程序在VC6.0下经过l阃试通过 参考文献

DavidJ.Kraclinskt.VisualC++技术内幕,清华大学出 版社.I996

(作者:广东茂名学院计算机中心) (收稿日期:2005年12月9日) 上海市科教兴市推进办举行科教兴市 重大攻关项目普元EOS成果推广会

2005年l2月20目.上海市科教必市推进办公窒 为推进科技向更大株废和广度发展.隆重举行上海市科 教兴市重大科技攻关成果——普元EOS5.1项目汇报推 广会

普元公司承扭的\"普元面向构件的中间件EOS\"项 目自扁动实施以来,各项工作进展顺利.取得重大科技 突破,EOS产品已成功应用于电信,金融,电子政务, 舱源,制造等领域

曾元EOS找到软件产业链的切入点,与开发商形 成利益互补关系.EOS提供稳固应用软件架构.同时可 提高开发效率70%.降低维护成本50%,EOS构件复 用率60%以上.从而使企业的软件知识得到有效积 胄l.2005年度的计世资讯的调研.普元公司及产品的 品牌在用户和台作伙伴中均排名国内领先 上海市科教兴市推进办指出,自主创新,自主知识 产权是十一五规划的重重之重.重大成粜推广是科教必 市主战略的重要环节一方面普元要继续为电子政务和 企业信息化提供更好的服务,另一方面,及企业要 大力支持科教兴市重大科技攻关成皋.从而使得自主创 新的科研成果产生更大社会价值.

出席会议的有科教必市领导小组协谓办公室专职副 主任,推进办公赛副主任俞国生,科教兴市钡导小组推 进办公室专职副主任陈寅,上海市发展和改革委员会高 技术产业处撩子瑛等领导以及上海市部分委办局, 大型企业集团信息化负责人.

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务