您的位置:首页 > 编程语言

Windows编程概念及框架

2016-02-14 13:59 381 查看
1、控制台程序与Windows窗口程序比较

在控制台程序中,入口函数是 main 函数,预处理宏为_CONSOLE,用于在预处理时包含控制台程序用到的一些宏或头文件;
在Windows窗口程序中,入口函数是 WinMain 函数,预处理宏为_WINDOWS;
Windows系统为开发者提供了很多函数,这些函数被包含在Windows软件开发工具包(全称:Software Development Kit,
简称:SDK)。而这些函数也被称为应用程序编程接口(全称:Application Programming Interface,简称:API)
在每一个 Windows程序中,我们都会用到一个头文件Windows.h,这个头文件其实是一个综合性的头文件,它包含很多在Windows编程中经常要用到的头文件

2、Unicode 与 ASCII

ASCII 是用来表示英文字符的一种编码规范。每个ASCII 字符占一个字节,可以容纳的最大字符数为255。由于其所容纳字符范围不够用,故而产生了一种新的编码规范 Unicode ,占用两个字节,可容纳65536个字符。在Unicode里,所有字符都按一个字符处理,它们都有一个唯一的Unicode 码。使用Unicode 编码可以使得我们的工程同时支持多种语言,更加国际化,另外,在Windows系统底层的字符串其实都是以Unicode编码形式进行操作,故而,在实际开发过程中使用Unicode编码形式编写代码将会使程序运行效率得到提升。

首先,我们看看Windows编程中与编码关系最大的字符串,从两种基本字符类型开始:
char(ASCII) 和 wchar_t(Unicode)
为了书写方便,Windows将其类型重定义为:
typedef char CHAR
typedef wchar_t WCHAR
又考虑到兼容性,Windows定义了TCHAR数据类型:
#ifdef UNICODE
typedef WCHAR TCHAR
#else
typedef CHAR TCHAR
#endif
我们在定义字符串的时候,可以用_T、TEXT、_TEXT宏保证兼容性。使得在ASCII 环境下,采用 ASCII 编码方式;而在Unicode 环境下,采用Unicode编码方式。这样无论是在ASCII 环境,还是Unicode 环境都可以适用了。下面是三种方式的对比:
char szStr1[ ] = "str1"; // ASCII 方式
WCHAR szStr2[ ] = L"str2"; // Unicode 方式
TCHAR szStr3[ ] = _T("str3"); // 兼容方式
那么,当szStr3在定义了Unicode 时会被解释成Unicode形式,未定义时则解释为ASCII 形式,str1总是被解释成ASCII 形式,str2总是被解释为Unicode 形式。

接下来看看Windows编程中的字符串指针类型:

LPSTR:指向以0结尾的ASCII 字符串的长指针;
LPCSTR:同上,且为 const 指针;
typedef CHAR* LPSTR
typedef const CHAR* LPCSTR
LPWSTR:指向以0结尾的UNICODE 字符串的长指针;
LPCWSTR:同上,且为 const 指针;
typedef WCHAR* LPWSTR
typedef const WCHAR* LPCWSTR
LPTSTR:指向以0结尾的ASCII或UNICODE 字符串的长指针;
LPCTSTR:同上,且为 const指针;
typedef TCHAR* LPTSTR
#ifdef UNICODE
typedef LPWSTR LPTSTR
#else
typedef LPSTR LPTSTR
#endif
typedef const TCHAR* LPCTSTR
#ifdef UNICODE
typedef LPCWSTR LPCTSTR
#else
typedef LPCSTR LPCTSTR
#endif

3、安全版字符串函数

我们了解到,在Windows中,不仅仅只是字符分ASCII 版和UNICOD 版,在API 函数中我们同样可以经常见到区分 ASCII 和UNICODE 版的函数,也就是所谓的“A”版和“W”版的API函数。不过有一点我么必须清楚,不管我们在实际编程中使用的是ASCII 还是UNICODE版,最终都是用UNICODE版来实现,其中的ASCII版的API只是一个转换层,负责分配内存,然后将ASCII版转换为UNICODE版。要验证这一点不难,我们只需编写一个简单的Windows程序,并在程序中调用一个比较常见的ASCII版API函数,生成可执行文件后将其在OD中打开,搜索到这个API,跟进这个函数直到其最终实现,即可。
通常,修改字符串的函数都存在一个安全隐患,即目标字符串的缓冲区不够大,导致缓冲区溢出,轻则破坏内存中的数据,被有心人利用时就成了一个严重的安全问题,即缓冲区溢出漏洞。故而,微软提供了能够避免大多数缓冲区溢出的安全版字符串函数,这类函数较我们所熟知的非安全版字符串函数而言,增加了检查缓冲区是否足以容纳结果数据的功能,在调用这类函数时,我们必须提供缓冲区大小(通过_coutof 宏计算)。然后,我们就可以通过检查返回的 error_t 值,只有当返回 S_OK 时才表明函数调用成功。

4、Windows数据类型

所有Windows数据类型都是由C数据类型经过类型重定义得到。如DWORD实质上就是unsigned long 数据类型,32位无符号整形。其定义为:
typedef unsigned long DWORD;
所有Windows数据类型都是通过这种方式在SDK头文件中进行定义的,都来源于标准C数据类型

5、句柄和对象

在Windows中,句柄是和对象一一对应的32位无符号整数值。对象可以映射到唯一的句柄,句柄也可以映射到唯一的对象。
句柄是一个抽象的概念,在作用呢上类似于C++类中的this指针。
在封装背后,需要实现解码,以实现句柄和对象的相互转换。存在以下两种映射方式:
a.全等映射:句柄本身即是指针,映射只是类型转换。如,进程实例句柄,模块句柄,资源句柄等;
b.基于表格的映射:最常见的映射方式,操作系统创建表格,并保存所有要考虑的对象。

6、编程框架

Windows编程的方式是以事件驱动的,即程序流程以事件的发生来控制。我们的重点在于对程序发出/接收的消息进行排序和管理。
也就是说,Windows编程以事件驱动,事件驱动依靠消息循环机制实现。
Windows编程核心思想:在回调函数中处理Windows消息。
回调函数:通过函数指针调用的函数。若将函数指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,称之为回调函数。

创建窗口并处理窗口消息:
a.设计窗口类
b.注册窗口类
c.创建窗口
d.显示刷新窗口
e.循环接收处理消息
f.退出程序

Windows编程要点:
a.创建窗口部分
b.消息循环部分
c.消息回调函数

7、消息机制

消息(Message):指的是Windows系统发给应用程序的一个通告,由系统或应用程序产生,用以通知应用程序某个特定的事件发生了。如:用户单击鼠标或按键都会引发windows系统发送相应的消息。最终处理消息的是应用程序的窗口函数,若程序不进行处理系统将会作出默认处理。
消息标识符的值:
系统保留消息标识符的值在:0x0000~0x03ff(WM_USER-1)。这些值被系统定义消息使用,应用程序不能使用这些值给自己的消息;
应用程序消息标识符的值在:0x0400(WM_USER)~0x7fff。由应用程序自己使用;
0xC000~0xFFFF。用于和其他应用程序通信。
消息种类:
a.窗口消息:由操作系统和控制其他窗口的窗口所使用的消息。
b.命令消息:特殊的窗口消息,处理从一个窗口发送到另一个窗口的用户请求。
c.控件通知消息: 一个窗口内的子控件发生的事件需要通知父窗口,只适用标准的窗口控件,如按钮、编辑框等。
按消息的发送途径分类:
a.队列消息:经系统消息队列,到线程消息队列,再到消息泵,最后到消息回调函数;
b.非队列消息:直接送到消息回调函数。

常用将消息发送到窗口的方式:
a.发送:发送的消息会被立即处理,处理完毕后函数才返回;
b.寄送:寄送的消息不会被立即处理,而是被放到一个先进先出的队列中,一直等到应用程序空闲时才会被处理,函数放置消息后立即返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: