Windows编程初步
|
|||
目前来说Windows已经家喻户晓,它的历史是Microsoft历史上最辉煌的一页.人们现在已经基本上使用Windows操作系统,因此在编程方面我们有必要从DOS环境编程向Windows编程转变.本文将向大家介绍Windows的技术特点,友好的界面及其内部引擎.除了对Windows系统的基本概念的介绍外,还将介绍用C语言和Windows SDK编写的Windows程序,使读者对Windows的编程思想有所了解,虽然这里我们还没有进入利用VC的MFC编程,但是可以给即将要学习Windows编程的同学奠定基础。 本文分为几个部分: 一.Windws类操作系统的技术特点 二.Windows的窗口和控件 三.Windows内部引擎 四.编写一个Windows程序 好了,那么下面我们一起进入Windows编程的广阔天地吧! 一.Windws类操作系统的技术特点:
以上是Windows的主要技术特点,此外Windows还有许多其他的技术,如网络功能,多媒体技术等.可以说Windows充分利用了PC的资源,同时也赋予了PC强大的活力. 二.Windows的窗口和控件: Windows具有友好并且华丽的界面.窗口是Windows本身及Windows环境下的应用程序的基本界面单位.之所以这样说因为Windows控件也是窗口,只不过是一种特殊的窗口罢了.从用户的角度看,Windows的窗口就是一个显示在屏幕上的矩形区域,其外观独立于应用程序,它就是生成该窗口的应用程序与程序用户间的直观接口.从应用程序的角度看,窗口是受其控制的一部分矩形屏幕区.应用程序生成并控制与窗口的有关的一切内容,包括窗口的大小,风格,位置及窗口内显示的内容.用户启动一个应用程序后,程序将创建一个窗口,并在那里等待着用户的要求.每当用户选取窗口内的选项后,程序即对此作出响应. 不论是Windows95,WindowsNT4.0,还是Windows98起用户程序接口API都是Win32API所以他们的编程大部分一样. 以Windows98为代表的32位操作系统还支持许多新的公用控件,这些控件使应用程序更加灵活,也使应用程序的外观更美观.Windows中有许多的常用控件,这些控件我们曾经在VB零起步中或其他文章中进行过介绍,这里就不详细介绍了.这里要说明的是:本文旨在带领大家进入Windows编程领域,编程的语言是C或C++,下面的例子也使用VC6.0编写的. 三.Windows内部引擎: 在这里我想对Windows的内部引擎多说几句,因为这很有利于我们理解Windows编程的基本思想. 1.事件驱动模型和消息循环: 用过TC的同学应该知道在DOS下开发的程序主要是使用顺序的过程驱动程序设计方法.请注意过程驱动这个概念,在这种设计思想的指导下一个程序会有一个明显的开始,明显的执行过程及一个明显的的结束.在程序的执行过程中,程序可以直接控制程序事件或过程的顺序. 但是在Windows程序设计方法中上述这种过程驱动的设计思想就要被彻底的打破.Windows的程序设计方法与DOS程序设计的不同就在于Windows程序是事件驱动的.事件驱动的程序是由事件的发生来控制.这种设计思想是一种非顺序方式处理事件,从而避开了顺序的过程驱动方法. 那么我们先来了解一下什么是事件.事件的含义很广泛,最常见的是鼠标事件,包括鼠标移动,鼠标左右键的单击双击,鼠标位于窗口的位置等.而应用程序启动后,程序等候事件的发生,当某事件发生时进行相应的处理,执行特定的功能.事件也可以由用户自己来定义,例如,某段程序处理完毕也可以作为一个事件. 事件驱动程序设计是围绕消息的产生与处理而展开的.一条消息是关于发生的事件的信息.例如,一个键或鼠标按钮被按下,就发生一个消息,而当松开时,另一个消息又发生了.作为一个Windows程序员,你的Windows应用程序所做的主要工作也就是对各种消息进行处理.应用程序的执行顺序也是无法预知的,而且消息的产生也不仅仅来源于键盘鼠标.消息可由应用程序本身产生,也可以由运行的其他程序产生,还可以由用户或Windows产生.每当事件发生时,Windows做出记录并将相应的消息分配到有关的应用程序. 初学者如果还没有体会到Windows的消息的话可以自己体验一下消息的存在. 在VC++6.0的Tool菜单中选择Spy++工具,它可以监视消息的产生.它也在Microsoft VisualStudio6.0 Tools程序组中找到该工具.单击Spy++图标,打开窗口如图: 图1 Spy++的工作窗口 打开主菜单的Spy菜单,选择Message命令(Ctrl+M),启动Message Options对话框,在Windows页面上有一个窗口的图标,把其中的"靶心"拖到你想进行消息监视的窗口内,比如你可以把它拖到桌面上,这是你可以观察到桌面所接收的消息.选择Message页面,这是个消息过滤器用户可以选择感兴趣的消息进行监视,默认情况下是选择所有消息,点击OK退出.Spy++工作区现在为你打开了一个新的窗口,用以显示消息的内容.这是你在桌面上做任意的动作就可以看到记录窗口中出现了大篇幅的消息记录.消息的名字是以"WM_"开头的,例如,WM_SETCURSOR是放置鼠标光标,WM_MOUSEMOVE是鼠标移动消息.如图所示: 图2 用Spy观察Windows消息 Windows为应用程序消息提供了称为消息队列(Message Queue)的保留区.在操作系统中的每个在执行的程序(包括应用程序和系统自身)都有自己的消息队列.由操作系统以及由其他应用程序或用户向应用程序发送的全部消息都存储在队列中,各消息在队中等待被调用.Windows应用程序以特定的循环调用Windows消息,该循环就是通常所说的消息循环(Message Loop).消息循环是一个简单的While()循环,他将一直运行,知道接收到终止执行的消息才会关闭应用程序,停止循环. 下图展示了Windows应用程序的流程和消息循环及处理机制. 图3 Windows应用程序的流程,消息循环和处理机制 2.多任务的内幕---进程和线程 多任务的操作系统是Windows的又一重要特征.当用户同时在Windows里打开多个窗口或一边听MP3一边工作时,Windows本身正在忙碌的进行各应用程序的切换,分时地工作着.虽然从表面上看,好像多个应用程序在同时进行,但是对单CPU的机器来说,无论在任何时刻,其中只有一个程序可以真正占有处理器. 在Windows中多任务机制使用了进程和线程的概念. 进程是应用程序的一个运行例程.又的应用程序准许有多个例程,比如画图,写字板等应用程序可以打开多个副本,有的应用程序只能有一个例程在运行,比如刚刚使用的Spy++工具.每一个进程由若干代码和数据块组成.理论上讲,32位Windows下应用程序的进程拥有4GB的虚拟地址空间,当然现在还没有这么大的程序.每个进程还拥有自己的资源,以及线程(Thread). 线程是进程中的一个执行单元.同进程中的各个线程对应于一组CPU指令,一组CPU寄存器以及一个堆栈.一个进程至少有一个"主线程",当然也可以有多个线程.进程实际上是通过线程来执行的.Windows家族中最卓越的Windows NT被设计成可以在有多个CPU的计算机上运行,此时多到进程和线程可真正的同时运行,并被均等的调入到全部有效CPU内执行,这种性能当然很理想.当前的PC多是单个 CPU的机器,那么先程必须排队等待"机时",按顺序获得它的一小段有效的执行时间.这一小段时间称为时间片.当一个线程的时间片用完,它将被迫转入"睡眠"状态,等到下一轮有效时间片到达,它才将被重新"唤醒",继续执行.当然在"睡眠"前和"唤醒"前要保存运行环境和恢复运行运行环境. Windows在调度进程和线程时,除了有排队机制外,进程和线程还有自己的优先级(Priority),优先级高的进程和线程将获得较多的时间片.这样,在应用程序中,程序员可以通过优先级的制定来制定是实行强的任务处理和非试试行性的任务处理. 我们现在可以体会一下进程和线程的存在.我们仍可用Spy++工具,你会发现Spy++确实很有用. 打开Spy菜单,选取Process命令(Ctrl+P).工作区内出现一个记录系统中正在运行的进程的窗口.每个进程后的十六进制数是进程在系统中的标识,标识后是进程的名字.将每个进程点开,树状图列出了进程的线程.有的线程点开,列出的是属于该线程的窗口.选中线程或进程双击鼠标,会列出进程和线程的详细信息.其中可以看到优先级(Priority Base).如图所示: 图4 SPY列出的进程和线程的详细信息 3.应用程序共享资源---动态链接库技术 动态链接库技术作为Windows的重要技术,其技术思想并不是起源于Windows.DOS环境下的C语言的标准函数库大家都是很熟悉的.C语言是依赖其Runtime库运行的.我们书写调用语句,链接程序将调用函数(如我们熟悉的Printf,getchar),从运算函数库拷入程序来形成可执行文件.这种用链接C Runtime库的方法叫做静态链接.这种静态链接的方法很大程度上解放了程序员,使其不必反复编制诸如读写字符 或格式化输出等公用过程,这些编入运行库的代码在链接时由链接程序拷入用户的代码.此外,程序员还可以方便的建立自己的函数库,其中包括自己常用的功能并标准库里没有的函数. 这种使用公共函数成为工具的思想,消除了重复设计的现象,但在Windows多任务环境下下却带来很多问题.多个程序在Windows环境下共享内存,每个程序都保存一个公用函数副本,这显然导致了内存的浪费.比如每个程序都有用到getchar()函数,静态链接库将给每个应用程序复制一个getchar()函数副本,结果内存中将出现多个getchar()副本这显然非常浪费内存空间.因此引出了动态链接的构想. Windows的库是动态链接的.链接程序并不把库函数拷入程序的可执行文件,而是由程序的可执行文件在执行过程中调用库函数.这种方法节约了内存,无论多少并行程序,要用到某个函数时,该函数在内存中只有一个拷贝.此外当函数被修改后,不必重新链接调用该函数的可执行文件.在Windows中,大部分功能都是有动态链接库(.DLL文件)实现的.动态链接库是Windows的核心和精华,因为Windows的几个主要模块其实质都是动态链接库.Windows向用户提供的应用程序接口(API)也使用动态链接库实现的(下面一小节会讲到).动态链接库的实质是一个可执行模块.它可以包括Windows应用程序所有的函数,以及资源和其他代码.但动态链接库本身不会自己运行,它将驻留内存而其他应用程序来调用它.在VC++6.0中我们可以编写自己的动态链接库.我们在Windows目录下的system文件夹中会看到大量的链接库(*.DLL). 四.编写一个Windows程序: 下面我想利用API和SDK编写一个简单的Windows程序,在其中体现Windows的概念. 在编写这个例程之前我想先向大家介绍一下Windows应用程序接口API和开发工具包SDK的概念. API这个词是指应用程序设计接口,其实质是在程序内的调用一套函数,我们可以用它创建其他程序.在调用的过程中不必知道其内部的实现,只要知道其出现原型及返回值就可以了.Windows API是当今最著名的API,它通过DLL实现,任何支持Windows API的语言都可以编写Windows应用程序.Windows API本身就是Windows的编程基础,其本身包括了Windows的基本概念.但由于Windows本身结构的复杂性,许多API函数的内在机理也很复杂,API函数间的关系也很复杂,有人比喻API相当于Windows应用程序编写的汇编语言.当前许多编程语言不仅支持Windows API,还将API封装起来,例如VC++的MFCDelphi,C++Build等都通过自己的函数类库来实现Windows API的功能,其实质还是最终转化为API. 在Windows核心中有三个动态链接库构成了Win32 API的主体:
好了不说别的了,下面就开始我们的第一个Windows程序. 了解API有助于了解Windows内部运行机制,因此在初学者接触MFC之前用API编写一个Windows程序是很有好处的. 我们用VC++6.0编写这个程序,首先打开VC++6.0打开File菜单,New命令建立一个Win32 Application类型的工程,注意,在建立工程时在第2步选择"A simple Win32 application.".将存放WinMain函数的文件修改如下: //目的:演示利用Windows API开发Windows应用程序 //*******************源代码如下**************************** #include "stdafx.h" INT PASCAL WinMain(HINSTANCE hInstance, LRESULT CALLBACK WndProc(HWND hMainwnd, //窗口句柄 //以下定义全局变量 //实例句柄 //应用程序名 //程序标题 INT PASCAL WinMain(HINSTANCE hInstance, //主窗口句柄(句柄为窗口windows中的标识) //定义windows消息数据结构 //定义窗口类 if(!hPrevInstance) //判断是否有其他应用程序实例在运行 //以下为窗口赋值 //注册窗口 } //创建应用程序窗口 ShowWindow(hMainwnd,SW_SHOWMAXIMIZED); //显示窗口 UpdateWindow(hMainwnd); //刷新窗口用户区 while(GetMessage(&message,NULL,0,0)) //建立消息循环 TranslateMessage(&message); //翻译键盘消息 } return message.wParam; } /*********************************************************************** LRESULT CALLBACK WndProc(HWND hMainwnd, //窗口句柄 char MsgLBTN[]="你刚按下了鼠标左键!"; //消息处理分支 case WM_RBUTTONDOWN: //右鼠标键被按下 MessageBeep(MB_ICONINFORMATION); } case WM_LBUTTONDOWN: //左鼠标键被按下 MessageBeep(MB_ICONINFORMATION); } case WM_DESTROY: //关闭窗口 PostQuitMessage(0); } default: break; } //未列入处理的消息由windows缺省操作完成处理 } 好了,程序完成运行一下,你可以看到如图所示的结果: 图5 API编写的Windows程序运行结果 运行时你可能会感到有些失望因为写了那么长的代码就这么简单的结果,的确是,用API写应用程序的确是很繁琐的事情,但是在其中很多地方可以反映Windows运行机制的内容. 对例程的剖析: 1.主函数WinMain(): (1)WinMain程序的入口:这就同DOS下的C程序中的main()函数类似,Windows程序的入口是WinMain().在WinMain这个主程序段中要完成注册窗口类型,创建窗口,显示窗口,建立消息循环等工作. (2)用RegisterClass函数注册窗口:任何窗口要在Windows中显示首先要注册,这样才能在Windows中管理.注册前要定义窗口类.窗口类是记录窗口信息的结构体在程序中WNDCLASSmyWC就是定义一个窗口类的数据结构. myWC.style //定义窗口类型,风格 定义了窗口类后就可以注册窗口类了.用RegisterClass(&myWC)语句注册过后就可以建立窗口的实例.创建窗口类所用的API函数CreateWindow,CreateWindow所用的参数包括了窗口实例的名字,标题,窗口风格,显示位置,窗口大小等. 现在为止,要创建的窗口已经在内存中准备好了,只等着显示出来. (3)用ShowWindow函数将窗口显示出来. (4)建立消息循环机制:消息循环是用While循环来实现的. 即: while(GetMessage(&message,NULL,0,0)) //建立消息循环 TranslateMessage(&message); //翻译键盘消息 } 其中GetMessage函数从消息队列中取出一条消息,并将其放入Windows的消息结构MSG中.MSG结构的含义如下: typedef struct tagMSG { HWND hwnd; //窗口句柄,Windows对窗口管理而负给每个窗口唯一的标识符. WPARAM wParam; //消息附加参数,包含消息的内容. DWORD time; //消息送入队的时间. }MSG; Windows程序将辨识消息的值UINT message/然后跳转到相应的处理程序.在处理程序中消息的wParam,lParam的内容决定具体如何处理消息.这就是事件驱动程序的实现机理. TranslateMessage函数实现键盘消息翻译,将键盘消息翻译成Windows字符集. 到这里,WinMain主函数的任务已经完成,他创建了窗口和消息循环. 2.窗口过程---消息处理的主体 窗口过程函数是应用程序的主体部分,在这里将处理所有的消息,应用程序的各个功能就是在消息处理过程中实现的. 窗口过程的函数原型如下: LRESULT CALLBACK WndProc(HWND hMainwnd, //窗口句柄 这里的过程名WndProc已在RegisterClass注册窗口前的定义窗口类中出现过了,该过程名已同前面定义的窗口紧密的联系在一起.其后面的参数意义如下: HWND hwnd //该参数是窗口过程对应的句柄 窗口处理程序往往很长,因为它要处理各种各样的消息.但窗口程序的主体结构很简单.就是switch-case结构,如下所示: switch(message) //根据消息标识符,进入不同消息处理的分支 ....... //此处为消息处理过程 case WM_***: ...... //此处加入根据消息内容进行的处理过程 ...... } case WM_DESTROY: //WM_DESTROY是消息窗口的消息. } 虽然窗口处理过程很简单,但使应用程序要处理的消息会很多,特别是应用程序由许多菜单和按钮,消息处理过程可能十分复杂.VC++的MFC的消息处理机制大大简化了这一过程,但我在这篇文章中还不涉及MFC的内容. 我们看到在例程中的switch-case结构中主要处理了两条消息:WM_LBUTTONDOWN和WM_RBUTTONDOWN.这两条消息是代表鼠标左键和右键按下的动作.当程序检测到鼠标动作时,转入相应的程序分支执行. MessageBeep(MB_ICONINFORMATION); MessageBox(GetFocus(),MsgLBTN,"Message",MB_OK|MB_ICONINFORMATION); 到此为止,我们已经学习了Windows编程的初步知识,理解了Windows的运行机制,事件驱动模型和Windows消息循环的概念,这为我们继续学习VC++的Windows编程和MFC编程奠定了基础,希望这篇文章可给读者带来帮助. 点击此处下载本文源代码。 |
Windows编程初步相关推荐
- Windows编程初步(一)
第一节:安装帮助文档 使用C语言进行Windows开发,必然使用到WindowsSDK.Windows SDK指Windows开发人员工具包,是为使用C语言开发Windows程序所提供的工具集.里面提 ...
- Windows编程初步(三)【说明:有敏感字眼已全删,不知道为啥还审核不通过】
第三节 设计输出及利用在线帮助 在Windows中,消息ON_PAINT是专门用来处理输出的.基本所有的输出代码应放在这里. .其输出方式不再限于从上往下,而是全屏可控,因此每个输出都需要告知系统输出 ...
- Windows编程初步(二)
第二节:简单的Windows程序(二) 下面为这个程序增加一个菜单项: 首先设计用户菜单.在工作区里找到资源视图.点击Menu左边的+号,双击出现的IDC_WIN_STEP1菜单. 图7 资源视图中的 ...
- Windows网络编程初步
1. OSI/RM和TCP/IP 国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)制定OSI/RM OSI/RM:Open SystemInterconnect/Recommended ...
- [转]Windows 语音编程初步
[转]Windows 语音编程初步 一.SAPI简介 软件中的语音技术包括两方面的内容,一个是语音识别(speech recognition) 和语音合成(speech synthesis).这两个技 ...
- 用C语言进行Windows编程入门
用C语言进行Windows编程入门 本文对一般教程或网上有的(如C语言语法等基础)不深入介绍,对初学者易造成疑惑误解或难以找到的内容进行较详尽的介绍. 学习C语言很久了,一直面对控制台应用程序(Win ...
- Windows 编程,画笔画刷以及几何图形的绘制
Windows编程,画笔画刷的介绍 画笔,可以用以下代码新建一个画笔对象: HPEN hpen = CreatePen(PS_SOLID, 1, RGB(255,0,0)); 可以看到,画笔的Crea ...
- 《从问题到程序:用Python学编程和计算》——第2章 计算和编程初步 2.1 数值表达式和算术...
本节书摘来自华章计算机<从问题到程序:用Python学编程和计算>一书中的第2章,第2.1节,作者 裘宗燕,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第2 ...
- 如何使对话框中接收到WM_CHAR消息(Windows编程)
我们大家都知道,对话框是有的时候捕获不到WM_CHAR消息的.比如,你想使对话框里的Edit控件所键入的全部变为大写.我们毫不犹豫的写到: #include //Declare the Dial ...
最新文章
- 卷积核一定可以提升网络性能吗?-分类0,2
- 162. Leetcode 45. 跳跃游戏 II (贪心算法-贪心区间)
- java 获取系统当前时间
- 连接端口 配置hive_Hadoop大数据平台数据仓库Hive管理操作
- 【ssi】增删改查六操作小框架(八)
- 课程设计完成之后要考虑的问题
- 计算机网络--接入互联网方式
- Lync Server 2010的部署系列_第六章 安装配置拓扑生成器、前端Server、前端池
- mt7620a拓展串口
- iphone录屏没内部声音_6个iPhone隐藏功能,让你的手机好用到飞起
- Leetcode每日一题:327.count-of-range-sum(区间和的个数)
- 《『若水新闻』客户端开发教程》——11.代码编码(3)
- SQL Server 2008 R2 中英文 开发版/企业版/标准版 链接地址
- nodeAPI--TCP
- vb.net 教程 3-1 窗体编程基础 2
- 绘制双Y轴坐标系及其设置
- Qt编写可视化大屏电子看板系统31-模块9视频监控
- 学计算机的数学一定要好吗,学计算机一定要数学好吗?
- 数据库原理第三章习题作业
- 机器学习6:——Pandas——6:高级处理3:数据合并
热门文章
- 2.6实训任务 Xshell、XFTP下载安装
- vue项目滚轮失效问题
- 快女王艺洁炮轰节目组 杨洋不是真“小三”
- “幻想计划”灵魂武器训练策略
- 如何实现ArrayList排序
- 苹果手机功能大全介绍_苹果手机初级摄影介绍
- POJ2394 Checking an Alibi ——最短路
- linux消耗ram内存吗,linux - 释放Ubuntu 8.04服务器上的内存(RAM) - Ubuntu问答
- 如何在自己网站内分享内容到twitter
- Ubuntu Linux下最好用的五大BT工具介绍