首页 VC++入门教程

VC++入门教程

举报
开通vip

VC++入门教程VC++入门教程 查看完整版本: 转 入门教程(windows 入门程序详解 --] 入门程序详解) 查看完整版本 [-- [转]VC++入门教程 入门教程 交流:::: -> [转]VC++入门教程 ?广海社区? - ghoffice.com -> ::::C++交流 广海社区? 交流 转 入门教程 (windows 入门程序详解 [打印本页 入门程序详解) 打印本页] 打印本页 登录 -> 注册 -> 回复主题 -> 发表主题 菜鸟学挂 2010-01-21 11:27 ...

VC++入门教程
VC++入门教程 查看完整版本: 转 入门教程(windows 入门程序详解 --] 入门程序详解) 查看完整版本 [-- [转]VC++入门教程 入门教程 交流:::: -> [转]VC++入门教程 ?广海社区? - ghoffice.com -> ::::C++交流 广海社区? 交流 转 入门教程 (windows 入门程序详解 [打印本页 入门程序详解) 打印本页] 打印本页 登录 -> 注册 -> 回复主 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 -> 发表主题 菜鸟学挂 2010-01-21 11:27 [转]VC++入门教程 转 入门教程(windows 入门程序详解 入门程序详解) 入门教程 想做个 VC 入门教程,呵呵~不敢称做教程.不过先借来用用吧. 很多内容都是己学习时积累下来的资料整理.把它们凑起来,供大家学习.其实也是督促我自自 己.好了 大家有什么意见可以在这里提哦. <<WINDOWS SDK 路报>>.上面说的已经很详细了.想学好 VC.了解他的内幕是至关重要的.废话少说,大家看下 面的内容.初学者可能不容易看懂,有问题在下面跟贴. ---- 不是我写的. 第一讲:预备知识与概念介绍 注:我写这个专题目的是为 VC 初学者提供一个思路,我本人很菜,但我认为对于 VC 初学者来讲,可能有点帮助, 当然,对于 WinSDK 编程,我也是刚刚接触。如果你对 WinSDK 编程较熟,请与我联系,咱们共同来把这个专题 做好,如果你发现了什么错误,也麻烦你给我留言指正。我写的内容也基本上是我自己的一些理解,错误是肯定有 的,如果你发现我的理解偏差很大的话,麻烦你提醒一下。---小朱! 什么是 WinSDK: 大致说来 windows 编程有两种方法: 1.windwos c 方式(SDK), 2.c++方式:即对 SDK 函数进行包装,如 VC 的 MFC,BCB 的 OWL 等,如果要深入 下去,还是要熟悉 SDK。 两种方法有哪些区别呢:SDK 编程就是直接调用 windows 的 API 进行编程,但是有上千个 API 组成(win95 的 API 有两千多个),这种数目太大了,对于编程显然不利。而 MFC 把这些 API 封闭起来,共有一百多个类组成。一 般只需 20 多个 windows 类和另外 20 多个通用的非 windows 类就可"干活"了,这一改变无疑是有很大好处的。 尽管 MFC 如此方便,但是要学 VC,直接去学 MFC 却是不明智的选择。只有在熟悉了 MFC 的运行机制的情况下, 才有可能深入下去。 那些如多少天精通什么什么的 关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf 籍其实讲的全是些如怎么 使用 VC 这种工具的话题,学来学去学 会了怎么会使用 VC 这种工具, 而不能深入 MFC 编程。 VB 这类工具就更令人感觉到太闷了, 象 不过各有各的好处。 MFC 虽然提高了程序员编程的效率,但是也失去了 SDK 编程的灵活性.....不好意思,跑题了.... 本专题假定: C 语言是 windows 的源语言,用 C 进行 SDK 编程是最合适的,你应该至少学过 C 语言,知道 C 语言的各种语法 等,当我说到指针等类似概念的时 候,你不至于茫然就行了。 你还应该安装了 Visual C++6.0,低版本的就不用用了吧,D 版的才几块钱吗, 推荐与参考资料: 1.Petzold 的[programming windows by petzold],这是我看过的一本书(电子书),不过是 E 文的,我只看了 一半,"下载空间"一栏能供了该电子书。中文版的是[Windows 程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 ](包括上,下卷),Charles Petzold 著,北 京博彦发展有限公司译,北京大学出版社出版,本书唯一的缺点就是太贵,价格是 160 元。一些朋友让我多推荐一 些这方面的书, 我也没办法, 一是这类书目前本就很少, 二是如果你非要买的话, 肯定要买这本书了, 可是经典呢~ ~ 2.还有一本老书值得一提,可能市面上已经买不到了,书名[Windows 编程],刘振安著,人民邮电出版社出版发 行。一个朋友曾借给我看了几天我又还了,很容易读懂的,不过一看日期,95 年出版,得!没希望了。我们学校图 书馆好像也有几本,不过好像都很烂。 3.VC 的在线帮助 MSDN,有关 SDK 的资料在"Platform SDK"一栏中。 下面再加深几点概念: 什么是 API: 什么是 API,有必要再谈一下,特别对于从 TC 过来的朋友和初学编程的朋友。API,全称 application program interface,意思是应用程序编程接口(说起 API 并不仅仅指 windows 而言,windows 支持的 API 叫 winapi)。 winapi 就是应用程序和 windows 之间通讯的一个编程界面。windows 提供了上千个 API 函数,以方便程序员来 编写应用程序。做数据库管理系统是很少和 API 打交道的,我以前学 PB,看的十几本书都没有专门的章节来介绍 API 的。只有到网上看那些 PB 技巧之类的文章才谈及 API,不过还要加入一大堆声明之类的东东。好像 VB 也是 这样。总之,进行系统编程,API 是必不可少的。API 是每个 VC 高手的必过的一关。 什么是 WinSDK 编程: WinSDK 程序设计就是 API 方式的 windows 程序设计。SDK,全称 Software Developers Kit,意思是软件开发 工具箱。它是在 windows 程序设计早期,程序员进行 windows 程序设计所必须购买的一个软件包(不知道那时候 有没有 D 版的)。我两个月前见 SDK 还不知所云。开始进行 WinSDK 编程用 C 语言最好,可以撇开 C++的特性 专心熟悉一下 Win32 编程的思路以及了解 windows 的消息运行机制。等把这些有所了解后,慢慢转向 C++和 MFC 编程。不过我的观点是 WinSDK 编程永远要慢慢进行下去,直接接触底层代码对 MFC 源码的理解是有很大 好处的。上周开始用 MFC 时,按 F11 进行单步跟踪,一开始见到"_tWinMain"这样古怪的东东也没有感觉到太大 的迷惑,不就是相当于 SDK 编程中的 WinMain 函数吗, 什么是 MFC: MFC,全称 Microsoft Foundation Classes,伪软把 WinAPI 进行封装的类 库。它是一个类的集合,通过覆盖 WinAPI,为编程提供了一个面向对象的界面。它使 windows 程序员能够利用 C++面象对象的特性进行编程,类 似 BCB 的 OWL,Delphi 的 VCL 组件。它把那些进行 SDK 编程时最繁琐的部分提供给程序员,使之专注于功能 的实现。你不妨把它想象成类似 TC 提供的函数库吧。用 Visual C++这种开发工具编程时,可以用 MFC,也可以 不用,但 MFC 是 VC 的精华所在,从某种意义上来说,不会 MFC 就是不会使用 VC。研究 MFC 源代码是件既快乐 又痛苦的事情,不过,阵痛之后,嘻嘻,...... 怎么进行 WinSDK 编程: Visual C++6.0:File-->new-->Projects-->Win32 Application(project name)-->...... 我们既然用 C 语言进行,就选第一项"An empty project"...... ......好累,这篇就写这么多吧,但愿对你有帮助,也建议多给我提意见,你的反馈是我最大的动力渊源...... 讲的不错吧~,还是比较好懂的.下面接着看. 要自己动手. 第二讲:WinMain 与两只小板凳的故事 注:呵呵,近两天收到不少网友来信,要求我继续写下去,说实在的,写这东西费时费力。不过一旦想起这些对大 家或许有些帮助时,无形的压力就来了。我所写的,仅仅是我编程中的感想,如果你有何感想,希望给我留言或到 "C 程序员论剑台"交流,如果你有好的建议,欢迎提出;如果你有好的对 VC 初学者有利的作品或文章,也欢迎给 本站介绍,我将大力为你推广。---小朱 第一只小板凳: 打开"an empty project"后,在 VC 的 IDE 中,打开文本编辑器。输入以下内容: ,i nclude "windows.h" int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MessageBox (NULL, TEXT ("你好,欢迎来到 VC 之路"), TEXT ("欢迎"), 0) ; return 0 ; } 把它保存成以".c"为扩展名的文件,并加入空项目中。编译...... 看到了吧, 这就我们的第一只小板凳。 它就类似于 TC 下的"hello world"吧~ 虽然什么功能也没实现, 但它比"hello world"强多了,因为它向我们展示了一个小窗口。 支解第一只小板凳: 像 TC 一样,它包含一个头文件"windows.h",这是一个最基本的头 文件,它包含其它的 windows 头文件.在你的 "X:\Program Files\Microsoft Visual Studio\VC98\Include"目录下,打开 windows.h 这个文件,你就知道 它 包含什么东东了。 像 dos 下的 C 编程的 main()一样,windows 下的入口是 WinMain()函数。 把光标放在 WinMain()上,按 F1 键。启动 MSDN,如果你没安装的话,一定要安装一下,MSDN 是最好的学习 VC 的资料,当然,对于我们入门者,有一本书从头到尾学一下最好。 第一个参数:应用程序的当前实例句柄。 第二个参数:应用程序的前一个实例句柄,别管它,对于 Win 32 位而言,它一般是 NULL. 第三个参数:指向任何传给程序的命令行参数。PSTR 代表"指向字符串的指针"。 第四个参数:它告诉应用程序如何初始化窗口,如最大化,最小化等状态。 WinMain()所起的作用:初始化,展示,销毁应用程序等。 MessageBox(),如果大家在 windows 下编程,这是一个很常用的 API,不用我费话了吧~ 几个要点: 1.句柄(handle):在 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 C 库中句柄用来对文件输入输出。如下面的代码: int handle; handle=open("filename","r") if(handle) { read(handle,block,bytesToread); } close(handle); 在文件被成功打开后,open()返回一个句柄,在 read()中使用这个句柄来阅读 这个文件。句柄不是指针。程序不 能直接使用句柄来阅读文件中的信息。如果不能把它传送给输入输出函数调用的话,句柄就没有用了。句柄不返回 零。句柄命名以 h 开始。这是匈牙利表示法的规定。 2.匈牙利表示法: 初开始看到这个程序时,你一定感觉到很怪,我当时就是这样的。不知道那些字母怎么回事。因为所有的命名采用 了,匈牙利表示法。如消息的前缀使用 msg.句柄使用 h.函数使用 fn 等。多说了,习惯了就好了. MSDN: 3.有效使用 想成为 VC 高手,还要强迫自己习惯于使用 MSDN,看得多了,不怕看不懂,如果仅仅知道功能不知道具体的函数, 可用类似的 英语 关于好奇心的名言警句英语高中英语词汇下载高中英语词汇 下载英语衡水体下载小学英语关于形容词和副词的题 单词去搜索。我平时就用金山词霸一点点的啃。唉,说起来惭愧,本人英语四级没过,这学期连报 考都没有。以后努力了,总感觉到大学的教育很有问题,好像每个人都在为四六级而奔忙。 呵呵,说了这些,真怀疑对你真的有用。有不对的地方,请指出。希望大家共同进步,把 VC 活吃了....... 第二只小板凳 >new-->progects-->win32 application,并在 project name 打开 VC,file-- 中输入 hello.顺路走下来,选择 第二项。在编辑器中输入以下程序覆盖向导产生的代码: ,i nclude "stdafx.h" //注意,这个向导产生的头文件不能去掉 ,i nclude <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; WNDCLASS wc ; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = WndProc ; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ; wc.hInstance = hInstance ; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wc.hCursor = LoadCursor (NULL, IDC_ARROW) ; wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wc.lpszMenuName = NULL ; wc.lpszClassName = szAppName ; if (!RegisterClass (&wc)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, // window class name TEXT (" 欢迎你的到来!"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; ,欢迎你来到 VC 之路!"), -1, &rect, DrawText (hdc, TEXT ("你好 DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } 按前两节讲的方法编译后,就见到我们的第二只小板凳了,可别小看它,对它的全面理解对于学习 MFC 的封装是 有很大好处的。windows 的消息循环机制等都可通过这个东东解释出来。好了,咱们年后继续努力吧,应该应付 一下该死的考试了...... windows 消息机制,我们要用四讲来讨论消息机制. 第一讲: Dos 的过程驱动与 Windows 的事件驱动 在讲本程序的消息循环之前,我想先谈一下 Dos 与 Windows 驱动机制的区别: DOS 程序主要使用顺序的,过程驱动的程序设计方法。顺序的,过程驱动的程序有一个明显的开始,明显的过程 及一个明显的结束,因此程序能直接控制程序事件或过程的顺序。虽然在顺序的过程驱动的程序中也有很多处理异 常的方法,但这样的异常处理也仍然是顺序的,过程驱动的结构。 而 Windows 的驱动方式是事件驱动,就是不由事件的顺序来控制,而是由事件的发生来控制,所有的事件是无序 的,所为一个程序员,在你编写程序时,你并不知道用户先按哪个按纽,也不知道程序先触发哪个消息。你的任务 就是对正在开发的应用程序要发出或要接收的消息进行排序和管理。事件驱动程序设计是密切围绕消息的产生与处 理而展开的,一条消息是关于发生的事件的消息。 Windows 编程的特点: C 语言编程至少有一个主程序,其名字是 main()。Windows 程序则至少两个主程序,一个是 WinMain(), int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ); 另一个是窗口过程函数 WndProc,它的函数原型为: long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam); Windows 应用程序的编程就围绕这 两个部份进行的。其中 WinMain 函数为应用程序的入口点,它的名字一定要 是 WinMain。 在 Windows 中,应用程序通过要求 Windows 完成指定操作,而承担这项通信任务的 API 函数就是 Windows 的 相应窗口函数 WndProc。在 dos 里,程序能直接控制事件的发生顺序,结果等。而在 Windows 里,应用程序不 直接调用任何窗口函数,而是等待 Windows 调用窗口函数,请求完成任务或返回信息。为保证 Windows 调用这 个窗口函数,这个函数必须先向 Windows 登记,然后在 Windows 实施相应操作时回调,所以窗口函数又称为回 调函数。WndProc 是一个主回调函数,Windows 至少有一个回调函数。 回调函数 WndProc 在哪里定义的呢,请看这个语句:wc.lpfnWndProc = WndProc ;将在第七讲里详谈. 实例:在 Windows 中,能多次同时运行同一个应用程序,即运行多个副本,每个副本叫做一个“实例”。 现在让我们把这个程序层层剥解开来,我把自己的理解慢慢地展示给你: 我把这个程序支解为四块一)建立,注册窗口类.(二)创建窗口.(三)显示和更新窗口.(四)创建消息循环.(五)终止应用 程序.(六)窗口过程.(七)处理消息. (一)注册窗口类: (1)建立窗口类 WinMain()是程序的入口,它相当于一个中介人的角色,把应用程序(指小窗口)介绍给 windows.首要的一步是登记 应用程序的窗口类. 窗口种类是定义窗口属性的模板,这些属性包括窗口式样,鼠标形状,菜单等等,窗口种类也指定处理该类中所有窗口 消息的窗口函数.只有先建立窗口种类,才能根据窗口种类来创建 Windows 应用程序的一个或多个窗口.创建窗口 时,还可以指定窗口独有的附加特性.窗口种类简称窗口类,窗口类不能重名.在建立窗口类后,必须向 Windows 登 记. 建立窗口类就是用 WNDCLASS 结构定义一个结构变量,在这个程序中就是指 WNDCLASS wc ;然后用自己设计 的窗口属性的信息填充结构变量 wc 的域. 要 WinMain 登记窗口类,首先要填写一个 WNDCLASS 结构,其定义如下所示: typedef struct _WNDCLASSA { UINT style ; //窗口类风格 WNDPROC lpfnWndProc ; //指向窗口过程函数的指针 int cbClsExtra ; //窗口类附加数据 int cbWndExtra ; //窗口附加数据 HINSTANCE hInstance ; //拥有窗口类的实例句柄 HICON hIcon ; //最小窗口图标 HCURSOR hCursor ; //窗口内使用的光标 HBRUSH hbrBackground ; //用来着色窗口背景的刷子 LPCSTR lpszMenuName ; //指向菜单资源名的指针 LPCSTR lpszClassName ; // 指向窗口类名的指针 } 在 VC6.0 里面,把光标定位在 WNDCLASS 上,按 F1,即可启动 MSDN,在 MSDN 里你可看到这个结构原形. 在下节讲解这些参数在本程序中的具体用法. (2)注册窗口类 style 控制窗口的某些重要特性 (1)第一个参数:成员 ,在 WINDOWS.H 中定义了一些前缀为 CS 的常量,在程序 中可组合使用这些常量.也可把 sytle 设为 0.本程序中为 wc.style = CS_HREDRAW | CS_VREDRAW,它表示 当窗口的纵横坐标发生变化时要重画整个窗口。你看:无论你怎样拉动窗口的大小,那行字都会停留在窗口的正中 部,而假如把这个参数设为 0 的话,当改动窗口的大小时,那行字则不一定处于中部了。 (2)第二个参数:lpfnWndProc 包括一个指向该窗口类的消息处理函数的指针,此函数称为窗口过程函数。它将接 收 Windows 发送给窗口的消息,并执行相应的任务。其原型为: long FAR PASCAL WndProc(HWND ,unsigned,WORD,LONG);并且必须在模快定义中回调它。WndProc 是 一个回调函数(见第五节),如果暂时无法理解这个模糊的概念意味着什么,可先放过,等到讲消息循环时再详谈。 (3)第三,四个参数:cbWndExtra 域指定用本窗口类建立的所有窗口结构分配的额外字节数。当有两个以上的窗口 属于同一窗口类时,如果想将不同的数据和每个窗口分别相对应。则使用该域很有用。这般来讲,你只要把它们设 为 0 就行了,不必过多考虑。 (4)第五个参数:hInstance 域标识应用程序的实例 hInstance,当然,实例名是可以改变的。wc.hInstance = hInstance ;这一成员可使 Windows 连接到正确的程序。 (5)第六个参数:成员 hIcon 被设置成应用程序所使用图标的句柄, 图标是将应用程序最小化时出现在任务栏里的的 图标,用以表示程序仍驻留在内存中。Windows 提供了一些默认图标,我们也可定义自己的图标,VC 里面专有一 个制作图标的工具。 (6)第七个参数: hCursor 域定义该窗口产生的光标形状。LoadCursor 可返回固有光标句柄或者应用程序定义的 光标句柄。IDC_ARROW 表示箭头光标. (7)第八个参数:wc.hbrBackground 域决定 Windows 用于着色窗口背景的刷子颜色,函数 GetStockObject 返 回窗口的颜色,本程序中返回的是白色,你也可以把它改变为红色等其他颜色.试试看 (8)第九个参数:lpszMenuName 用来指定菜单名,本程序中没有定义菜单,所以为 NULL。 (9)第十个参数:lpszClassName 指定了本窗口的类名。 当对 WNDCLASS 结构域一一赋值后,就可注册窗口类了,在创建窗口之前, API 函数是 RegisterClass,注册失败是必须要注册窗口类的,注册窗口类 用的 的话,就会出现一个对话框如程序所示,函数 RegisterClass 返回 0 值, 也只能返回 0 值,因为注册不成功,程序已经不能再进行下去了。 在本程序中注册窗口类如下: if (!RegisterClass (&wc)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName,MB_ICONERROR) ; return 0 ; } 第二讲 消息机制 (二)创建窗口 注册窗口类后,就可以创建窗口了,本 程序中创建窗口的有关语句如下: hwnd = CreateWindow (szAppName, // window class name TEXT ("欢迎你的到来!"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters 参数 1:登记的窗口类名,这个类名刚才咱们在注册窗口时已经定义过了。 参数 2:用来表明窗口的标题。 参数 3: 用来表明窗口的风格,如有无最大化,最小化按纽啊什么的。 参数 4,5: 用来表明程序运行后窗口在屏幕中的坐标值。 参数 6,7: 用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度。 。 参数 8: 在创建窗口时可以指定其父窗口,这里没有父窗口则参数值为 0 参数 9: 用以指明窗口的菜单,菜单以后会讲,这里暂时为 0。 最后一个参数是附加数据,一般都是 0。 CreateWindow()的返回值是已经创建的窗口的句柄,应用程序使用这个句柄来引用该窗口。如果返回值为 0,就 应该终止该程序,因为可能某个地方出错了。如果一个程序创建了多个窗口,则每个窗口都有各自不同的句柄. )显示和更新窗口 (三 API 函数 CreateWindow 创建完窗口后,要想把它显示出现,还必须调用另一 ShowWindows.形式 为: 个 API 函数 ShowWindow (hwnd, iCmdShow); 其第一个参数是窗口句柄,告诉 ShowWindow()显示哪一个窗口,而第二个参数则告诉它如何显示这个窗口:最 小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),还是最大化(SW_SHOWMAXIMIZED)。WinMain 在创 建完窗口后就调用 ShowWindow 函数,并把 iCmdShow 参数传送给这个窗口。你可把 iCmdShow 改变为这些 参数试试。 WinMain()调用完 ShowWindow 后,还需要调用函数 UpdateWindow,最终把窗口显示了出来。调用函数 UpdateWindow 将产生一个 WM_PAINT 消息,这个消息将使窗口重画,即使窗口得到更新. (四)创建消息循环 主窗口显示出来了,WinMain 就开始处理消息了,怎么做的呢, Windows 为每个正在运行的应用程序都保持一个消息队列。当你按下鼠标或者键盘时,Windows 并不是把这个 输入事件直接送给应用程序,而是将输入的事件先翻译成一个消息,然后把这个消息放入到这个应用程序的消息队 列中去。应用程序又是怎么来接收这个消息呢,这就讲讲消息循环了。 应用程序的 WinMain 函数通过执行一段代码从她的队列中来检索 Windows 送往她的消息。然后 WinMain 就把 这些消息分配给相应的窗口函数以便处理 它们,这段代码是一段循环代码,故称为"消息循环"。这段循环代码是什 么呢,好,往下看: 在 咱们的第二只小板凳中,这段代码就是: ...... MSG msg; //定义消息名 while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; //翻译消息 DispatchMessage (&msg) ; //撤去消息 } return msg.wParam ; MSG 结构在头文件中定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; MSG 数据成员意义如下: 参数 1:hwnd 是消息要发送到的那个窗口的句柄,这个窗口就是咱们用 CreateWindows 函数创建的那一个。如 果是在一个有多个窗口的应用程序中,用这个参数就可决定让哪个窗口接收消息。 参数 2:message 是一个数字,它唯一标识了一种消息类型。每种消息类型都在 Windows 文件中定义了,这些常 量都以 WM_开始后面带一些描述了消息特性的名称。比如说当应用程序退出时,Windows 就向应用程序发送一 条 WM_QUIT 消息。 参数 3:一个 32 位的消息参数,这个值的确切意义取决于消息本身。 参数 4:同上。 参数 5:消息放入消息队列中的时间,在这个域中写入的并不是日期,而是从 Windows 启动后所测量的时间值。 Windows 用这个域来使用消息保持正确的顺序。 参数 6:消息放入消息队列时的鼠标坐标. 消息循环以 GetMessage 调用开始,它从消息队列中取出一个消息: GetMessage(&msg,NULL,0,0), 第一个参数是要接收消息的 MSG 结构的地址, 第二个参数表示窗口句柄,NULL 则表示要获取该应用程序创建的所有窗口的消息;第三,四参数指定消息范围。后面三个参数被设置为默认值,这 就是说你打算接收发送到属于这个应用程序的任何一个窗口的所有消息。在接收到除 WM_QUIT 之外的任何一个 消息后,GetMessage()都返回 TRUE。如果 GetMessage 收到一个 WM_QUIT 消息,则返回 FALSE,如收到其 他消息,则返回 TRUE。因此,在接收到 WM_QUIT 之前,带有 GetMessage()的消息循环可以一直循环下去。 只有当收到的消息是 WM_QUIT 时, GetMessage 才返回 FALSE, 结束消息循环, 从而终止应用程序。 均为 NULL 时就表示获取所有消息。 消息用 GetMessage 读入后(注意这个消息可不是 WM_QUIT 消息),它首先要经过函数 TranslateMessage()进 行翻译,这个函数会转换成一些键盘消息,它检索匹配的 WM_KEYDOWN 和 WM_KEYUP 消息,并为窗口产生 相应的 ASCII 字符消息(WM_CHAR),它包含指定键的 ANSI 字符.但对大多数消息来说它并不起什么作用, 所以现 在没有必要考虑它。 下一个函数调用 DispatchMessage()要求 Windows 将消息传送给在 MSG 结构中为窗口所指定的窗口过程。我 们在讲到登记窗口类时曾提到过,登记窗口类时,我们曾指定 Windows 把函数 WindosProc 作为咱们这个窗口的 窗口过程(就是指处理这个消 息的东东)。就是说,Windows 会调用函数 WindowsProc()来处理这个消息。在 WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了一个消息循环。 下一个出场的东东就是窗口过程了,先歇一会儿再说吧?? 再次申明,不是我写的。觉得作者写的好转过来和大家一起分享。 第三讲:Windows 消息机制(3) (五)终止应用程序: Windows 是一种非剥夺式多任务操作系统。只有的应用程序交出 CPU 控制权后,Windows 才能把控制权交给其 他应用程序。当 GetMessage 函数找不到等待应用程序处理的消息时,自动交出控制权,Windows 把 CPU 的控 制权交给其他等待控制权的应用程序。由于每个应用程序都有一个消息循环,这种隐式交出控制权的方式保证合并 各个应用程序共享控制权。一旦发往该应用程序的消息到达应用程序队列,即开始执行 GetMessage 语句的下一 条语句。 当 WinMain 函数把控制返回到 Windows 时,应用程序就终止了。应用程序的启动消息循环前要检查引导出消息 循环的每一步,以确保每个窗口已注册,每个窗口都已创建。如存在一个错误,应用程序应返回控制权,并显示一 条消息。 但是, 一旦 WinMain 函数进入消息循环, 终止应用程序的唯一办法就是使用 PostQuitMessage 把消息 WM_QUIT 发送到应用程序队列。当 GetMessage 函数检索到 WM_QUIT 消息,它就返回 NULL,并退出消息外循环。通常, 当主窗口正在删除时(即窗口已接收到一条 WM_DESTROY 消息),应用程序主窗口的窗口函数就发送一条 WM_QUIT 消息。 虽然 WinMain 指定了返回值的数据类型,但 Windows 并不使用返回值。不过,在调试一应用程序时,返回值地 有用的。通常,可使用与标准 C 程序相同的返回值约定:0 表示成功,非 0 表示出错。PostQuitMessage 函数允 许窗口函数指定返回值, 这个值复制到 WM_QUIT 消息的 wParam 参数中。 为了的结束消息循环之后返回这个值, 我们的第二只小板凳中使用了以下语句: return msg.wParam ; //表示从 PostQuitMessage 返回的值 例如:当 Windows 自身终止时,它会撤消每个窗口,但不把控制返回给应用程序的消息循环,这意味着消息循环 将永远不会检索到 WM_QUIT 消息,并且的循环之后的语句也不能再执行。Windows 的终止前的确发送一消息给 每个应用程序,因而标准 C 程序通常会的结束前清理现场并释放资源,但 Windows 应用程序必须随每个窗口的撤 消而被清除,否则会丢失一些数据。 (六)窗口过程,窗口过程函数 如前所述, 函数 GetMessage 负责从应用程序的消息队列中取出消息, 而函数 DispatchMessage()要求 Windows 将消息传送给在 MSG 结构中为窗口所指定的窗口过程。 然后出台的就是这个窗口过程了,这个窗口过程的任务是 干什么呢,就是最终用来处理消息的, 就是消息的处理器而已, 那么这个函数就是 WindowProc,在 Visual C++6.0 中按 F1 启动 MSDN,按下面这个路径走下来: PlatForm SDK-->User Interface services-->Windows user Interface-->Windowing-->Window Procedures-->Window Procedure Reference-->Windows Procedure Functions-->WindowProc 啊,太累了,不过我们终于的 MSDN 中找到了这个函数,前几次我讲解这些 API 函数的时候,都是的知道的情况 下搜索出来的,所以没有详细给出每个函数的具体位置,而这次我却是一点点去找的,还好,没被累死,体会到 MSDN 的庞大了吧,不过我用的是 MSDN2000,是 D 版的,三张光盘装。你用的 MSDN 如果按这个路径走下去 的话,可能会找不到,不过我想大致也是在这个位置了,找找看~~~ LRESULT CALLBACK WindowProc ( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); 这个函数我们的第二只小板凳里被我们称为 WndProc. 下面讲解: 不知你注意到了没有, 这个函数的参数与刚刚提到的 GetMessage 调用把返回的 MSG 结构的前四个成员相同。 如 果消息处理成功,WindowProc 的返回值为 0. Windows 的启动应用程序时,先调用 WinMain 函数,然后调用窗口过程,注意:在我们的这个程序中,只有一 个窗口过程,实际上,也许有不止一个的窗口过程。例如,每一个不同的窗口类都 有一个与之相对应的窗口过程。 无论 Windows 何时想传递一个消息到一窗口,都将调用相应的窗口过程。当 Windows 从环境,或从另一个应用 程序,或从用户的应用程序中得到消息时,它将调用窗口过程并将信息传给此函数。总之,窗口过程函数处理所有 传送到由此窗口类创建的窗口所得到的消息。并且窗口过程有义务处理 Windows 扔给它的任何消息。我们在学习 Windows 程序设计的时候,最主要的就是学习这些消息是什么以及是什么意思,它们是怎么工作的。 令我们不解的是,在程序中我们看不出来是哪一个函数在调用窗口过程。它其实是一个回调函数.前面已经提到, Windows 把发生的输入事件转换成输入消息放到消息队列中,而消息循环将它们发送到相应的窗口过程函数,真 正的处理是在窗口过程函数中执行的,在 Windows 中就使用了回调函数来进行这种通信。 回调函数是输出函数中特殊的一种,它是指那些在 Windows 环境下直接调用的函数。一个应用程序至少有一个回 调函数,因为在应用程序处理消息时,Windows 调用回调函数。这种回调函数就是我们前面提到的窗口过程,它 对对应于 一个活动的窗口,回调函数必须向 Windows 注册,Windows 实施相应操作即行回调。 每个窗口必须有一个窗口过程与之对应,且 Windows 直接调用本函数,因此, 窗口函数必须采用 FAR PASCAL 调用约定。在我们的第二只小板凳中,我们的窗口函数为 WndProc,必须注意这里的函数名必须是前面注册的窗 口类时,向域 wc.lpfnWndProc 所赋的 WndProc。函数 WndProc 就是前面定义的窗口类所生成的所有窗口的窗 口函数。 在我们的这个窗口函数中,WndProc 处理了共有两条消息:WM_PAINT 和WM_DESTROY. 窗口函数从 Windows 中接收消息, 这些消息或者是由 WinMain 函数发送的输入消息, 或者是直接来自 Windows 的窗口管理消息。窗口过程检查一条消息,然后根据这些消息执行特定的动作未被处理的消息通过 DefWindowProc 函数传回给 Windows 作缺海上处理。 可以发送窗口函数的消息约有 220 种,所有窗口消息都以 WM_开头,这些消息在头文件中被定义为常量。引起 Windows 调用窗口函数的原因有很多,,如改变窗口大小啊,改变窗口在屏幕上的位置啊什么的。 Windows 已经把任务扔给窗口过程了,窗口过程是怎么处理消息的呢,稍息一 ...... 第三讲:Windows 消息机制(4) 下,让我们进行下一节:处理消 息 注:可能你看这些东西的时候有些乱,不过没关系,这很正常,多看几下 MSDN 就慢慢明白了,有我写这个专题的 时候,很多概念也太不清楚,不过等我查资料写下来后,感觉渐渐有些东西也有了点眉目,因为这本身也是个进步 的过程。 ---小朱 (七)处理消息 窗口过程处理消息通常以 switch 语句开始, 对于它要处理的每一条消息 ID 都跟有一条 case 语句。 大多数 windows proc 都有具有下面形式的内部结构: switch(uMsgId) { case WM_(something): //这里此消息的处理过程 return 0; case WM_(something else): //这里是此消息的处理过程 ruturn 0; default: //其他消息由这个默认处理函数来处理 return DefWindowProc(hwnd,uMsgId,wParam,lParam); } 在处理完消息后,要返回 0,这很重要-----它会告诉 Windows 不必再重试了。对于那些在程序中不准备处理的消 息,窗口过程会把它们都扔给 DefWindowProc 进行缺省处理,而且还要返回那个函数的返回值。在消息传递层次 中,可以认为 DefWindowProc 函数是最顶层的函数。这个函数发出 WM_SYSCOMMAND 消息,由系统执行 Windows 环境中多数窗口所公用的各种通用操作,例如,画窗口的非用户区,更新窗口的正文标题等等等等。 再提示一下,以 WM_的消息在 Windows 头文件中都被定义成了常量,如 WM_QUIT=XXXXXXXXXXX,但我们 没有必要记住这个数值,也不可能记得住,我们只要知道 WM_QUIT 就 OK 了。 在第二只小 板凳中我们只让窗口过程处理了两个消息:一个是 WM_PAINT,另一个是 WM_DESTROY,先说说第一 个消息---WM_PAINT. 关于 WM_PAINT: 无论何时 Windows 要求重画当前窗口时,都会发该消息。也可以这样说:无论何时窗口非法,都必须进行重画。 哎呀,什么又是"非法窗口",什么又是重画啊,你这人有没有完,嗯, 稍安勿燥,我比你还烦呢,我午饭到现在还没吃呢~你有点耐心,来点专业精神好不好,,,我开始在 MSDN 里 面找有关这个方面的内容了,别急,我找找看: Platform SDK-->Graphics and Multimedia Services-->Windows GDI-->Painting and Drawing-->Using the WM_PAINT Message-----终于找到了。 下面是一大套理论: 让我们把 Windows 的屏幕想像成一个桌面,把一个窗口想像成一张纸。当我们把一张纸放到桌面上时,它会盖住 其他的纸,这样被盖住的其他纸上的内容都看不到了。但我们只要把这张纸移开,被盖住的其他纸上的内容就会显 示出来了---这是一个很简单的道理,谁都明白。 对于我们的屏幕来说,当一个窗口被另一窗口盖住时,被盖住的窗口的某些部分就看不到了,我们要想看到被盖住 的窗口的全部面貌,就要把另一个窗口移开,但是当我们移开后,事情却起了变化-----很可能这个被盖住的窗口上 的信息被擦除了或是丢失了。当窗口中的数据丢失或过期时,窗口就变成非法的了---或者称为"无效"。于是我们的 任务就来了,我们必须考虑怎样在窗口的信息丢失时"重画窗口"--使窗口恢复成以前的那个样子。这也就是我们在 这第二只小板凳中调用 UpdateWindow 的原因。 你忘记了吗,刚才我们在(三)显示和更新窗口中有下面的一些文字: WinMain()调用完 ShowWindow 后,还需要调用函数 UpdateWindow,最终把窗口显示了出来。调用函数 UpdateWindow 将产生一个 WM_PAINT 消息,这个消息将使窗口重画,即使窗口得到更新.---这是程序第一次 调用了这条消息。 为重新显示非法区域,Windows 就发送 WM_PAINT 消息实现。要求 Windows 发送 WM_PAINT 的情况有改变 窗口大小,对话框关闭,使用了 UpdateWindows 和 ScrollWindow 函数等。这里注意,Windows 并非是消息 WM_PAINT 的唯一来源,使用 InvalidateRect 或 InvalidateRgn 函数也可以产 息...... 生绘图窗口的 WM_PAINT 消 通常情况下用 BeginPaint()来响应 WM_PAINT 消息。如果要在没有 WM_PAINT 的情况下重画窗口,必须使用 GetDC 函数得到显示缓冲区的句柄。这里面不再扩展。详细见 MDSN。 这个 BeginPaint 函数会执行准备绘画所需的所有步骤,包括返回你用于输入的句柄。结束则是以 EndPaint(); 在调用完 BeginPaint 之后,WndProc 接着调用 GetClientRect: GetClientRect(hwnd,&rect); 第一个参数是
本文档为【VC++入门教程】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_005190
暂无简介~
格式:doc
大小:59KB
软件:Word
页数:0
分类:工学
上传时间:2017-09-15
浏览量:19