C语言内存讲解

堆和栈的区别

  1.申请方式

  (1)栈(satck):由系统自动分配。例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间。

  (2)堆(heap):需程序员自己申请(调用malloc,realloc,calloc),并指明大小,并由程序员进行释放。容易产生memory leak.

  eg:char  p;

  p = (char *)malloc(sizeof(char));

  但是,p本身是在栈中。

  2.申请大小的限制

  (1)栈:在windows下栈是向底地址扩展的数据结构,是一块连续的内存区域(它的生长方向与内存的生长方向相反)。栈的大小是固定的。如果申请的空间超过栈的剩余空间时,将提示overflow。

  (2)堆:堆是高地址扩展的数据结构(它的生长方向与内存的生长方向相同),是不连续的内存区域。这是由于系统使用链表来存储空闲内存地址的,自然是不连续的,而链表的遍历方向是由底地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。

  3.系统响应:

  (1)栈:只要栈的空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

  (2)堆:首先应该知道操作系统有一个记录空闲内存地址的链表,但系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的free语句才能正确的释放本内存空间。另外,找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

  说明:对于堆来讲,对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,

  4.申请效率

  (1)栈由系统自动分配,速度快。但程序员是无法控制的

  (2)堆是由malloc分配的内存,一般速度比较慢,而且容易产生碎片,不过用起来最方便。

  5.堆和栈中的存储内容

  (1)栈:在函数调用时,第一个进栈的主函数中后的下一条语句的地址,然后是函数的各个参数,参数是从右往左入栈的,然后是函数中的局部变量。注:静态变量是不入栈的。

  当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续执行。

  (2)堆:一般是在堆的头部用一个字节存放堆的大小。

  6.存取效率

  (1)堆:char *s1=”hellow tigerjibo”;是在编译是就确定的

  (2)栈:char s1[]=”hellow tigerjibo”;是在运行时赋值的;用数组比用指针速度更快一些,指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上读取。

  补充:

  栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

  7.分配方式:

  (1)堆都是动态分配的,没有静态分配的堆。

  (2)栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的。它的动态分配是由编译器进行释放,无需手工实现。

C语言 malloc 工作机制

void *malloc (size_t stSize);

  该函数在内存的动态存储区中分配 stSize 连续空间,返回值是一个指向所分配的连续存储域的起始地址的指针。

  void free(void *firstbyte);

  如果给定一个由先前的 malloc 返回的指针,那么该函数会将分配的空间归还给进程的“空闲空间”。

  malloc 工作机制:

  malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。

C语言中的时间函数及使用实例

#include           /* NULL         */

#include           /* ctime, asctime      */

main()

{

time_t now;  

 /* define 'now'. time_t is probably

  * a typedef */

/* Calender time is the number of

  * seconds since 1/1/1970    */

now = time((time_t *)NULL); 

/* Get the system time and put it

  * into 'now' as 'calender time' */

printf("%s", ctime(&now));

 /* Format data in 'now'

  * NOTE that 'ctime' inserts a

  * '\n' */

/*********************************************************************/

/* Here is another way to extract the time/date information */

time(&now);

printf("%s", ctime(&now));  /* Format data in 'now'  */

/*********************************************************************/

{

struct tm *l_time;

l_time = localtime(&now); 

/* Convert 'calender time' to

  * 'local time' - return a pointer

  * to the 'tm' structure. localtime

  * reserves the storage for us. */

printf("%s", asctime(l_time));

}

/*********************************************************************/

time(&now);

printf("%s", asctime(localtime( &now  )));

/*********************************************************************/

{

struct tm *l_time;

char string[20];

time(&now);

l_time = localtime(&now);

strftime(string, sizeof string, "%d-%b-%y\n", l_time);

printf("%s", string);

}

}

内存管理

欢迎进入内存这片雷区。伟大的Bill Gates 曾经失言:

640K ought to be enough for everybody

— Bill Gates 1981

程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本章的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。

7.1内存分配方式
内存分配方式有三种:

(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

7.2常见的内存错误及其对策
发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。

常见的内存错误及其对策如下:

u 内存分配未成功,却使用了它。

编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

u 内存分配虽然成功,但是尚未初始化就引用它。

犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。

内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

u 内存分配成功并且已经初始化,但操作越过了内存的边界。

例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

u 忘记了释放内存,造成内存泄露。

含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。

动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。

u 释放了内存却继续使用它。

有三种情况:

(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

l 【规则7-2-1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。

l 【规则7-2-2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

l 【规则7-2-3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

l 【规则7-2-4】动态内存的申请与释放必须配对,防止内存泄漏。

l 【规则7-2-5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

7.3指针与数组的对比
C++/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。

指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

下面以字符串为例比较指针与数组的特性。

示例7-3-1中,字符数组a的容量是6个字符,其内容为hello\0。a的内容可以改变,如a[0]= ‘X’。指针p指向常量字符串“world”(位于静态存储区,内容为world\0),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]= ‘X’有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。

char a[] = “hello”;

a[0] = ‘X’;

cout << a << endl;

char *p = “world”; // 注意p指向常量字符串

p[0] = ‘X’; // 编译器不能发现该错误

cout << p << endl;

示例7-3-1 修改数组和指针的内容

7.3.2 内容复制与比较

不能对数组名进行直接复制与比较。示例7-3-2中,若想把数组a的内容复制给数组b,不能用语句 b = a ,否则将产生编译错误。应该用标准库函数strcpy进行复制。同理,比较b和a的内容是否相同,不能用if(b==a) 来判断,应该用标准库函数strcmp进行比较。

语句p = a 并不能把a的内容复制指针p,而是把a的地址赋给了p。要想复制a的内容,可以先用库函数malloc为p申请一块容量为strlen(a)+1个字符的内存,再用strcpy进行字符串复制。同理,语句if(p==a) 比较的不是内容而是地址,应该用库函数strcmp来比较。

// 数组…

char a[] = "hello";

char b[10];

strcpy(b, a); // 不能用 b = a;

if(strcmp(b, a) == 0) // 不能用 if (b == a)



//
指针…

int len = strlen(a);

char *p = (char *)malloc(sizeof(char)*(len+1));

strcpy(p,a); // 不要用 p = a;

if(strcmp(p, a) == 0) // 不要用 if (p == a)

示例7-3-2 数组和指针的内容复制与比较

用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了’\0’)。指针p指向a,但是sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。

注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。

char a[] = "hello world";

char *p = a;

cout<< sizeof(a) << endl; // 12字节

cout<< sizeof(p) << endl; // 4字节

示例7-3-3(a) 计算数组和指针的内存容量

void Func(char a[100])

{

cout<< sizeof(a) << endl; // 4字节而不是100字节

}

示例7-3-3(b) 数组退化为指针

7.4指针参数是如何传递内存的?
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?

void GetMemory(char *p, int num)

{

p = (char *)malloc(sizeof(char) * num);

}

void Test(void)

{

char *str = NULL;

GetMemory(str, 100); // str 仍然为 NULL

strcpy(str, "hello"); // 运行错误

}

示例7-4-1 试图用指针参数申请动态内存

毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。

如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例7-4-2。

void GetMemory2(char **p, int num)

{

*p = (char *)malloc(sizeof(char) * num);

}

void Test2(void)

{

char *str = NULL;

GetMemory2(&str, 100); // 注意参数是 &str,而不是str

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

示例7-4-2用指向指针的指针申请动态内存

由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例7-4-3。

char *GetMemory3(int num)

{

char *p = (char *)malloc(sizeof(char) * num);

return p;

}

void Test3(void)

{

char *str = NULL;

str = GetMemory3(100);

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

示例7-4-3 用函数返回值来传递动态内存

用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例7-4-4。

char *GetString(void)

{

char p[] = "hello world";

return p; // 编译器将提出警告

}

void Test4(void)

{

char *str = NULL;

str = GetString(); // str 的内容是垃圾

cout<< str << endl;

}

示例7-4-4 return语句返回指向“栈内存”的指针

用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello world”而是垃圾。

如果把示例7-4-4改写成示例7-4-5,会怎么样?

char *GetString2(void)

{

char *p = "hello world";

return p;

}

void Test5(void)

{

char *str = NULL;

str = GetString2();

cout<< str << endl;

}

示例7-4-5 return语句返回常量字符串

函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。

7.5 free和delete把指针怎么啦?
7.7 杜绝“野指针”
“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。

野指针”的成因主要有两种:

(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如

char *p = NULL;

char *str = (char *) malloc(100);

(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。参见7.5节。

(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

class A

{

public:

void Func(void){ cout << “Func of class A” << endl; }

};

void Test(void)

{

A *p;

{

A a;

p = &a; // 注意 a 的生命期

}

p->Func(); // p是“野指针”

}

函数Test在执行语句p->Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。但奇怪的是我运行这个程序时居然没有出错,这可能与编译器有关。

7.8 有了malloc/free为什么还要new/delete ?
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

我们先看一看malloc/free和new/delete如何实现对象的动态内存管理,见示例7-8。

class Obj

{

public :

Obj(void){ cout << “Initialization” << endl; }

~Obj(void){ cout << “Destroy” << endl; }

void Initialize(void){ cout << “Initialization” << endl; }

void Destroy(void){ cout << “Destroy” << endl; }

};

void UseMallocFree(void)

{

Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存

a->Initialize(); // 初始化

//…

a->Destroy(); // 清除工作

free(a); // 释放内存

}

void UseNewDelete(void)

{

Obj *a = new Obj; // 申请动态内存并且初始化

//…

delete a; // 清除并且释放内存

}

示例7-8 用malloc/free和new/delete如何实现对象的动态内存管理

类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。

所以我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。

如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。

7.9 内存耗尽怎么办?
如果在申请动态内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存申请失败。通常有三种方式处理“内存耗尽”问题。

(1)判断指针是否为NULL,如果是则马上用return语句终止本函数。例如:

void Func(void)

{

A *a = new A;

if(a == NULL)

{

return;

}

}

(2)判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。例如:

void Func(void)

{

A *a = new A;

if(a == NULL)

{

cout << “Memory Exhausted” << endl;

exit(1);

}

}

(3)为new和malloc设置异常处理函数。例如Visual C++可以用_set_new_hander函数为new设置用户自己定义的异常处理函数,也可以让malloc享用与new相同的异常处理函数。详细内容请参考C++使用手册。

上述(1)(2)方式使用最普遍。如果一个函数内有多处需要申请动态内存,那么方式(1)就显得力不从心(释放内存很麻烦),应该用方式(2)来处理。

很多人不忍心用exit(1),问:“不编写出错处理程序,让操作系统自己解决行不行?”

不行。如果发生“内存耗尽”这样的事情,一般说来应用程序已经无药可救。如果不用exit(1) 把坏程序杀死,它可能会害死操作系统。道理如同:如果不把歹徒击毙,歹徒在老死之前会犯下更多的罪。

有一个很重要的现象要告诉大家。对于32位以上的应用程序而言,无论怎样使用malloc与new,几乎不可能导致“内存耗尽”。我在Windows 98下用Visual C++编写了测试程序,见示例7-9。这个程序会无休止地运行下去,根本不会终止。因为32位操作系统支持“虚存”,内存用完了,自动用硬盘空间顶替。我只听到硬盘嘎吱嘎吱地响,Window 98已经累得对键盘、鼠标毫无反应。

我可以得出这么一个结论:对于32位以上的应用程序,“内存耗尽”错误处理程序毫无用处。这下可把Unix和Windows程序员们乐坏了:反正错误处理程序不起作用,我就不写了,省了很多麻烦。

我不想误导读者,必须强调:不加错误处理将导致程序的质量很差,千万不可因小失大。

void main(void)

{

float *p = NULL;

while(TRUE)

{

p = new float[1000000];

cout << “eat memory” << endl;

if(p==NULL)

exit(1);

}

}

示例7-9试图耗尽操作系统的内存

7.10 malloc/free 的使用要点
函数malloc的原型如下:

void * malloc(size_t size);

用malloc申请一块长度为length的整数类型的内存,程序如下:

int *p = (int *) malloc(sizeof(int) * length);

我们应当把注意力集中在两个要素上:“类型转换”和“sizeof”。

u malloc返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的指针类型。

u malloc函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。我们通常记不住int, float等数据类型的变量的确切字节数。例如int变量在16位系统下是2个字节,在32位下是4个字节;而float变量在16位系统下是4个字节,在32位下也是4个字节。最好用以下程序作一次测试:

cout << sizeof(char) << endl;

cout << sizeof(int) << endl;

cout << sizeof(unsigned int) << endl;

cout << sizeof(long) << endl;

cout << sizeof(unsigned long) << endl;

cout << sizeof(float) << endl;

cout << sizeof(double) << endl;

cout << sizeof(void *) << endl;

在malloc的“()”中使用sizeof运算符是良好的风格,但要当心有时我们会昏了头,写出 p = malloc(sizeof(p))这样的程序来。

u 函数free的原型如下:

void free( void * memblock );

为什么free函数不象malloc函数那样复杂呢?这是因为指针p的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存。如果p是NULL指针,那么free对p无论操作多少次都不会出问题。如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。

 7.11 new/delete 的使用要点
运算符new使用起来要比函数malloc简单得多,例如:

int *p1 = (int *)malloc(sizeof(int) * length);

int *p2 = new int[length];

这是因为new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new的语句也可以有多种形式。例如

class Obj

{

public :

Obj(void); // 无参数的构造函数

Obj(int x); // 带一个参数的构造函数

}

void Test(void)

{

Obj *a = new Obj;

Obj *b = new Obj(1); // 初值为1

delete a;

delete b;

}

如果用new创建对象数组,那么只能使用对象的无参数构造函数。例如

Obj *objects = new Obj[100]; // 创建100个动态对象

不能写成

Obj *objects = new Obj[100](1);// 创建100个动态对象的同时赋初值1

在用delete释放对象数组时,留意不要丢了符号‘[]’。例如

delete []objects; // 正确的用法

delete objects; // 错误的用法

后者相当于delete objects[0],漏掉了另外99个对象。

7.12 一些心得体会
我认识不少技术不错的C++/C程序员,很少有人能拍拍胸脯说通晓指针与内存管理(包括我自己)。我最初学习C语言时特别怕指针,导致我开发第一个应用软件(约1万行C代码)时没有使用一个指针,全用数组来顶替指针,实在蠢笨得过分。躲避指针不是办法,后来我改写了这个软件,代码量缩小到原先的一半。

我的经验教训是:

(1)越是怕指针,就越要使用指针。不会正确使用指针,肯定算不上是合格的程序员。

(2)必须养成“使用调试器逐步跟踪程序”的习惯,只有这样才能发现问题的本质。

1. API之网络函数 

WNetAddConnection 创建同一个网络资源的永久性连接 
WNetAddConnection2 创建同一个网络资源的连接 
WNetAddConnection3 创建同一个网络资源的连接 
WNetCancelConnection 结束一个网络连接 
WNetCancelConnection2 结束一个网络连接 
WNetCloseEnum 结束一次枚举操作 
WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接 
WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接 
WNetEnumResource 枚举网络资源 
WNetGetConnection 获取本地或已连接的一个资源的网络名称 
WNetGetLastError 获取网络错误的扩展错误信息 
WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称 
WNetGetUser 获取一个网络资源用以连接的名字 
WNetOpenEnum 启动对网络资源进行枚举的过程 

2. API之消息函数 

BroadcastSystemMessage 将一条系统消息广播给系统中所有的顶级窗口 
GetMessagePos 取得消息队列中上一条消息处理完毕时的鼠标指针屏幕位置 
GetMessageTime 取得消息队列中上一条消息处理完毕时的时间 
PostMessage 将一条消息投递到指定窗口的消息队列 
PostThreadMessage 将一条消息投递给应用程序 
RegisterWindowMessage 获取分配给一个字串标识符的消息编号 
ReplyMessage 答复一个消息 
SendMessage 调用一个窗口的窗口函数,将一条消息发给那个窗口 
SendMessageCallback 将一条消息发给窗口 
SendMessageTimeout 向窗口发送一条消息 
SendNotifyMessage 向窗口发送一条消息 

3. API之文件处理函数 

CloseHandle 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等 
CompareFileTime 对比两个文件的时间 
CopyFile 复制文件 
CreateDirectory 创建一个新目录 
CreateFile 打开和创建文件、管道、邮槽、通信服务、设备以及控制台 
CreateFileMapping 创建一个新的文件映射对象 
DeleteFile 删除指定文件 
DeviceIoControl 对设备执行指定的操作 
DosDateTimeToFileTime DOS日期和时间值转换成一个 win32 FILETIME  
FileTimeToDosDateTime 将一个 win32 FILETIME 值转换成DOS日期和时间值 
FileTimeToLocalFileTime 将一个FILETIME结构转换成本地时间 
FileTimeToSystemTime 根据一个FILETIME结构的内容,装载一个SYSTEMTIME结构 
FindClose 关闭由FindFirstFile函数创建的一个搜索句柄 
FindFirstFile 根据文件名查找文件 
FindNextFile 根据调用FindFirstFile函数时指定的一个文件名查找下一个文件 
FlushFileBuffers 针对指定的文件句柄,刷新内部文件缓冲区 
FlushViewOfFile 将写入文件映射缓冲区的所有数据都刷新到磁盘 
GetBinaryType 判断文件是否可以执行 
GetCompressedFileSize 判断一个压缩文件在磁盘上实际占据的字节数 
GetCurrentDirectory 在一个缓冲区中装载当前目录 
GetDiskFreeSpace 获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量 
GetDiskFreeSpaceEx 获取与一个磁盘的组织以及剩余空间容量有关的信息 
GetDriveType 判断一个磁盘驱动器的类型 
GetExpandedName 取得一个压缩文件的全名 
GetFileAttributes 判断指定文件的属性 
GetFileInformationByHandle 这个函数提供了获取文件信息的一种机制 
GetFileSize 判断文件长度 
GetFileTime 取得指定文件的时间信息 
GetFileType 在给出文件句柄的前提下,判断文件类型 
GetFileVersionInfo 从支持版本标记的一个模块里获取文件版本信息 
GetFileVersionInfoSize 针对包含了版本资源的一个文件,判断容纳文件版本信息需要一个多大的缓冲区 
GetFullPathName 获取指定文件的完整路径名 
GetLogicalDrives 判断系统中存在哪些逻辑驱动器字母 
GetLogicalDriveStrings 获取一个字串,其中包含了当前所有逻辑驱动器的根驱动器路径 
GetOverlappedResult 判断一个重叠操作当前的状态 
GetPrivateProfileInt 为初始化文件(.ini文件)中指定的条目获取一个整数值 
GetPrivateProfileSection 获取指定小节(在.ini文件中)所有项名和值的一个列表 
GetPrivateProfileString 为初始化文件中指定的条目取得字串 
GetProfileInt 取得win.ini初始化文件中指定条目的一个整数值 
GetProfileSection 获取指定小节(在win.ini文件中)所有项名和值的一个列表 
GetProfileString win.ini初始化文件中指定的条目取得字串 
GetShortPathName 获取指定文件的短路径名 
GetSystemDirectory 取得Windows系统目录(即System目录)的完整路径名 
GetTempFileName 这个函数包含了一个临时文件的名字,它可由应用程序使用 
GetTempPath 获取为临时文件指定的路径 
GetVolumeInformation 获取与一个磁盘卷有关的信息 
GetWindowsDirectory 获取Windows目录的完整路径名 
hread 参考lread 
hwrite 参考lwrite函数 
lclose 关闭指定的文件 
lcreat 创建一个文件 
llseek 设置文件中进行读写的当前位置 
LockFile 锁定文件的某一部分,使其不与其他应用程序共享 
LockFileEx LockFile相似,只是它提供了更多的功能 
lopen 以二进制模式打开指定的文件 
lread 将文件中的数据读入内存缓冲区 
lwrite 将数据从内存缓冲区写入一个文件 
LZClose 关闭由LZOpenFile LZInit函数打开的一个文件 
LZCopy 复制一个文件 
LZInit 这个函数用于初始化内部缓冲区 
LZOpenFile 该函数能执行大量不同的文件处理,而且兼容于压缩文件 
LZRead 将数据从文件读入内存缓冲区 
LZSeek 设置一个文件中进行读写的当前位置 
MapViewOfFile 将一个文件映射对象映射到当前应用程序的地址空间 
MoveFile 移动文件 
OpenFile 这个函数能执行大量不同的文件操作 
OpenFileMapping 打开一个现成的文件映射对象 
QueryDosDevice Windows NT中,DOS设备名会映射成NT系统设备名。该函数可判断当前的设备映射情况 
ReadFile 从文件中读出数据 
ReadFileEx ReadFile相似,只是它只能用于异步读操作,并包含了一个完整的回调 
RegCloseKey 关闭系统注册表中的一个项(或键) 
RegConnectRegistry 访问远程系统的部分注册表 
RegCreateKey 在指定的项下创建或打开一个项 
RegCreateKeyEx 在指定项下创建新项的更复杂的方式。在Win32环境中建议使用这个函数 
RegDeleteKey 删除现有项下方一个指定的子项 
RegDeleteValue 删除指定项下方的一个值 
RegEnumKey 枚举指定项的子项。在Win32环境中应使用RegEnumKeyEx 
RegEnumKeyEx 枚举指定项下方的子项 
RegEnumValue 枚举指定项的值 
RegFlushKey 将对项和它的子项作出的改动实际写入磁盘 
RegGetKeySecurity 获取与一个注册表项有关的安全信息 
RegLoadKey 从以前用RegSaveKey函数创建的一个文件里装载注册表信息 
RegNotifyChangeKeyValue 注册表项或它的任何一个子项发生变化时,用这个函数提供一种通知机制 
RegOpenKey 打开一个现有的注册表项 
RegOpenKeyEx 打开一个现有的项。在win32下推荐使用这个函数 
RegQueryInfoKey 获取与一个项有关的信息 
RegQueryValue 取得指定项或子项的默认(未命名)值 
RegQueryValueEx 获取一个项的设置值 
RegReplaceKey 用一个磁盘文件保存的信息替换注册表信息;并创建一个备份,在其中包含当前注册表信息 
RegRestoreKey 从一个磁盘文件恢复注册表信息 
RegSaveKey 将一个项以及它的所有子项都保存到一个磁盘文件 
RegSetKeySecurity 设置指定项的安全特性 
RegSetValue 设置指定项或子项的默认值 
RegSetValueEx 设置指定项的值 
RegUnLoadKey 卸载指定的项以及它的所有子项 
RemoveDirectory 删除指定目录 
SearchPath 查找指定文件 
SetCurrentDirectory 设置当前目录 
SetEndOfFile 针对一个打开的文件,将当前文件位置设为文件末尾 
SetFileAttributes 设置文件属性 
SetFilePointer 在一个文件中设置当前的读写位置 
SetFileTime 设置文件的创建、访问及上次修改时间 
SetHandleCount 这个函数不必在win32下使用;即使使用,也不会有任何效果 
SetVolumeLabel 设置一个磁盘的卷标(Label 
SystemTimeToFileTime 根据一个FILETIME结构的内容,载入一个SYSTEMTIME结构 
UnlockFile 解除对一个文件的锁定 
UnlockFileEx 解除对一个文件的锁定 
UnmapViewOfFile 在当前应用程序的内存地址空间解除对一个文件映射对象的映射 
VerFindFile 用这个函数决定一个文件应安装到哪里 
VerInstallFile 用这个函数安装一个文件 
VerLanguageName 这个函数能根据16位语言代码获取一种语言的名称 
VerQueryValue 这个函数用于从版本资源中获取信息 
WriteFile 将数据写入一个文件 
WriteFileEx WriteFile类似,只是它只能用于异步写操作,并包括了一个完整的回调 
WritePrivateProfileSection 为一个初始化文件(.ini)中指定的小节设置所有项名和值 
WritePrivateProfileString 在初始化文件指定小节内设置一个字串 
WriteProfileSection Win.ini初始化文件中一个指定的小节设置所有项名和值 
WriteProfileString Win.ini初始化文件指定小节内设置一个字串 

4. API之打印函数 
AbortDoc 取消一份文档的打印 
AbortPrinter 删除与一台打印机关联在一起的缓冲文件 
AddForm 为打印机的表单列表添加一个新表单 
AddJob 用于获取一个有效的路径名,以便用它为作业创建一个后台打印文件。它也会为作业分配一个作业编号 
AddMonitor 为系统添加一个打印机监视器 
AddPort 启动添加端口对话框,允许用户在系统可用端口列表中加入一个新端口 
AddPrinter 在系统中添加一台新打印机 
AddPrinterConnection 连接指定的打印机 
AddPrinterDriver 为指定的系统添加一个打印驱动程序 
AddPrintProcessor 为指定的系统添加一个打印处理器 
AddPrintProvidor 为系统添加一个打印供应商 
AdvancedDocumentProperties 启动打印机文档设置对话框 
ClosePrinter 关闭一个打开的打印机对象 
ConfigurePort 针对指定的端口,启动一个端口配置对话框 
ConnectToPrinterDlg 启动连接打印机对话框,用它同访问网络的打印机连接 
DeleteForm 从打印机可用表单列表中删除一个表单 
DeleteMonitor 删除指定的打印监视器 
DeletePort 启动删除端口对话框,允许用户从当前系统删除一个端口 
DeletePrinter 将指定的打印机标志为从系统中删除 
DeletePrinterConnection 删除与指定打印机的连接 
DeletePrinterDriver 从系统删除一个打印机驱动程序 
DeletePrintProcessor 从指定系统删除一个打印处理器 
DeletePrintProvidor 从系统中删除一个打印供应商 
DeviceCapabilities 利用这个函数可获得与一个设备的能力有关的信息 
DocumentProperties 打印机配置控制函数 
EndDocAPI 结束一个成功的打印作业 
EndDocPrinter 在后台打印程序的级别指定一个文档的结束 
EndPage 用这个函数完成一个页面的打印,并准备设备场景,以便打印下一个页 
EndPagePrinter 指定一个页在打印作业中的结尾 
EnumForms 枚举一台打印机可用的表单 
EnumJobs 枚举打印队列中的作业 
EnumMonitors 枚举可用的打印监视器 
EnumPorts 枚举一个系统可用的端口 
EnumPrinterDrivers 枚举指定系统中已安装的打印机驱动程序 
EnumPrinters 枚举系统中安装的打印机 
EnumPrintProcessorDatatypes 枚举由一个打印处理器支持的数据类型 
EnumPrintProcessors 枚举系统中可用的打印处理器 
Escape 设备控制函数 
FindClosePrinterChangeNotification 关闭用FindFirstPrinterChangeNotification函数获取的一个打印机通告对象 
FindFirstPrinterChangeNotification 创建一个新的改变通告对象,以便我们注意打印机状态的各种变化 
FindNextPrinterChangeNotification 用这个函数判断触发一次打印机改变通告信号的原因 
FreePrinterNotifyInfo 释放由FindNextPrinterChangeNotification函数分配的一个缓冲区 
GetForm 取得与指定表单有关的信息 
GetJob 获取与指定作业有关的信息 
GetPrinter 取得与指定打印机有关的信息 
GetPrinterData 为打印机设置注册表配置信息 
GetPrinterDriver 针对指定的打印机,获取与打印机驱动程序有关的信息 
GetPrinterDriverDirectory 判断指定系统中包含了打印机驱动程序的目录是什么 
GetPrintProcessorDirectory 判断指定系统中包含了打印机处理器驱动程序及文件的目录 
OpenPrinter 打开指定的打印机,并获取打印机的句柄 
PrinterMessageBox 在拥有指定打印作业的系统上显示一个打印机出错消息框 
PrinterProperties 启动打印机属性对话框,以便对打印机进行配置 
ReadPrinter 从打印机读入数据 
ResetDC 重设一个设备场景 
ResetPrinter 改变指定打印机的默认数据类型及文档设置 
ScheduleJob 提交一个要打印的作业 
SetAbortProc Windows指定取消函数的地址 
SetForm 为指定的表单设置信息 
SetJob 对一个打印作业的状态进行控制 
SetPrinter 对一台打印机的状态进行控制 
SetPrinterData 设置打印机的注册表配置信息 
StartDoc 开始一个打印作业 
StartDocPrinter 在后台打印的级别启动一个新文档 
StartPage 打印一个新页前要先调用这个函数 
StartPagePrinter 在打印作业中指定一个新页的开始 
WritePrinter 将发送目录中的数据写入打印机 

5. API之文本和字体函数 

AddFontResource Windows系统中添加一种字体资源 
CreateFont 用指定的属性创建一种逻辑字体 
CreateFontIndirect 用指定的属性创建一种逻辑字体 
CreateScalableFontResource 为一种TureType字体创建一个资源文件,以便能用API函数AddFontResource将其加入Windows系统 
DrawText 将文本描绘到指定的矩形中 
DrawTextEx DrawText相似,只是加入了更多的功能 
EnumFontFamilies 列举指定设备可用的字体 
EnumFontFamiliesEx 列举指定设备可用的字体 
EnumFonts 列举指定设备可用的字体 
ExtTextOut 经过扩展的文本描绘函数。也请参考SetTextAlign函数 
GetAspectRatioFilterEx SetMapperFlags要求Windows只选择与设备当前纵横比相符的光栅字体时,本函数可判断纵横比大小 
GetCharABCWidths 判断TureType字体中一个或多个字符的A-B-C大小 
GetCharABCWidthsFloat 查询一种字体中一个或多个字符的A-B-C尺寸 
GetCharacterPlacement 该函数用于了解如何用一个给定的字符显示一个字串 
GetCharWidth 调查字体中一个或多个字符的宽度 
GetFontData 接收一种可缩放字体文件的数据 
GetFontLanguageInfo 返回目前选入指定设备场景中的字体的信息 
GetGlyphOutline 取得TureType字体中构成一个字符的曲线信息 
GetKerningPairs 取得指定字体的字距信息 
GetOutlineTextMetrics 接收与TureType字体内部特征有关的详细信息 
GetRasterizerCaps 了解系统是否有能力支持可缩放的字体 
GetTabbedTextExtent 判断一个字串占据的范围,同时考虑制表站扩充的因素 
GetTextAlign 接收一个设备场景当前的文本对齐标志 
GetTextCharacterExtra 判断额外字符间距的当前值 
GetTextCharset 接收当前选入指定设备场景的字体的字符集标识符 
GetTextCharsetInfo 获取与当前选定字体的字符集有关的详细信息 
GetTextColor 判断当前字体颜色。通常也称为前景色 
GetTextExtentExPoint 判断要填入指定区域的字符数量。也用一个数组装载每个字符的范围信息 
GetTextExtentPoint 判断一个字串的大小(范围) 
GetTextFace 获取一种字体的字样名 
GetTextMetrics 获取与选入一种设备场景的物理字体有关的信息 
GrayString 描绘一个以灰色显示的字串。通常由Windows用于标识禁止状态 
PolyTextOut 描绘一系列字串 
RemoveFontResource Windows系统中删除一种字体资源 
SetMapperFlags Windows对字体进行映射时,可用该函数选择与目标设备的纵横比相符的光栅字体 
SetTextAlign 设置文本对齐方式,并指定在文本输出过程中使用设备场景的当前位置 
SetTextCharacterExtra 描绘文本的时候,指定要在字符间插入的额外间距 
SetTextColor 设置当前文本颜色。这种颜色也称为前景色 
SetTextJustification 通过指定一个文本行应占据的额外空间,可用这个函数对文本进行两端对齐处理 
TabbedTextOut 支持制表站的一个文本描绘函数 
TextOut 文本绘图函数 

6. API之菜单函数 

AppendMenu 在指定的菜单里添加一个菜单项 
CheckMenuItem 复选或撤消复选指定的菜单条目 
CheckMenuRadioItem 指定一个菜单条目被复选成单选项目 
CreateMenu 创建新菜单 
CreatePopupMenu 创建一个空的弹出式菜单 
DeleteMenu 删除指定的菜单条目 
DestroyMenu 删除指定的菜单 
DrawMenuBar 为指定的窗口重画菜单 
EnableMenuItem 允许或禁止指定的菜单条目 
GetMenu 取得窗口中一个菜单的句柄 
GetMenuCheckMarkDimensions 返回一个菜单复选符的大小 
GetMenuContextHelpId 取得一个菜单的帮助场景ID 
GetMenuDefaultItem 判断菜单中的哪个条目是默认条目 
GetMenuItemCount 返回菜单中条目(菜单项)的数量 
GetMenuItemID 返回位于菜单中指定位置处的条目的菜单ID 
GetMenuItemInfo 取得(接收)与一个菜单条目有关的特定信息 
GetMenuItemRect 在一个矩形中装载指定菜单条目的屏幕坐标信息 
GetMenuState 取得与指定菜单条目状态有关的信息 
GetMenuString 取得指定菜单条目的字串 
GetSubMenu 取得一个弹出式菜单的句柄,它位于菜单中指定的位置 
GetSystemMenu 取得指定窗口的系统菜单的句柄 
HiliteMenuItem 控制顶级菜单条目的加亮显示状态 
InsertMenu 在菜单的指定位置处插入一个菜单条目,并根据需要将其他条目向下移动 
InsertMenuItem 插入一个新菜单条目 
IsMenu 判断指定的句柄是否为一个菜单的句柄 
LoadMenu 从指定的模块或应用程序实例中载入一个菜单 
LoadMenuIndirect 载入一个菜单 
MenuItemFromPoint 判断哪个菜单条目包含了屏幕上一个指定的点 
ModifyMenu 改变菜单条目 
RemoveMenu 删除指定的菜单条目 
SetMenu 设置窗口菜单 
SetMenuContextHelpId 设置一个菜单的帮助场景ID 
SetMenuDefaultItem 将一个菜单条目设为默认条目 
SetMenuItemBitmaps 设置一幅特定位图,令其在指定的菜单条目中使用,代替标准的复选符号( 
SetMenuItemInfo 为一个菜单条目设置指定的信息 
TrackPopupMenu 在屏幕的任意地方显示一个弹出式菜单 
TrackPopupMenuEx TrackPopupMenu相似,只是它提供了额外的功能 

7. API之位图、图标和光栅运算函数 
BitBlt 将一幅位图从一个设备场景复制到另一个 
CopyIcon 制作指定图标或鼠标指针的一个副本。这个副本从属于发出调用的应用程序 
CopyImage 复制位图、图标或指针,同时在复制过程中进行一些转换工作 
CreateBitmap 按照规定的格式创建一幅与设备有关位图 
CreateBitmapIndirect 创建一幅与设备有关位图 
CreateCompatibleBitmap 创建一幅与设备有关位图,它与指定的设备场景兼容 
CreateCursor 创建一个鼠标指针 
CreateDIBitmap 根据一幅与设备无关的位图创建一幅与设备有关的位图 
CreateDIBSection 创建一个DIBSection 
CreateIcon 创建一个图标 
CreateIconIndirect 创建一个图标 
DestroyCursor 清除指定的鼠标指针,并释放它占用的所有系统资源 
DestroyIcon 清除图标 
DrawIcon 在指定的位置画一个图标 
DrawIconEx 描绘一个图标或鼠标指针。与DrawIcon相比,这个函数提供了更多的功能 
ExtractAssociatedIcon 判断一个可执行程序或DLL中是否存在图标,或是否有图标与系统注册表中指定的文件存在关联并提取之 
ExtractIcon 判断一个可执行文件或DLL中是否有图标存在,并将其提取出来 
GetBitmapBits 将来自位图的二进制位复制到一个缓冲区 
GetBitmapDimensionEx 取得一幅位图的宽度和高度 
GetDIBColorTable 从选入设备场景的DIBSection中取得颜色表信息 
GetDIBits 将来自一幅位图的二进制位复制到一幅与设备无关的位图里 
GetIconInfo 取得与图标有关的信息 
GetStretchBltMode 判断StretchBlt StretchDIBits函数采用的伸缩模式 
LoadBitmap 从指定的模块或应用程序实例中载入一幅位图 
LoadCursor 从指定的模块或应用程序实例中载入一个鼠标指针 
LoadCursorFromFile 在一个指针文件或一个动画指针文件的基础上创建一个指针 
LoadIcon 从指定的模块或应用程序实例中载入一个图标 
LoadImage 载入一个位图、图标或指针 
MaskBlt 执行复杂的图象传输,同时进行掩模(MASK)处理 
PatBlt 在当前选定的刷子的基础上,用一个图案填充指定的设备场景 
PlgBlt 复制一幅位图,同时将其转换成一个平行四边形。利用它可对位图进行旋转处理 
SetBitmapBits 将来自缓冲区的二进制位复制到一幅位图 
SetBitmapDimensionEx 设置一幅位图的宽度。以一毫米的十分之一为单位 
SetDIBColorTable 设置选入设备场景的一个DIBSection的颜色表信息 
SetDIBits 将来自与设备无关位图的二进制位复制到一幅与设备有关的位图里 
SetDIBitsToDevice 将一幅与设备无关位图的全部或部分数据直接复制到一个设备 
SetStretchBltMode 指定StretchBlt StretchDIBits函数的伸缩模式 
StretchBlt 将一幅位图从一个设备场景复制到另一个 
StretchDIBits 将一幅与设备无关位图的全部或部分数据直接复制到指定的设备场景

8. API之绘图函数 

AbortPath 抛弃选入指定设备场景中的所有路径。也取消目前正在进行的任何路径的创建工作 
AngleArc 用一个连接弧画一条线 
Arc 画一个圆弧 
BeginPath 启动一个路径分支 
CancelDC 取消另一个线程里的长时间绘图操作 
Chord 画一个弦 
CloseEnhMetaFile 关闭指定的增强型图元文件设备场景,并将新建的图元文件返回一个句柄 
CloseFigure 描绘到一个路径时,关闭当前打开的图形 
CloseMetaFile 关闭指定的图元文件设备场景,并向新建的图元文件返回一个句柄 
CopyEnhMetaFile 制作指定增强型图元文件的一个副本(拷贝) 
CopyMetaFile 制作指定(标准)图元文件的一个副本 
CreateBrushIndirect 在一个LOGBRUSH数据结构的基础上创建一个刷子 
CreateDIBPatternBrush 用一幅与设备无关的位图创建一个刷子,以便指定刷子样式(图案) 
CreateEnhMetaFile 创建一个增强型的图元文件设备场景 
CreateHatchBrush 创建带有阴影图案的一个刷子 
CreateMetaFile 创建一个图元文件设备场景 
CreatePatternBrush 用指定了刷子图案的一幅位图创建一个刷子 
CreatePen 用指定的样式、宽度和颜色创建一个画笔 
CreatePenIndirect 根据指定的LOGPEN结构创建一个画笔 
CreateSolidBrush 用纯色创建一个刷子 
DeleteEnhMetaFile 删除指定的增强型图元文件 
DeleteMetaFile 删除指定的图元文件 
DeleteObject 删除GDI对象,对象使用的所有系统资源都会被释放 
DrawEdge 用指定的样式描绘一个矩形的边框 
DrawEscape 换码(Escape)函数将数据直接发至显示设备驱动程序 
DrawFocusRect 画一个焦点矩形 
DrawFrameControl 描绘一个标准控件 
DrawState 为一幅图象或绘图操作应用各式各样的效果 
Ellipse 描绘一个椭圆,由指定的矩形围绕 
EndPath 停止定义一个路径 
EnumEnhMetaFile 针对一个增强型图元文件,列举其中单独的图元文件记录 
EnumMetaFile 为一个标准的windows图元文件枚举单独的图元文件记录 
EnumObjects 枚举可随同指定设备场景使用的画笔和刷子 
ExtCreatePen 创建一个扩展画笔(装饰或几何) 
ExtFloodFill 在指定的设备场景里,用当前选择的刷子填充一个区域 
FillPath 关闭路径中任何打开的图形,并用当前刷子填充 
FillRect 用指定的刷子填充一个矩形 
FlattenPath 将一个路径中的所有曲线都转换成线段 
FloodFill 用当前选定的刷子在指定的设备场景中填充一个区域 
FrameRect 用指定的刷子围绕一个矩形画一个边框 
GdiComment 为指定的增强型图元文件设备场景添加一条注释信息 
GdiFlush 执行任何未决的绘图操作 
GdiGetBatchLimit 判断有多少个GDI绘图命令位于队列中 
GdiSetBatchLimit 指定有多少个GDI绘图命令能够进入队列 
GetArcDirection 画圆弧的时候,判断当前采用的绘图方向 
GetBkColor 取得指定设备场景当前的背景颜色 
GetBkMode 针对指定的设备场景,取得当前的背景填充模式 
GetBrushOrgEx 判断指定设备场景中当前选定刷子起点 
GetCurrentObject 获得指定类型的当前选定对象 
GetCurrentPositionEx 在指定的设备场景中取得当前的画笔位置 
GetEnhMetaFile 取得磁盘文件中包含的一个增强型图元文件的图元文件句柄 
GetEnhMetaFileBits 将指定的增强型图元文件复制到一个内存缓冲区里 
GetEnhMetaFileDescription 返回对一个增强型图元文件的说明 
GetEnhMetaFileHeader 取得增强型图元文件的图元文件头 
GetEnhMetaFilePaletteEntries 取得增强型图元文件的全部或部分调色板 
GetMetaFile 取得包含在一个磁盘文件中的图元文件的图元文件句柄 
GetMetaFileBitsEx 将指定的图元文件复制到一个内存缓冲区 
GetMiterLimit 取得设备场景的斜率限制(Miter)设置 
GetNearestColor 根据设备的显示能力,取得与指定颜色最接近的一种纯色 
GetObjectAPI 取得对指定对象进行说明的一个结构 
GetObjectType 判断由指定句柄引用的GDI对象的类型 
GetPath 取得对当前路径进行定义的一系列数据 
GetPixel 在指定的设备场景中取得一个像素的RGB 
GetPolyFillMode 针对指定的设备场景,获得多边形填充模式 
GetROP2 针对指定的设备场景,取得当前的绘图模式 
GetStockObject 取得一个固有对象(Stock 
GetSysColorBrush 为任何一种标准系统颜色取得一个刷子 
GetWinMetaFileBits 通过在一个缓冲区中填充用于标准图元文件的数据,将一个增强型图元文件转换成标准windows图元文件 
InvertRect 通过反转每个像素的值,从而反转一个设备场景中指定的矩形 
LineDDA 枚举指定线段中的所有点 
LineTo 用当前画笔画一条线,从当前位置连到一个指定的点 
MoveToEx 为指定的设备场景指定一个新的当前画笔位置 
PaintDesk 在指定的设备场景中描绘桌面墙纸图案 
PathToRegion 将当前选定的路径转换到一个区域里 
Pie 画一个饼图 
PlayEnhMetaFile 在指定的设备场景中画一个增强型图元文件 
PlayEnhMetaFileRecord 回放单独一条增强型图元文件记录 
PlayMetaFile 在指定的设备场景中回放一个图元文件 
PlayMetaFileRecord 回放来自图元文件的单条记录 
PolyBezier 描绘一条或多条贝塞尔(Bezier)曲线 
PolyDraw 描绘一条复杂的曲线,由线段及贝塞尔曲线组成 
Polygon 描绘一个多边形 
Polyline 用当前画笔描绘一系列线段 
PolyPolygon 用当前选定画笔描绘两个或多个多边形 
PolyPolyline 用当前选定画笔描绘两个或多个多边形 
Rectangle 用当前选定的画笔描绘矩形,并用当前选定的刷子填充 
RoundRect 用当前选定的画笔画一个圆角矩形,并用当前选定的刷子在其中填充 
SelectClipPath 将设备场景当前的路径合并到剪切区域里 
SelectObject 为当前设备场景选择图形对象 
SetArcDirection 设置圆弧的描绘方向 
SetBkColor 为指定的设备场景设置背景颜色 
SetBkMode 指定阴影刷子、虚线画笔以及字符中的空隙的填充方式 
SetBrushOrgEx 为指定的设备场景设置当前选定刷子的起点 
SetEnhMetaFileBits 用指定内存缓冲区内包含的数据创建一个增强型图元文件 
SetMetaFileBitsEx 用包含在指定内存缓冲区内的数据结构创建一个图元文件 
SetMiterLimit 设置设备场景当前的斜率限制 
SetPixel 在指定的设备场景中设置一个像素的RGB 
SetPixelV 在指定的设备场景中设置一个像素的RGB 
SetPolyFillMode 设置多边形的填充模式 
SetROP2 设置指定设备场景的绘图模式。与vbDrawMode属性完全一致 
SetWinMetaFileBits 将一个标准Windows图元文件转换成增强型图元文件 
StrokeAndFillPath 针对指定的设备场景,关闭路径上打开的所有区域 
StrokePath 用当前画笔描绘一个路径的轮廓。打开的图形不会被这个函数关闭 
UnrealizeObject 将一个刷子对象选入设备场景之前,如刷子的起点准备用SetBrushOrgEx修改,则必须先调用本函数 
WidenPath 根据选定画笔的宽度,重新定义当前选定的路径 

9. API之设备场景函数 

CombineRgn 将两个区域组合为一个新区域 
CombineTransform 驱动世界转换。它相当于依顺序进行两次转换 
CreateCompatibleDC 创建一个与特定设备场景一致的内存设备场景 
CreateDC 为专门设备创建设备场景 
CreateEllipticRgn 创建一个椭圆 
CreateEllipticRgnIndirect 创建一个内切于特定矩形的椭圆区域 
CreateIC 为专用设备创建一个信息场景 
CreatePolygonRgn 创建一个由一系列点围成的区域 
CreatePolyPolygonRgn 创建由多个多边形构成的区域。每个多边形都应是封闭的 
CreateRectRgn 创建一个矩形区域 
CreateRectRgnIndirect 创建一个矩形区域 
CreateRoundRectRgn 创建一个圆角矩形 
DeleteDC 删除专用设备场景或信息场景,释放所有相关窗口资源 
DPtoLP 将点阵从设备坐标转换到专用设备场景逻辑坐标 
EqualRgn 确定两个区域是否相等 
ExcludeClipRect 从专用设备场景的剪裁区中去掉一个矩形区。矩形内不能进行绘图 
ExcludeUpdateRgn 从专用设备场景剪裁区去掉指定窗口的刷新区域 
ExtCreateRegion 根据世界转换修改区域 
ExtSelectClipRgn 将指定区域组合到设备场景的当前剪裁区 
FillRgn 用指定刷子填充指定区域 
FrameRgn 用指定刷子围绕指定区域画一个外框 
GetBoundsRect 获取指定设备场景的边界矩形 
GetClipBox 获取完全包含指定设备场景剪裁区的最小矩形 
GetClipRgn 获取设备场景当前剪裁区 
GetDC 获取指定窗口的设备场景 
GetDCEx 为指定窗口获取设备场景。相比GetDC,本函数提供了更多的选项 
GetDCOrgEx 获取指定设备场景起点位置(以屏幕坐标表示) 
GetDeviceCaps 根据指定设备场景代表的设备的功能返回信息 
GetGraphicsMode 确定是否允许增强图形模式(世界转换) 
GetMapMode 为特定设备场景调入映象模式 
GetRegionData 装入描述一个区域信息的RgnData结构或缓冲区 
GetRgnBox 获取完全包含指定区域的最小矩形 
GetUpdateRgn 确定指定窗口的刷新区域。该区域当前无效,需要刷新 
GetViewportExtEx 获取设备场景视口(viewport)范围 
GetViewportOrgEx 获取设备场景视口起点 
GetWindowDC 获取整个窗口(包括边框、滚动条、标题栏、菜单等)的设备场景 
GetWindowExtEx 获取指定设备场景的窗口范围 
GetWindowOrgEx 获取指定设备场景的逻辑窗口的起点 
GetWindowRgn 获取窗口区域 
GetWorldTransform 如果有世界转换,为设备场景获取当前世界转换 
IntersectClipRect 为指定设备定义一个新的剪裁区 
InvalidateRgn 使窗口指定区域不活动,并将它加入窗口刷新区,使之可随后被重画 
InvertRgn 通过颠倒每个像素值反转设备场景指定区域 
LPtoDP 将点阵从指定设备场景逻辑坐标转换为设备坐标 
ModifyWorldTransform 根据指定的模式修改世界转换 
OffsetClipRgn 按指定量平移设备场景剪裁区 
OffsetRgn 按指定偏移量平移指定区域 
OffsetViewportOrgEx 平移设备场景视口区域 
OffsetWindowOrgEx 平移指定设备场景窗口起点 
PaintRgn 用当前刷子背景色填充指定区域 
PtInRegion 确定点是否在指定区域内 
PtVisible 确定指定点是否可见(即,点是否在设备场景剪裁区内) 
RectInRegion 确定矩形是否有部分在指定区域内 
RectVisible 确定指定矩形是否有部分可见(是否在设备场景剪裁区内) 
ReleaseDC 释放由调用GetDCGetWindowDC函数获取的指定设备场景 
RestoreDC 从设备场景堆栈恢复一个原先保存的设备场景 
SaveDC 将指定设备场景状态保存到Windows设备场景堆栈 
ScaleViewportExtEx 缩放设备场景视口的范围 
ScaleWindowExtEx 缩放指定设备场景窗口范围 
ScrollDC 在窗口(由设备场景代表)中水平和(或)垂直滚动矩形 
SelectClipRgn 为指定设备场景选择新的剪裁区 
SetBoundsRect 设置指定设备场景的边界矩形 
SetGraphicsMode 允许或禁止增强图形模式,以提供某些支持(包括世界转换) 
SetMapMode 设置指定设备场景的映射模式 
SetRectRgn 设置区域为指定的矩形 
SetViewportExtEx 设置设备场景视口范围 
SetViewportOrgEx 设置设备场景视口起点 
SetWindowExtEx 设置指定设备场景窗口范围 
SetWindowOrgEx 设置指定设备场景窗口起点 
SetWindowRgn 设置窗口区域 
SetWorldTransform 设置世界转换 
ValidateRgn 激活窗口中指定区域,把它从刷新区移走 
WindowFromDC 取回与某一设备场景相关的窗口的句柄 

10. API之硬件与系统函数 
ActivateKeyboardLayout 激活一个新的键盘布局。键盘布局定义了按键在一种物理性键盘上的位置与含义 
Beep 用于生成简单的声音 
CharToOem 将一个字串从ANSI字符集转换到OEM字符集 
ClipCursor 将指针限制到指定区域 
ConvertDefaultLocale 将一个特殊的地方标识符转换成真实的地方ID 
CreateCaret 根据指定的信息创建一个插入符(光标),并将它选定为指定窗口的默认插入符 
DestroyCaret 清除(破坏)一个插入符 
EnumCalendarInfo 枚举在指定地方环境中可用的日历信息 
EnumDateFormats 列举指定的当地设置中可用的长、短日期格式 
EnumSystemCodePages 枚举系统中已安装或支持的代码页 
EnumSystemLocales 枚举系统已经安装或提供支持的地方设置 
EnumTimeFormats 枚举一个指定的地方适用的时间格式 
ExitWindowsEx 退出windows,并用特定的选项重新启动 
ExpandEnvironmentStrings 扩充环境字串 
FreeEnvironmentStrings 翻译指定的环境字串块 
GetACP 判断目前正在生效的ANSI代码页 
GetAsyncKeyState 判断函数调用时指定虚拟键的状态 
GetCaretBlinkTime 判断插入符光标的闪烁频率 
GetCaretPos 判断插入符的当前位置 
GetClipCursor 取得一个矩形,用于描述目前为鼠标指针规定的剪切区域 
GetCommandLine 获得指向当前命令行缓冲区的一个指针 
GetComputerName 取得这台计算机的名称 
GetCPInfo 取得与指定代码页有关的信息 
GetCurrencyFormat 针对指定的地方设置,根据货币格式格式化一个数字 
GetCursor 获取目前选择的鼠标指针的句柄 
GetCursorPos 获取鼠标指针的当前位置 
GetDateFormat 针对指定的当地格式,对一个系统日期进行格式化 
GetDoubleClickTime 判断连续两次鼠标单击之间会被处理成双击事件的间隔时间 
GetEnvironmentStrings 为包含了当前环境字串设置的一个内存块分配和返回一个句柄 
GetEnvironmentVariable 取得一个环境变量的值 
GetInputState 判断是否存在任何待决(等待处理)的鼠标或键盘事件 
GetKBCodePage GetOEMCP取代,两者功能完全相同 
GetKeyboardLayout 取得一个句柄,描述指定应用程序的键盘布局 
GetKeyboardLayoutList 获得系统适用的所有键盘布局的一个列表 
GetKeyboardLayoutName 取得当前活动键盘布局的名称 
GetKeyboardState 取得键盘上每个虚拟键当前的状态 
GetKeyboardType 了解与正在使用的键盘有关的信息 
GetKeyNameText 在给出扫描码的前提下,判断键名 
GetKeyState 针对已处理过的按键,在最近一次输入信息时,判断指定虚拟键的状态 
GetLastError 针对之前调用的api函数,用这个函数取得扩展错误信息 
GetLocaleInfo 取得与指定地方有关的信息 
GetLocalTime 取得本地日期和时间 
GetNumberFormat 针对指定的地方,按特定的格式格式化一个数字 
GetOEMCP 判断在OEMANSI字符集间转换的windows代码页 
GetQueueStatus 判断应用程序消息队列中待决(等待处理)的消息类型 
GetSysColor 判断指定windows显示对象的颜色 
GetSystemDefaultLangID 取得系统的默认语言ID 
GetSystemDefaultLCID 取得当前的默认系统地方 
GetSystemInfo 取得与底层硬件平台有关的信息 
GetSystemMetrics 返回与windows环境有关的信息 
GetSystemPowerStatus 获得与当前系统电源状态有关的信息 
GetSystemTime 取得当前系统时间,这个时间采用的是协同世界时间(即UTC,也叫做GMT)格式 
GetSystemTimeAdjustment 使内部系统时钟与一个外部的时钟信号源同步 
GetThreadLocale 取得当前线程的地方ID 
GetTickCount 用于获取自windows启动以来经历的时间长度(毫秒) 
GetTimeFormat 针对当前指定的地方,按特定的格式格式化一个系统时间 
GetTimeZoneInformation 取得与系统时区设置有关的信息 
GetUserDefaultLangID 为当前用户取得默认语言ID 
GetUserDefaultLCID 取得当前用户的默认地方设置 
GetUserName 取得当前用户的名字 
GetVersion 判断当前运行的WindowsDOS版本 
GetVersionEx 取得与平台和操作系统有关的版本信息 
HideCaret 在指定的窗口隐藏插入符(光标) 
IsValidCodePage 判断一个代码页是否有效 
IsValidLocale 判断地方标识符是否有效 
keybd_event 这个函数模拟了键盘行动 
LoadKeyboardLayout 载入一个键盘布局 
MapVirtualKey 根据指定的映射类型,执行不同的扫描码和字符转换 
MapVirtualKeyEx 根据指定的映射类型,执行不同的扫描码和字符转换 
MessageBeep 播放一个系统声音。系统声音的分配方案是在控制面板里决定的 
mouse_event 模拟一次鼠标事件 
OemKeyScan 判断OEM字符集中的一个ASCII字符的扫描码和Shift键状态 
OemToChar OEM字符集的一个字串转换到ANSI字符集 
SetCaretBlinkTime 指定插入符(光标)的闪烁频率 
SetCaretPos 指定插入符的位置 
SetComputerName 设置新的计算机名 
SetCursor 将指定的鼠标指针设为当前指针 
SetCursorPos 设置指针的位置 
SetDoubleClickTime 设置连续两次鼠标单击之间能使系统认为是双击事件的间隔时间 
SetEnvironmentVariable 将一个环境变量设为指定的值 
SetKeyboardState 设置每个虚拟键当前在键盘上的状态 
SetLocaleInfo 改变用户地方设置信息 
SetLocalTime 设置当前地方时间 
SetSysColors 设置指定窗口显示对象的颜色 
SetSystemCursor 改变任何一个标准系统指针 
SetSystemTime 设置当前系统时间 
SetSystemTimeAdjustment 定时添加一个校准值使内部系统时钟与一个外部的时钟信号源同步 
SetThreadLocale 为当前线程设置地方 
SetTimeZoneInformation 设置系统时区信息 
ShowCaret 在指定的窗口里显示插入符(光标) 
ShowCursor 控制鼠标指针的可视性 
SwapMouseButton 决定是否互换鼠标左右键的功能 
SystemParametersInfo 获取和设置数量众多的windows系统参数 
SystemTimeToTzSpecificLocalTime 将系统时间转换成地方时间 
ToAscii 根据当前的扫描码和键盘信息,将一个虚拟键转换成ASCII字符 
ToUnicode 根据当前的扫描码和键盘信息,将一个虚拟键转换成Unicode字符 
UnloadKeyboardLayout 卸载指定的键盘布局 
VkKeyScan 针对Windows字符集中一个ASCII字符,判断虚拟键码和Shift键的状态 

11. API之进程和线程函数 

CancelWaitableTimer 这个函数用于取消一个可以等待下去的计时器操作 
CallNamedPipe 这个函数由一个希望通过管道通信的一个客户进程调用 
ConnectNamedPipe 指示一台服务器等待下去,直至客户机同一个命名管道连接 
CreateEvent 创建一个事件对象 
CreateMailslot 创建一个邮路。返回的句柄由邮路服务器使用(收件人) 
CreateMutex 创建一个互斥体(MUTEX 
CreateNamedPipe 创建一个命名管道。返回的句柄由管道的服务器端使用 
CreatePipe 创建一个匿名管道 
CreateProcess 创建一个新进程(比如执行一个程序) 
CreateSemaphore 创建一个新的信号机 
CreateWaitableTimer 创建一个可等待的计时器对象 
DisconnectNamedPipe 断开一个客户与一个命名管道的连接 
DuplicateHandle 在指出一个现有系统对象当前句柄的情况下,为那个对象创建一个新句柄 
ExitProcess 中止一个进程 
FindCloseChangeNotification 关闭一个改动通知对象 
FindExecutable 查找与一个指定文件关联在一起的程序的文件名 
FindFirstChangeNotification 创建一个文件通知对象。该对象用于监视文件系统发生的变化 
FindNextChangeNotification 重设一个文件改变通知对象,令其继续监视下一次变化 
FreeLibrary 释放指定的动态链接库 
GetCurrentProcess 获取当前进程的一个伪句柄 
GetCurrentProcessId 获取当前进程一个唯一的标识符 
GetCurrentThread 获取当前线程的一个伪句柄 
GetCurrentThreadId 获取当前线程一个唯一的线程标识符 
GetExitCodeProces 获取一个已中断进程的退出代码 
GetExitCodeThread 获取一个已中止线程的退出代码 
GetHandleInformation 获取与一个系统对象句柄有关的信息 
GetMailslotInfo 获取与一个邮路有关的信息 
GetModuleFileName 获取一个已装载模板的完整路径名称 
GetModuleHandle 获取一个应用程序或动态链接库的模块句柄 
GetPriorityClass 获取特定进程的优先级别 
GetProcessShutdownParameters 调查系统关闭时一个指定的进程相对于其它进程的关闭早迟情况 
GetProcessTimes 获取与一个进程的经过时间有关的信息 
GetProcessWorkingSetSize 了解一个应用程序在运行过程中实际向它交付了多大容量的内存 
GetSartupInfo 获取一个进程的启动信息 
GetThreadPriority 获取特定线程的优先级别 
GetTheardTimes 获取与一个线程的经过时间有关的信息 
GetWindowThreadProcessId 获取与指定窗口关联在一起的一个进程和线程标识符 
LoadLibrary 载入指定的动态链接库,并将它映射到当前进程使用的地址空间 
LoadLibraryEx 装载指定的动态链接库,并为当前进程把它映射到地址空间 
LoadModule 载入一个Windows应用程序,并在指定的环境中运行 
MsgWaitForMultipleObjects 等侯单个对象或一系列对象发出信号。如返回条件已经满足,则立即返回 
SetPriorityClass 设置一个进程的优先级别 
SetProcessShutdownParameters 在系统关闭期间,为指定进程设置他相对于其它程序的关闭顺序 
SetProcessWorkingSetSize 设置操作系统实际划分给进程使用的内存容量 
SetThreadPriority 设定线程的优先级别 
ShellExecute 查找与指定文件关联在一起的程序的文件名 
TerminateProcess 结束一个进程 
WinExec 运行指定的程序 

12. API之控件与消息函数 

AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 
AnyPopup 判断屏幕上是否存在任何弹出式窗口 
ArrangeIconicWindows 排列一个父窗口的最小化子窗口 
AttachThreadInput 连接线程输入函数 
BeginDeferWindowPos 启动构建一系列新窗口位置的过程 
BringWindowToTop 将指定的窗口带至窗口列表顶部 
CascadeWindows 以层叠方式排列窗口 
ChildWindowFromPoint 返回父窗口中包含了指定点的第一个子窗口的句柄 
ClientToScreen 判断窗口内以客户区坐标表示的一个点的屏幕坐标 
CloseWindow 最小化指定的窗口 
CopyRect 矩形内容复制 
DeferWindowPos 该函数为特定的窗口指定一个新窗口位置 
DestroyWindow 清除指定的窗口以及它的所有子窗口 
DrawAnimatedRects 描绘一系列动态矩形 
EnableWindow 指定的窗口里允许或禁止所有鼠标及键盘输入 
EndDeferWindowPos 同时更新DeferWindowPos调用时指定的所有窗口的位置及状态 
EnumChildWindows 为指定的父窗口枚举子窗口 
EnumThreadWindows 枚举与指定任务相关的窗口 
EnumWindows 枚举窗口列表中的所有父窗口 
EqualRect 判断两个矩形结构是否相同 
FindWindow 寻找窗口列表中第一个符合指定条件的顶级窗口 
FindWindowEx 在窗口列表中寻找与指定条件相符的第一个子窗口 
FlashWindow 闪烁显示指定窗口 
GetActiveWindow 获得活动窗口的句柄 
GetCapture 获得一个窗口的句柄,这个窗口位于当前输入线程,且拥有鼠标捕获(鼠标活动由它接收) 
GetClassInfo 取得WNDCLASS结构(或WNDCLASSEX结构)的一个副本,结构中包含了与指定类有关的信息 
GetClassLong 取得窗口类的一个Long变量条目 
GetClassName 为指定的窗口取得类名 
GetClassWord 为窗口类取得一个整数变量 
GetClientRect 返回指定窗口客户区矩形的大小 
GetDesktopWindow 获得代表整个屏幕的一个窗口(桌面窗口)句柄 
GetFocus 获得拥有输入焦点的窗口的句柄 
GetForegroundWindow 获得前台窗口的句柄 
GetLastActivePopup 获得在一个给定父窗口中最近激活过的弹出式窗口的句柄 
GetParent 判断指定窗口的父窗口 
GetTopWindow 搜索内部窗口列表,寻找隶属于指定窗口的头一个窗口的句柄 
GetUpdateRect 获得一个矩形,它描叙了指定窗口中需要更新的那一部分 
GetWindow 获得一个窗口的句柄,该窗口与某源窗口有特定的关系 
GetWindowContextHelpId 取得与窗口关联在一起的帮助场景ID 
GetWindowLong 从指定窗口的结构中取得信息 
GetWindowPlacement 获得指定窗口的状态及位置信息 
GetWindowRect 获得整个窗口的范围矩形,窗口的边框、标题栏、滚动条及菜单等都在这个矩形内 
GetWindowText 取得一个窗体的标题(caption)文字,或者一个控件的内容 
GetWindowTextLength 调查窗口标题文字或控件内容的长短 
GetWindowWord 获得指定窗口结构的信息 
InflateRect 增大或减小一个矩形的大小 
IntersectRect 这个函数在lpDestRect里载入一个矩形,它是lpSrc1RectlpSrc2Rect两个矩形的交集 
InvalidateRect 屏蔽一个窗口客户区的全部或部分区域 
IsChild 判断一个窗口是否为另一窗口的子或隶属窗口 
IsIconic 判断窗口是否已最小化 
IsRectEmpty 判断一个矩形是否为空 
IsWindow 判断一个窗口句柄是否有效 
IsWindowEnabled 判断窗口是否处于活动状态 
IsWindowUnicode 判断一个窗口是否为Unicode窗口。这意味着窗口为所有基于文本的消息都接收Unicode文字 
IsWindowVisible 判断窗口是否可见 
IsZoomed 判断窗口是否最大化 
LockWindowUpdate 锁定指定窗口,禁止它更新 
MapWindowPoints 将一个窗口客户区坐标的点转换到另一窗口的客户区坐标系统 
MoveWindow 改变指定窗口的位置和大小 
OffsetRect 通过应用一个指定的偏移,从而让矩形移动起来 
OpenIcon 恢复一个最小化的程序,并将其激活 
PtInRect 判断指定的点是否位于矩形内部 
RedrawWindow 重画全部或部分窗口 
ReleaseCapture 为当前的应用程序释放鼠标捕获 
ScreenToClient 判断屏幕上一个指定点的客户区坐标 
ScrollWindow 滚动窗口客户区的全部或一部分 
ScrollWindowEx 根据附加的选项,滚动窗口客户区的全部或部分 
SetActiveWindow 激活指定的窗口 
SetCapture 将鼠标捕获设置到指定的窗口 
SetClassLong 为窗口类设置一个Long变量条目 
SetClassWord 为窗口类设置一个条目 
SetFocusAPI 将输入焦点设到指定的窗口。如有必要,会激活窗口 
SetForegroundWindow 将窗口设为系统的前台窗口 
SetParent 指定一个窗口的新父 
SetRect 设置指定矩形的内容 
SetRectEmpty 将矩形设为一个空矩形 
SetWindowContextHelpId 为指定的窗口设置帮助场景(上下文)ID 
SetWindowLong 在窗口结构中为指定的窗口设置信息 
SetWindowPlacement 设置窗口状态和位置信息 
SetWindowPos 为窗口指定一个新位置和状态 
SetWindowText 设置窗口的标题文字或控件的内容 
SetWindowWord 在窗口结构中为指定的窗口设置信息 
ShowOwnedPopups 显示或隐藏由指定窗口所有的全部弹出式窗口 
ShowWindow 控制窗口的可见性 
ShowWindowAsync ShowWindow相似 
SubtractRect 装载矩形lprcDst,它是在矩形lprcSrc1中减去lprcSrc2得到的结果 
TileWindows 以平铺顺序排列窗口 
UnionRect 装载一个lpDestRect目标矩形,它是lpSrc1RectlpSrc2Rect联合起来的结果 
UpdateWindow 强制立即更新窗口 
ValidateRect 校验窗口的全部或部分客户区 
WindowFromPoint 返回包含了指定点的窗口的句柄。忽略屏蔽、隐藏以及透明窗口

你可能感兴趣的:(c语言,开发语言)