Windows编程概念及框架

来源:互联网 发布:移动信号检测软件 编辑:程序博客网 时间:2024/05/22 03:36
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.寄送:寄送的消息不会被立即处理,而是被放到一个先进先出的队列中,一直等到应用程序空闲时才会被处理,函数放置消息后立即返回。

     
0 0
原创粉丝点击