




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
SDK 编程讲座(一) 摘自SDK 路报no.1(电子版)Wndows 编程两种方式:1.SDK编程:用C语言直接调用Windows API函数.这类API函数有上千个;2.MFC编程:用类将上述API 封装起来,用C+来调用.一般只需20 多个windows 类和另外20 多个通用的非windows 类就可干活了.Windows 编程的特点:C 语言编程至少有一个主程序,其名字是main()。Windows 程序则至少两个主程序,一个是WinMain(),另一个是窗口过程函数WndProc。其中WinMain函数为应用程序的入口点,它的名字一定要是WinMain。在Windows 中,应用程序通过要求Windows 完成指定操作,而承担这项通信任务的API 函数就是Windows 的相应窗口函数WndProc。在dos 里,程序能直接控制事件的发生顺序,结果等。而在Windows 里,应用程序不直接调用任何窗口函数,而是等待Windows 调用窗口函数,请求完成任务或返回信息。为保证Windows 调用这个窗口函数,这个函数必须先向Windows 登记,然后在Windows实施相应操作时回调,所以窗口函数又称为回调函数。WndProc 是一个主回调函数,Windows 至少有一个回调函数。回调函数WndProc 在哪里向windows 登记呢,请看这个语句:wc.lpfnWndProc = WndProc.一个简单windows程序执行过程有几大块:(一)建立,注册窗口类.(二)创建窗口.(三)显示和更新窗口.(四)创建消息循环.(五)终止应用程序.(六)窗口过程.(七)处理消息.(一)注册窗口类:1).建立窗口类WinMain()是程序的入口,它相当于一个中介人的角色,把应用程序(指小窗口)介绍给windows.首要的一步是登记应用程序的窗口类.窗口种类是定义窗口属性的模板,这些属性包括窗口式样,鼠标形状,菜单等等,窗口种类也指定处理该类中所有窗口消息的窗口函数.只有先建立窗口种类,才能根据窗口种类来创建Windows 应用程序的一个或多个窗口.创建窗口时,还可以指定窗口独有的附加特性.窗口种类简称窗口类,窗口类不能重名.在建立窗口类后,必须向Windows 登记.建立窗口类就是用WNDCLASS 结构定义一个结构变量,在这个程序中就是指 WNDCLASS wc ;然后用自己设计的窗口属性的信息填充结构变量wc 的域.要WinMain登记窗口类,首先要填写一个WNDCLASS结构,其定义如下所示:typedef struct _WNDCLASSAUINT 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)注册窗口类(1)第一个参数:成员style 控制窗口的某些重要特性,在WINDOWS.H 中定义了一些前缀为CS 的常量,在程序中可组合使用这些常量.也可把sytle 设为0.本程序中为wc.style = CS_HREDRAW | CS_VREDRAW,它表示当窗口的纵或者横坐标发生变化时要重画整个窗口。你看:无论你怎样拉动窗口的大小,那行字都会停留在窗口的正中部,而假如把这个参数设为0 的话,当改动窗口的大小时,那行字则不一定处于中部了。(2)第二个参数:lpfnWndProc 包括一个指向该窗口类的消息处理函数的指针,此函数称为窗口过程函数。它将接收Windows 发送给窗口的消息,并执行相应的任务。(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 指定了本窗口的类名。利用RegisterClass 可以将该类名注册,下次在CreateWindow 中就可以根据该类名生成一个具体的window 了。当对WNDCLASS 结构域一一赋值后,就可注册窗口类了,在创建窗口之前,是必须要注册窗口类的,注册窗口类用的API 函数是RegisterClass,注册失败的话,就会出现一个对话框如程序所示,函数RegisterClass 返回0 值,也只能返回0值,因为注册不成功,程序已经不能再进行下去了。在本程序中注册窗口类如下:if (!RegisterClass (&wc) MessageBox (NULL, TEXT (This program requires Windows NT! ,zAppName,MB_ICONERROR) ;return 0 ;(二)创建窗口注册窗口类后,就可以创建窗口了,本程序中创建窗口的有关语句如下:hwnd = CreateWindow (szAppName, / window class nameTEXT (欢迎你的到来! , / window captionWS_OVERLAPPEDWINDOW, / window styleCW_USEDEFAULT, / initial x positionCW_USEDEFAULT, / initial y positionCW_USEDEFAULT, / initial x sizeCW_USEDEFAULT, / initial y sizeNULL, / parent window handleNULL, / window menuhandlehInstance, / program instance handleNULL) ; / creation parameters参数1:登记的窗口类名,这个类名刚才咱们在注册窗口时已经定义过了。参数2:用来表明窗口的标题。参数3: 用来表明窗口的风格,如有无最大化,最小化按纽啊什么的。参数4,5: 用来表明程序运行后窗口在屏幕中的坐标值。参数6,7: 用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度。参数8: 在创建窗口时可以指定其父窗口,这里没有父窗口则参数值为0。参数9: 用以指明窗口的菜单,菜单以后会讲,这里暂时为0。最后一个参数是附加数据,一般都是0。CreateWindow()的返回值是已经创建的窗口的句柄,应用程序使用这个句柄来引用该窗口。如果返回值为0,就应该终止该程序,因为可能某个地方出错了。如果一个程序创建了多个窗口,则每个窗口都有各自不同的句柄.(三)显示和更新窗口API函数CreateWindow 创建完窗口后,要想把它显示出现,还必须调用另一个API 函数ShowWindows.形式为: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 tagMSGHWND 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,结束消息循环,从而终止应用程序。消息用GetMessage 读入后(注意这个消息可不是WM_QUIT 消息),它首先要经过函数TranslateMessage()进行翻译,这个函数会转换成一些键盘消息,它检索匹配的WM_KEYDOWN 和WM_KEYUP 消息,并为窗口产生相应的ASCII 字符消息(WM_CHAR),它包含指定键的ANSI 字符.但对大多数消息来说它并不起什么作用,所以现在没有必要考虑它。下一个函数调用DispatchMessage()要求Windows 将消息传送给在MSG 结构中为窗口所指定的窗口过程。我们在讲到登记窗口类时曾提到过,登记窗口类时,我们曾指定Windows把函数WindosProc作为咱们这个窗口的窗口过程(就是指处理这个消息的东东)。就是说,Windows会调用函数WindowsProc()来处理这个消息。在WindowProc()处理完消息后,代码又循环到开始去接收另一个消息,这样就完成了一个消息循环。(五)窗口过程,窗口过程函数如前所述,函数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 windowUINT uMsg, / message identifierWPARAM wParam, / first message parameterLPARAM lParam / second message parameter;下面讲解:不知你注意到了没有,这个函数的参数与刚刚提到的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 已经把任务扔给窗口过程了,窗口过程是怎么处理消息的呢?稍息一下,让我们进行下一节:处理消息.(六)处理消息此部分位于一个循环中。窗口过程处理消息通常以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 要求重画当前窗口时,都会发该消息。也可以这样说:无论何时窗口非法,都必须进行重画。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 接着调用GetC
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电子束加速器创新创业项目商业计划书
- 教师招聘之《小学教师招聘》通关训练试卷详解(达标题)附答案详解
- 2025年教师招聘之《幼儿教师招聘》真题带答案详解(综合题)
- 教师招聘之《小学教师招聘》题型+答案(考点题)附参考答案详解【模拟题】
- 教师招聘之《小学教师招聘》考前冲刺练习(综合题)附答案详解
- 2025年教师招聘之《小学教师招聘》考试题库带答案详解(巩固)
- 内蒙古呼伦贝尔农垦集团有限公司招聘笔试题库及1套参考答案详解
- 2025年思政综合测试题及答案
- 工行历年考试题库及答案
- 节能知识培训单位职责课件
- 日本所有番号分类
- (高清版)DG∕TJ 08-7-2021 建筑工程交通设计及停车库(场)设置标准
- 《优化教学策略:打造卓越课件的秘诀》课件
- 教师专业发展-课件
- 2025年数学新课标《义务教育数学课程标准(2025年版)》解读
- 网络分析仪企业ESG实践与创新战略研究报告
- 保险行业组织发展
- 管制部运行管理手册(机场)第六章 运行程序
- 药品临床综合评价解读
- 2025年中国人寿:养老险北京分公司招聘笔试参考题库含答案解析
- 2025年度建筑地基基础清包工劳务合同规范范本
评论
0/150
提交评论