博文

MFC 四大天王(2005-12-17 15:02:00)

摘要: 关於 MFC 这一主题,在「沧海书讯」版上曾经被讨论过的书籍有四本,正是我所列出的这四大天王。看来我心目中的好书颇能吻合市场的反应。 ---------------------------------------------------------------
我还记得,无责任书评是在四年前(1993)开春时和大家第一次见面。虽然不是每个月都出货,但断断续续总保持着讯息。在明确宣布的情况下这个专栏曾经停过两次,第一次停了叁个月,於 1994 年开春复工;第二次停了十五个月,於 1997 年开春的今天,重新与各位说哈罗。 休息整整一个年头又叁个月,写作上的疲倦固然是因素之一,另外也是因为这个专栏直接间接引起的让人意兴阑珊的俗人俗务。读者写信来说,『总把无责任书评当成休闲散文看。或许您可以考虑写些休闲小品,定会畅销』,是呀,我正构思把因这个专栏而获得的人生经验写成一本「现形记」。可是不知道手上「正当」工作什麽时间才能告一段落,写起我的小说。也不知道什麽样的出版社有兴趣侯捷写的小说。 倦勤与无奈过去了,满腔读书心得沛然欲发。所以,我又拿起笔「无责任」了。感觉有点陌生,但是回顾读者们这一年写来的上百封信,让我意气昂扬。这个月我谈的是 Visual C++ 与 MFC。此题目我已提过两次。一来它十分重要,演化的过程也十分快速而明显,二来这个领域又有一些重量级书籍出现,所以我必须再谈一次。 另外,我还是得再强调,侯捷的专长领域有限,离我火力太远的书我只能远观不敢近玩。这个专栏用在抛砖引玉,让谈书成为一种风气。Windows Developer's Journal(WDJ)的 Books in Brief 专栏原先也是主持人 Ron Burk 唱独角戏,後来(现在)就有了许多读者的互动。我也希望这样的事情在这里发生。 ●必也正名乎 常在 BBS 的程式设计相关版面上看到,许多人把 Visual C++ 和 C++混淆不清,另则是把 Visual C++ 和 MFC 混为一谈,实在有必要做个 清。C++ 是语言,Visual C++ 是产品。『我们学校开了一门 Visual C++ 的课程』这种说法就有点奇怪,实际意义是『我们学校开了一门 C++ 课程,以 Visual C++ 为软体开发环境』。『我会写 Visual C++ 程式』这种说法也很怪,因为Vis......

阅读全文(4121) | 评论:0

Visual C++ MFC 中常用宏的含义(2005-12-06 09:47:00)

摘要:AND_CATCHAND_CATCH
AND_CATCH(exception_class,exception _object_point_name)
说明:

定义一个代码块,它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型,然后使用AND_CATCH宏获得随后的异常处理代码可以访问异常对象(若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾。

注释:
AND_CATCH块被定义成为一个C++作用域(由花括号来描述)。若用户在此作用域定义变量,那么记住他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量。

ASSERT
ASSERT(booleanExpression)
说明:
计算变量的值。如果结构的值为0,那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0,那么什么也不做。 诊断消息的形式为: assertion failed in file in line 其中name是元文件名,num是源文件中运行失败的中断号。 在Release版中,ASSERT不计算表达式的值也就不中断程序。如果必须计算此表达式的值且不管环境如何那么用VERIFY代替ASSERT。
注释:
ASSERT只能在Debug版中用

ASSERT_VAILD
ASSERT_VAILD(pObject)
说明:
用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数(把它们作为自己的变量来传递)。在Release版中ASSERT_VALID什么也不做。在DEBUG版中,他检查指针,以不同于NULL的方式进行检查,并调用对象自己的AssertValid成员函数。如果这些检测中有任何一个失败的话,那么他会以与ASSERT相同的方法显示一个警告的消息。
注释:
此函数只在DEBUG版中有效。

BEGIN_MESSAGE_MAP
BEGIN_MES......

阅读全文(4416) | 评论:0

Visual C++6.0 API函数操作技巧集(2005-12-06 09:46:00)

摘要:我们在编制应用软件的过程中,常常需要对光标和鼠标操作,本人在文中介绍了Windows系统中有关实现对鼠标和光标进行操作的API函数,并给出了在Visual C6.0++中利用所介绍的API函数实现对鼠标和光标的操作的代码。

  一、隐藏和显示光标

  函数: int ShowCursor ( BOOL bShow );

  参数 bshow,为布尔型,bShow的值为False时隐藏光标,为True时显示光标;该函数的返回值为整型,为鼠标隐藏或显示的指数器;返回值大于等于0时显示光标,否则隐藏鼠标;如果安装了鼠标初值为0。

  实例:

  在基于对话框的应用程序中放置两个Button,名称分别为HideCursor和ShowCursor;再放置一个CStatic控件,名称为Label1,用于显示光标计数器。

  源程序为:

// 使光标计数器的值减一,如果小于零,隐藏光标
void CMyTestDlg::OnHideCursor()
{
int i;
i=ShowCursor(FALSE);
Cstring string;
string.Format(_T("%d" ),i);
Label1.SetWindowText(&string);
}
// 使光标计数器的值加一,如果大于等于零,显示光标
void CMyTestDlg::OnShowCursor()
{
int j;
j=ShowCursor(TRUE);
Cstring string;
string.Format(_T("%d" ),j);
Label1.SetWindowText(&string);
}
  运行程序,连续单击ShowCursor按钮,你会见到计数器从1(光标显示时初值为0)开始不断加1;再连续单击HideCursor按钮,又会见到计数器不断减1,当计数器为-1时开始隐藏光标。

  二、交换鼠标左右键和恢复

  函数:



BOOL SwapMouseButton ( BOOL fSwap );
 ......

阅读全文(3349) | 评论:0

VC入门的一条[转](2005-12-03 18:46:00)

摘要:

    首先声明,我可不是什么高手,也就是刚脱贫。因为运气很好,买到了几本好书,在学习过程中几乎没走什么弯路,没费什么劲就入门了,现在一般的小程序能搞定了。看到那些因为不知从何下手而苦苦挣扎的朋友,希望我的文章能给他们一些帮助。

    学编程急不得,上来就学VC肯定碰一头灰,说VC难就难在这点上了。如果硬上,意志坚强的话也许能挺过来,但也是会缺乏后劲,不得不回过头来补习基础知识。意志不坚强的话,很有可能就此放弃了,并留下一个VC难得不得了的印象。其实,只要踏踏实实一步一步来,VC也就是很简单点事。在这里我说一下,如果你还只是一个初中生,那么你就应当仔细考虑一下了。首先,限于你的知识和思维能力,学学C语言还应该没问题,但要学VC是要下相当大的功夫的。而且,你现在学到的东西将来一定会过时,所以不如把精力放在算法的研究上,毕竟这些东西永远都不会过时。
    
    我觉着如果走对路子,入门VC,一个暑假应该够用了。

    虽说学VC并不是传说的那么难,可不下些苦功夫是学不成的。在学VC前,你必须确定,你是因为热爱编程才学VC的,而不是出于炫耀或其他。否则,恐怕你坚持不到胜利的那一天。    

    对于首次接触编程的同学,我建议最好先学一下Quick BASIC(DOS里就有带,就是那个QBASIC.EXE),不用多学,知道什么是整型什么是浮点,以及DO...LOOP FOR...NEXT 等最基本的知识,能算个阶乘,求个积分就行了,关键要明白计算机是怎么执行命令的,对编程有个感性认识。如果你对自己有自信,也可以直接学C++,应该也不会多费太多事。不过我觉着因为有很多资料是FOR VB的,并且网页编程常用VB Script,以后你也很有可能要用到VB,所以了解一些BASIC对以后也是有帮助的。而且如果只是要算个小题用QB比VC、VB之类方便多了。(找个人教一两天应该就能搞定了吧)

  ......

阅读全文(3823) | 评论:1

MFC窗口位置管理详细分析及实例(2005-12-03 17:37:00)

摘要: 在一般用MFC编写的程序的窗口客户区中,可能有好几个子窗口(具有WM_CHILD风格的窗口)。上边是工具栏,中间是视图窗口,下边是状态栏。三个窗口在框架的客户区里和平共处,互不重叠。主框架窗口的尺寸改变了,别的子窗口都能及时调整自己的尺寸以便保持相互位置关系不变,例如状态条窗口总能保持在主框架客户区底部,并且其宽度总能和主框架客户区宽度一致。工具栏窗口总能停靠在主框架的某一边不变,其宽度或高度总能和主框架客户区的宽度或高度一致,视图窗口总能填满主框架客户区的剩余空间。

假如我们自己从CWnd类派生一个窗口类并生成一个窗口,在它的客户区里要生成若干个子窗口,我们想使这些子窗口排列得规规矩矩,互不重叠,当父窗口的尺寸变了时各个子窗口能适时调整自己的尺寸和位置,使各个子窗口之间的位置大小比例关系不变。当移动其中一个或几个子窗口时,别的子窗口能及时为这个移动了的子窗口让位。当然我们可以利用api函数里管理窗口的函数来编写自己的管理子窗口的方法。可是如果在父窗口的客户区里有了工具栏,状态条等等子窗口时,你自己加进来的子窗口还能和这些mfc提供的子窗口融洽相处吗?你如何保证你的子窗口不会覆盖了能够四处停靠的工具栏?当工具栏和状态条消失后你的子窗口如何才能知道,以便及时调整自己的大小从而覆盖工具栏和状态条腾出的空间?基于文档视图构架的窗口的客户区内还有个视图,你自己硬加上的子窗口能不和视图窗口争地盘吗?

所以必须了解mfc的窗口管理它的客户区的方法。其实,mfc的窗口管理它的客户区的方法是非常简单的:父窗口调用一个函数,子窗口响应一个消息,就这么多。

CWnd::RepositionBars函数和WM_SIZEPARENT消息

先简述一下mfc的窗口为子窗口分配客户区空间的过程:这一过程是父窗口与子窗口共同协调完成的。父窗口先提供它的客户区内的一块区域,叫做起始可用区域。然后调用一个函数,在这个函数里,父窗口把这片区域通过一个消息提交给它的第一个子窗口,该子窗口决定自己要占用多大一块,然后在可用区域里把它将占据的部分划出去,这样可用区域就被切去了一块。父窗口再把这块剩下的可用区域通过同样的消息提交给第二个子窗口,第二个子窗口再根据自己的需要切掉一块。如此这般,每个子窗口都切去自己所需的一块。最后剩下的可用区域就给最后......

阅读全文(3685) | 评论:0

C++基础:常量成员函数特殊说明(2005-11-23 23:38:00)

摘要:
 1. 传指针时,我们可以通过指针来修改它在外部所指向的内容。但如果要修改外部指针所指向的对象是不可能的。例如传递外部指针到函数内来分配空间,必须传递指针的指针或指针的引用。   2. char carry[10] = {0}; 编译器会将其后所有的东西都置0;   3. 函数返回值为const时,返回的东西付给一个类型相同的标示后其不能为左值;   4. const int *i; int const *i; int * const i; 前两个功能相同,说明I所指向的内容不变;最后一个说明指针指向的地址不变,但内容可变。   5. 类中的const成员函数。定义为在原型后加const。常量函数不能修改类中的任何属性。但有两种方法可以修改。   a) {(myclass *)this->member1 = values;}   b) 将一个成员定义成mutable即可被常量函数修改。   6. 类中的常量const 类型的,不能在类中被用来定义数组。而enum {ONE=100; TWO=2};定义的ONE、TWO却可以。通常的enum定义的置分配问题:enum A{ L=9, Z};此时Z的值为10。   7. 用const定义的int可用来开辟数组,但const定义的常量数组中的元素,不能用来定义数组。   8. 用sizeof计算变量的空间,如果是数组,按实际空间返回;常量字符串(实际上是在静态内存区开辟的变量)sizeof返回比实际长度加一。如果是指针则不考虑它指向的空间大小,仅仅返回指针类型的大小。如果用sizeof计算函数的行参,即使是属组也仅仅返回一个相关类型指针的大小。   9. 形如int iarray[] = {12, 124, 433};编译器会自动给iarray分配3个元素的长度。元素长度的个数计算公式为sizeof(iarray) / sizeof(*iarray)。   10. 拷贝构造函数:当行参和实参结合时,如果是复杂对象的传值类型,则调用拷贝构造函数生成一个临时对象作为实参,退出函数时,临时对象被调用析构函数释放。当返回值是复杂对象是,也是调用拷贝构造函数来赋值。这就出现构造函数和析构函数被调用次数不相等的情况。拷贝构造函数的原型为A(A&),我们可在类中重载。(缺省的拷贝构造......

阅读全文(3413) | 评论:0

C常规错误(2005-11-23 23:37:00)

摘要:C语言的最大特点是:功能强,使用方便灵活.C编译的程序对语法 检查并不象其它高级语言那么严格,这就给编程人员留下"灵活的 余地",但还是由于这个灵活给程序的调试带来了许多不便,尤其 对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的 错误.看着有错的程序,不知该如何改起,本人通过对C的学习, 积累了一些C编程时常犯的错误,写给各位学员以供参考.      1.书写标识符时,忽略了大小写字母的区别. main()
{
 int a=5;
 printf("%d",A);
}    编译程序把a和A认为是两个不同的变量名,而显示出错信息. C认为大写字母和小写字母是两个不同的字符.习惯上,符号常量 名用大写,变量名用小写表示,以增加可读性.   2.忽略了变量的类型,进行了不合法的运算. main()
{
 float a,b;
 printf("%d",a%b);
}    %是求余运算,得到a/b的整余数.整型变量a和b可以进行求余 运算,而实型变量则不允许进行"求余"运算.   3.将字符常量与字符串常量混淆. char c;
c="a";    在这里就混淆了字符常量与字符串常量,字符常量是由一对单 引号括起来的单个字符,字符串常量是一对双引号括起来的字符序 列.C规定以"\"作字符串结束标志,它是由系统自动加上的,所 以字符串"a"实际上包含两个字符:'a'和'\',而把它赋给一 个字符变量是不行的.   4.忽略了"="与"=="的区别.   在许多高级语言中,用"="符号作为关系运算符"等于". 如在BASIC程序中可以写 if (a=3) then …    但C语言中,"="是赋值运算符,"=="是关系运算符.如: if (a==3) a=b;    前者是进行比较,a是否和3相等,后者表示如果a和3相等,把 b值赋给a.由于习惯问题,初学者往往会犯这......

阅读全文(3507) | 评论:0

C 语言图形函数(2005-11-15 10:38:00)

摘要:
C语言图形函数
图形函数
所有图形函数的原型均在graphics. h
中, 本节主要介绍图形模式的初始化、独立图形程序的建立、基本图形功能、图
形窗口以及图形模式下的文本输出等函数。另外, 使用图形函数时要确保有显示
器图形驱动程序*BGI, 同时将集成开发环境Options/Linker中的Graphics lib选
为on, 只有这样才能保证正确使用图形函数。
1. 图形模式的初始化
不同的显示器适配器有不同的图形分辨率。即是同一显示器适配器, 在不同
模式下也有不同分辨率。因此, 在屏幕作图之前, 必须根据显示器适配器种类将
显示器设置成为某种图形模式, 在未设置图形模式之前, 微机系统默认屏幕为文
本模式(80列, 25行字符模式), 此时所有图形函数均不能工作。设置屏幕为图形
模式, 可用下列图形初始化函数:
void far initgraph(int far *gdriver, int far *gmode, char *path);
其中gdriver和gmode分别表示图形驱动器和模式, path是指图形驱动程序所
在的目录路径。有关图形驱动器、图形模式的符号常数及对应的分辨率见表2。
图形驱动程序由Turbo C出版商提供, 文件扩展名为.BGI。 根据不同的图形
适配器有不同的图形驱动程序。例如对于EGA、 VGA 图形适配器就调用驱动程序
EGAVGA.BGI。
表2. 图形驱动器、模式的符号常数及数值
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
图形驱动器(gdriver) 图形模式(gmode)
─────────── ─────────── 色调 分辨率
符号常数 数值 符号常数 数值
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGA 1  CGAC0 0 C0 320*200
CGAC1 1 C1 320*200
CGAC2 2 C2 320*200
CGAC3 3 C3 320*200
CGAHI 4 2色 640*200
────......

阅读全文(11375) | 评论:1

TC 字符屏幕函数详解(2005-11-15 10:37:00)

摘要:
     Turbo C2.0的字符屏幕函数主要包括文本窗口大小的设定、窗口颜色的设置、
窗口文本的清除和输入输出等函数。     1.文本窗口的定义
    Turbo C2.0默认定义的文本窗口为整个屏幕, 共有80列(或40列)25行的文本
单元, 每个单元包括一个字符和一个属性, 字符即ASCII 码字符, 属性规定该字
符的颜色和强度。
    Turbo C2.0可以定义屏幕上的一个矩形域作为窗口, 使用window()函数定义。
窗口定义之后, 用有关窗口的输入输出函数就可以只在此窗口内进行操作而不超
出窗口的边界。
    window()函数的调用格式为:
     void window(int left, int top, int right, int bottom);
    该函数的原型在conio.h 中 (关于文本窗口的所有函数其头文件均为conio.h,
后面不再说明)。 函数中形式参数(int left,  int top)是窗口左上角的坐标,
(int right, int  bottom)是窗口的右下角坐标, 其中(left,  top)和(right,
bottom) 是相对于整个屏幕而言的。 Turbo C 2.0规定整个屏幕的左上角坐标为
(1, 1), 右下角坐标为(80, 25)。并规定沿水平方向为 X轴, 方向朝右; 沿垂直
方向为 Y轴, 方向朝下。若window()函数中的坐标超过了屏幕坐标的界限, 则窗
口的定义就失去了意义, 也就是说定义将不起作用, 但程序编译链接时并不出错。
    另外, 一个屏幕可以定义多个窗口, 但现行窗口只能有一个(因为DOS为单任
......

阅读全文(4863) | 评论:0

面向对象基础(OO)(2005-11-15 10:35:00)

摘要:
面向对象的软件开发对于90年代,就像是结构化的软件开发对于70年代那样让人着迷,而且 OO 的发展势头还在日益加速。OO 最初被多数人看作只是一种不切实际的方法和满足一时好奇心的研究,而现在已经得到了人们近乎狂热的欢迎。许多编程语言都推出了支持面向对象的新版本。大量的面向对象的开发方法被提出来。 一、软件工程: 需求分析 --> 总体设计 --> 详细设计 --> 编码 --> 测试
 (OOA)      (OOD)      (OOP)  (Coding) (OOT)
   ↑____________________________________________|   1、过程语言(高级语言):     - 过程或函数块、函数库,数据公开暴露给算法,使得修改函数体不影响程序代码几乎不可能(数据与函数绞在一起)。     - 结构化编程:不是改变使用的语言,提供了一个新的处理方法,如设计框图、流程图,以阐述各函数之间的相互作用关系和数据如何流过该程序,不利于独立开发,且饱受开发循环的折磨。     - 算法总是离不开数据结构,只能使用特定的数据结构。由于数据结构和数据对所有函数都可见,很难把握数据的修改出自哪个函数,这些数据的安全性得不到保障。     - 自上而下地解决规模较小的问题:程序规模小,并不一定效率高。一些小程序,可以通过结构化的程序设计技巧和优化,小幅度地提高运行速度,但是往往都是以牺牲可读性为代价的,给维护造成了大量的困难。一旦程序规模扩大,程序的可读性和可维护性,甚至连结构化的程序设计都感到力不从心。   2、1967年,Simula 67......

阅读全文(4272) | 评论:0