ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:95.89KB ,
资源ID:3552189      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3552189.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Win32编程2.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Win32编程2.docx

1、Win32编程2Win32编程一、 Win32编程中的宏学习windows编程是一个比较难的过程,主要的障碍是因为windows程序中很多新的东西,我们一下子不能适应,下面我们就来扫清这些障碍:n 我们在上一课中看到了一个简单的windows程序,大家会发现windows程序中有很多全部大写定义的东西,这就是我们的障碍之一,因为,太多的东西我们以前没有见过。Windows程序中全大写的东西可以分为三种: 第一种:windows定义的变量比如这句:LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa

2、ram ) 这是一个方法的定义,这和我们以前的程序就有太多的不同。下面的列表是从相应windows的头文件中摘下来的,看完这个后,你是否可以理解上面这句话的意思。#define CONST const#define CALLBACK _stdcall#define WINAPI _stdcalltypedef CONST CHAR * LPCSTRtypedef unsigned long DWORD;typedef int BOOL;typedef unsigned char BYTE;typedef unsigned short WORD;typedef float FLOAT;typed

3、ef DWORD far * LPDWORD;typedef void far * LPVOID;typedef CONST void far * LPCVOID;typedef int INT;typedef unsigned int UINT;typedef UINT WPARAM;typedef LONG LPARAM;typedef LONG LRESULT;其实,windows程序把很多变量进行了重新定义,还记得typedef这个类型定义关键字吧!上面的UINT、WPARAM、LPARAM,其实都是unsigned int(无符号整数),HWND也是无符号整数,后面我们详细介绍HWN

4、D,今后,如果大家见到了一个类型是全大写的,那么它一定是在windows的头文件中重新定义了。还有就是:LRESULT CALLBACK,从上面的表中,大家可以看到他们是返回类型和宏定义,其中,LRESULT是long,而CALLBACK是函数的调用方式_stdcall,是一种调用约定,详见文章函数调用约定.txt 第二种:windows的宏定义:在前面,大家看到了_stdcall是一个宏定义,在windows程序中有大量的宏定义,宏定义用于这样几个地方: 常量所有的消息都是常量,比如前面看到的 WM_KEYDOWN、WM_PAINT等,所有的键盘标识,如VK_ESCAPE,还有就是我们在函数

5、调用中用到的 一些参数:如WS_OVERLAPPEDWINDOW, WHITE_BRUSH、IDI_APPLICATION等都是常量 简单函数如:#define MAKEWORD(a, b) (WORD)(BYTE)(a) | (WORD)(BYTE)(b) 8)#define MAKELONG(a,b) (LONG)(WORD)(a) | (DWORD)(WORD)(b) 16) & 0xFFFF)#define LOBYTE(w) (BYTE)(w)#define HIBYTE(w) (BYTE)(WORD)(w) 8) & 0xFF)以上的都是简单的函数,如LOWORD是表示取一个DWO

6、RD(32位整数)的低16位,而HIWORD取高16位 程序结构中用到的宏在后面的MFC学习中,我们要学习的消息映射中的BEGIN_MESSAGE_MAP、DECLARE_MESSAGE_MAP等就是在程序结构中用到的宏。 第三种:是windows中的结构:windows程序中大量使用结构,对这些结构的掌握程度,可以作为衡量一个程序员对windows程序的熟悉程度,windows程序的结构难,而且结构中的成员非常多,是我们学习的难点。在上一章的程序中,我们看到的结构有:WNDCLASS、MSG等,学习中,大家应该掌握这些常用结构的常用成员的用法。 typedef struct tagMSG H

7、WND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; MSG;二、理解句柄上一章的程序中,我们看到了这样的类型定义:HINSTANCE hInstanc; /执行实体(程序自身)的句柄 HWND hWnd; /窗口句柄 在windows程序中,有很多以H开头的变量类型,这个H,我们叫HANDLE(句柄)。handle的本意是把柄,把手的意思。是你与操作系统打交道的东西。举个例子:比如你做了亏心事(我说的是比如,呵呵),不幸让我抓住了把柄,那么我让你做什么你就得做什么,因为你的把柄在我这。我们编程的

8、时候也是这样,比如我们要想操纵一个窗口,那我们就必须抓住它的把柄,只有这样,我们才能改变它的属性,改变它的式样,甚至销毁它。句柄在Windows中使用非常频繁。句柄是WINDOWS用来标识应用程序所建立或使用对象的唯一整数(通常为32位的整数)。这非常类似我们每个人都有一个身份证号,我们用这个编号区分不同的人,同样windows用不同的句柄来区分和使用各种各样的应用程序实例,如窗口、控件、位图、GDI对象等,如:HWND 窗口HINSTANCE 执行程序的实例HMENU 菜单HICON 图标HCURSOR 鼠标光标HDC 图形设备HBITMAP 位图HBRUSH 画刷HPEN 画笔我们也可以把

9、Windows中的句柄看成传统C或者MS-DOS程序设计中使用的文件句柄。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。句柄的实际值对程序来说是无关紧要的。只是,我们要知道在程序中间怎样去使用这个句柄,以后,在很多的函数中,第一个参数就会是该对象句柄,如:ShowWindow,UpdateWindow等函数的第一个参数都是窗口句柄。如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的对象是驻留在内存中的。如果简单地理解,似乎我们只要获

10、知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统,在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢? 为了解决这个问题,Windows操作系统为各应用程序腾出一些内存地址,用来专门登记各应用对象在内存中的地址变化,而这个内存地址(存储单元的位置)本身是不变的。Windows内存管理器在内存中移动对象的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需

11、记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配的,当系统卸载时(Unload)又释放给系统。句柄地址(稳定)记载对象在内存中的地址(不稳定)实际对象三、消息处理机制Windows程序中有两个消息队列,分别叫系统消息队列和窗口消息队列,操作系统的执行过程,就是不断产生消息和处理消息的过程,这里的消息又叫事件,前面介绍过windows的事件驱动的概念,核心的思想就是windows程序是通过不断处理消息来完成任务的,那么到底消息是怎么产生的,消息有是什么样子的呢?消息的产生有几个来源: 用户操作产生的消息比如,我们点击了窗口上的一个按钮,按下

12、了键盘上的键等等,都会产生消息。 应用程序产生的消息比如,一个窗口被最大化时,它就会产生重画(WM_PAINT)的消息,后面的课程中会详细说明。也可以使用SendMessage()或PostMessage()主动发送一条消息。 操作系统产生的消息比如,我们在程序中有一个定时器,系统隔相应的时间就会产生WM_TIMER(计时器事件)。在Win32编程中,消息循环是相当重要的一个概念,看似很难,但是使用起来却是非常简单。在WinMain()函数中,创建了应用程序主窗口之后,就要启动消息循环,其代码如下:while (GetMessage(&msg, NULL, 0, 0) TranslateMes

13、sage(&msg); DispatchMessage(&msg);Windows应用程序可以接收以各种形式输入的信息,这包括键盘、鼠标动作、记时器产生的消息,也可以是其它应用程序发来的消息等等。Windows系统自动监控所有的输入设备,并将其消息放入该应用程序的消息队列中。GetMessage()函数则是用来从应用程序的消息队列中按照先进先出的原则将这些消息一个个的取出来,放进一个MSG结构中去。GetMessage()函数原型如下:BOOL GetMessage(LPMSG lpMsg, /指向一个MSG结构的指针,用来保存消息HWND hWnd, /指定哪个窗口的消息将被获取UINT w

14、MsgFilterMin, /指定获取的主消息值的最小值UINT wMsgFilterMax /指定获取的主消息值的最大值);GetMessage()将获取的消息复制到一个MSG结构中。如果队列中没有任何消息,GetMessage()函数将一直空闲直到队列中又有消息时再返回。如果队列中已有消息,它将取出一个后返回。MSG结构包含了一条Windows消息的完整信息,其定义如下:typedef struct tagMSG HWND hwnd; /接收消息的窗口句柄UINT message; /主消息值WPARAM wParam; /副消息值,其具体含义依赖于主消息值LPARAM lParam; /

15、副消息值,其具体含义依赖于主消息值DWORD time; /消息被投递的时间POINT pt; /鼠标的位置 MSG; GetMessage()函数获取到一条消息后,会将该消息从消息队列中删除掉。如果不想删除,可以使用PeekMessage()函数,PeekMessage()函数只是去消息队列中复制一条消息,但不会从消息队列中删除该消息。消息的处理过程如下图所示:假如,我们在一个窗口中点击了一下鼠标左键,处理过程是这样的:首先,系统会填充一个MSG消息结构,把当前的消息句柄放到MSG结构的hwnd成员中去,把消息类型WM_LBUTTONDOWN(鼠标左键按下)放到messge成员中,把鼠标的位

16、置信息放到lParam中,然后把产生的消息放到系统消息队列的尾部,GetMessage函数从消息队列的头部一直不停的取消息,当取到刚才的消息后,会根据消息结构成员的第一个参数即窗口句柄,把消息分发给不同的窗口消息队列,窗口消息队列得到消息后,根据消息的类型,进行不同的处理。窗口对消息的响应过程,前文有说明,在这里就不多说了。四、Win32程序对键盘的控制在一个程序中,我们和程序的交互一般都是通过键盘和鼠标来完成的,下面,我们先来看看对键盘的处理。 按键消息当您按下一个键时,Windows把WM_KEYDOWN或WM_SYSKEYDOWN消息放入有输入焦点的窗口的消息队列;当您释放一个键时,Wi

17、ndows把WM_KEYUP或者WM_SYSKEYUP消息放入消息队列中。键按下键释放非系统键WM_KEYDOWNWM_KEYUP系统键WM_SYSKEYDOWNWM_SYSKEYUP通常“down(按下)”和“up(放开)”消息总是成对出现的。不过,如果您按住一个键使得自动重复功能生效了,那么当该键最后被释放时,Windows会给窗口消息处理程序发送一系列WM_KEYDOWN(或者WM_SYSKEYDOWN)消息和一个WM_KEYUP(或者WM_SYSKEYUP)消息。像所有放入对列的消息一样,按键消息也有时间信息。通过调用GetMessageTime,您可以获得按下或者释放键的相对时间。

18、系统按键与非系统按键WM_SYSKEYDOWN和WM_SYSKEYUP中的“SYS”代表“系统”,它表示该按键对Windows系统比对应用程序更加重要。WM_SYSKEYDOWN和WM_SYSKEYUP消息经常由与Alt相组合的按键产生,这些按键启动程序菜单或者系统菜单上的选项,或者用于切换活动窗口等系统功能(Alt-Tab或者Alt-Esc),也可以用作系统菜单加速键(Alt键与一个功能键相结合,例如Alt-F4用于关闭应用程序)。程序通常忽略WM_SYSKEYUP和WM_SYSKEYDOWN消息,并将它们传送到DefWindowProc。由于Windows要处理所有Alt键的功能,所以您无

19、需拦截这些消息。您的窗口消息处理程序将最后收到关于这些按键结果(如菜单选择)的其它消息。如果您想在自己的窗口消息处理程序中加上拦截系统按键的程序码,那么在处理这些消息之后再传送到DefWindowProc,Windows就仍然可以将它们用于通常的目的。 虚拟键码虚拟键码保存在WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP消息的wParam参数中。此代码标识按下或释放的键。哈,又是虚拟,您喜欢这个词吗?虚拟指的是假定存在于思想中而不是现实世界中的一些事物,也只有熟练使用DOS汇编语言编写应用程序的程序写作者才有可能指出,为什么对Windows键盘处理如

20、此基本的键码是虚拟的而不是真实的。对于早期的程序写作者来说,真实的键码由实际键盘硬件产生。在Windows文件中将这些键码称为扫描码(scan codes)。在IBM兼容机种上,扫描码16是Q键,17是W键,18是E、19是R,20是T,21是Y等等。这时您会发现,扫描码是依据键盘的实际布局的。Windows开发者认为这些代码过于与设备相关了,于是他们试图通过定义所谓的虚拟键码,以便经由与设备无关的方式处理键盘。其中一些虚拟键码不能在IBM兼容机种上产生,但可能会在其它制造商生产的键盘中找到,或者在未来的键盘上找到。您使用的大多数虚拟键码的名称在WINUSER.H表头文件中都定义为以VK_开头

21、。下表列出了与虚拟键相对应的IBM兼容机种键盘上的键。#define VK_SPACE 0x20#define VK_PRIOR 0x21#define VK_NEXT 0x22#define VK_END 0x23#define VK_HOME 0x24#define VK_LEFT 0x25#define VK_UP 0x26#define VK_RIGHT 0x27#define VK_DOWN 0x28#define VK_F1 0x70#define VK_F2 0x71#define VK_F3 0x72#define VK_F4 0x73#define VK_F5 0x74#de

22、fine VK_F6 0x75#define VK_F7 0x76#define VK_F8 0x77#define VK_F9 0x78#define VK_F10 0x79如上表,我们表示向上箭头键,可以用VK_UP,F10可以用VK_F10。 组合键单个键可以用虚拟键码表示,那么,我们如何表示组合键,如Alt+F1呢?如何知道是否按下了位移键(Shift、Ctrl和Alt)或开关键(Caps Lock、Num Lock和Scroll Lock)呢?答案是:调用GetKeyState函数。其原型为:SHORT GetKeyState( int nVirtKey); 其返回值指明了nVirt

23、Key这个虚拟键码对应的键的状态,如果返回值的高位为1,该键就是按下的,否则就是松开的;如果返回值的低位为1,表明该键是锁定的,否则就不是锁定状态,如大写键,数字键,滚动键。例如:SHORT nState = GetKeyState (VK_SHIFT); /sizeof(short) = 2个字节=16位BOOL bIsPressed = nState & 0x8000; / nState 15可以用bIsPressed来判断SHIFT键是否被按下了。SHORT nState = GetKeyState (VK_ CAPITAL);BOOL bIsToggled = nState & 0x0

24、001; / nState15可以用bIsToggled来判断大写键是否锁定状态。通常,您在使用GetKeyState时,会带有虚拟键码VK_SHIFT、VK_CONTROL和VK_MENU(在说明Alt键时调用)。使用GetKeyState时,您也可以用下面的识别字来确定按下的Shift、Ctrl或Alt键是左边的还是右边的:VK_LSHIFT、VK_RSHIFT、VK_LCONTROL、VK_RCONTROL、VK_LMENU、VK_RMENU。这些识别字只用于GetKeyState和GetAsyncKeyState。如:下面的例子判断Alt+F1 case WM_KEYDOWN: swi

25、tch (wParam) case VK_F1: if (GetKeyState(VK_ALT)MBCS-Unicode编码如今,Windows操作系统的使用已经遍及世界,为使Windows操作系统及运行在操作系统上的应用软件更容易被世界所有国籍的用户所使用,需要使Windows及运行在其上的应用程序本地化,即使用用户本民族语言的字符集。字符集的不统一使得本地化变得很困难,这需要对操作系统的源代码根据不同的字符集进行全方位的定制,还要提供API的不同字符集的版本,此外,编写应用软件也要针对不同的字符集开发不同的版本。在欧美地区,多数使用ASCII编码,字符串被当作一系列以0结尾的单字节字符,这

26、非常自然。使用strlen函数时,会返回一个以0结尾的单字节字符数组中的字符数。单字节字符集包含256个符号。但是有些语言,如汉字,字符集的符号很多,而单字节字符集最多只能提供256个符号,这是远远不够的。因此,创立了双字节字符集DBCS(double byte character set)来支持这些语言。在双字节字符集中,字符串中的每个字符由1或2字节组成,因此也叫多字节字符集MBCS(multiple byte character set)。由于有些字符是1字节宽,而有些是2字节宽,这使得操作多字节字符串变得非常麻烦,使用strlen操作多字节字符串不能得到字符串的真正长度,而只能得到字符的字节数。为了更方便地支持软件的国际化,便创立了一个宽字节的字符集标准:Unicode。Unicode这个名称来自三个主要特征:通用(universal)它解决了世界语言的需要;统一(uniform)它为了保证效率而使用固定长度的代码;唯一(unique)字符代码的重复将到了最低点。Unicode字符串中所有字符都是16位的(2个字节),没有象MBCS字符那

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1