一丶什么是Win32 API?

  微软为了保护操作系统的安全性和稳定性,把系统分为内核层和用户层(内核层的代码只能在当CPU的特权级为R0状态下执行,用户层的代码在CPU特权级为R0和R3都能执行),windows在内核层构建了一套管理和保护机制,用于维护系统的正常运行,这些机制的实现被称为系统内核。为了区别于windows的内部实现,把我们日常使用的应用程序所运行的环境称为用户层,此时CPU特权级为R3,无法调用系统的内核函数。但是,只有内核函数才能操控硬件,所以windows又提供了可在用户层调用的函数接口,即Windows API,调用API最后调用的是系统的内核函数。

  所有基于NT内核(XP到Win10都是基于NT内核开发)的Windows API都可以称为Win32,即便是64位系统,也用这个名称,因为64位系统是完全兼容32位程序的(纯32位系统不兼容16位程序),所以你可以看到这些DLL名称都有个"32"的后缀。那我们用C/C++写程序,没用到Win32,怎么也能够执行分配内存,打开进程等操作呢?实际上在Windows系统上的C/C++的运行库内部也是封装了Win32API。进一步说,几乎所有运行在Windows用户层的程序都调用了Win 32API。

  Windows采用分层结构,大致来说就是(用户层->内核层->硬件抽象层->硬件层)(这里的分层只是指一个功能分成多个层次执行,Windows下CPU只有内核模式R0和用户模式R3两种状态),

一个Win32 API调用的大体过程如下:

  Win32 API(kernel32.dll、user32.dll等函数)->调用ntdll.dll函数->使CPU进入内核模式(改变CPU特权级为R0)->查表并调用ntoskrnl.exe或win32k.sys内的函数(ntoskrnl.exe即nt系统内核程序,提供内存、进程管理等服务,同时内部包含了windows的内核函数。在任务管理器中的名字为System)->执行结束返回到用户模式(改模CPU特权级为R3)

  Win 32API大多是微软提供的给ntdll.dll函数的封装,而ntdll.dll是执行内核函数的中介层,由其内的函数进入内核(改变CPU特权级)并调用内核函数。你可以直接调用ntdll.dll的函数,甚至自己编写访问内核函数的接口(有些调用被windows保护程序禁止),这样程序的运行效率会更高,但是我们还是从那几个常用的dll开始学习更为简单。要知道的是,虽然通过Win32 API调用了内核函数,实现了用户层与内核层的交互,但其实大多内核函数都是未公开的。

二丶为什么要学Win32 API?  

  现在用于windows平台的程序开发方式日新月异,种类繁多,比如使用Delphi、WPF、Qt等,开发效率远高于使用Win32 API开发,那为什么还要学习使用Win32 API开发呢?

  ①理解Windows程序底层运行机制。

  ②帮助学习Windows上其他的编程语言、平台。

  ③实现其他库没有提供的高级功能,比如修改其他进程内存等。

三丶开始前你必须知道

语言基础: C/C++

开发平台: Visual Studio

编码格式:Unicode

----------------------

为什么区分编码格式?

  windows程序的编码格式分为两种:ANSI(MBCS:多字节字符集)和Unicode,Windows会按程序的编码格式解码字符。

  ANSI:根据系统当前设置的语言采用不同编码,比如系统语言设置为简体中文,则ANSI采用GBK编码。

  Unicode:统一的字符集,在所有系统中均相同,每个字符占用两个字节。

为什么使用Unicode?

  ①Windows NT是使用Unicode开发的,调用API时要把ANSI字符转换成Unicode字符,直接使用Unicode可以提高运行效率。

  ②使你的程序在不同语言的系统上运行时不会出现乱码。

  ③一些API只能处理Unicode字符。

怎么设置Unicode?

修改编译器设置

  项目->属性->高级->字符集:使用Unicode字符集

设置后观察

  项目->属性->C/C++->命令行:看到两个选项 /D "_UNICODE" /D "UNICODE",说明已成功设置为Unicode编码,否则看到选项 /D "_MBCS",说明使用的是MBCS编码。

  其中_UNICODE定义在C运行库的头文件中,UNICODE定义在Windows的头文件中。

----------------------

尽量使用Windows数据类型

  在平时使用C/C++编程时,我们都使用C/C++标准提供的数据类型,比如:char,shot,int,long int等等,但是在使用Windows API编程时,我们应该尽量使用Windows提供的数据类型,因为Win32 API函数都是使用Windows数据类型编写的,所以你必须要认识它。事实上,这些Windows数据类型都是在windows头文件中对C/C++库原生类型的宏定义,本质上并无差别。下面列举常见的Windows数据类型。

  类型前缀:

  c=const 常量

  u=unsigned 无符号

  p=pointer 指针

  h=handle 句柄

  w=word 字

  dw=double word 双字
  sz=strinszg terminated with a zero 以0结尾的字符串

  lp=long pointer 长指针

  函数后缀:

  A=ansi字符 参数接受ANSI字符

  W=wide宽字符 参数接受Unicode字符

  Ex=extended 扩展版函数,在原函数基础上增加某些新的特性

  Windows类型举例:

  typedef int INT;

  typedef int BOOL;

  typedef unsigned int UINT;

  typedef unsigned short WORD;

  typedef WORD near *PWORD;

  typedef WORD far *LPWORD; 

  其他定义详见 <minwindef.h>
  near指针NP,far指针FP,long指针LP,是为了兼容16位程序,在32位编程中都为P(32位指针)

------------------------

在字符串前添加 L标志:该字符串将按宽字符(Unicode)编码

  TEXT、__TEXT(winnt.h内定义的宏)

  如果 UNICODE被定义,则在字符串前添加L

  _T、__T、_TEXT(tchar.h内定义的宏)

  如果 _UNICODE被定义,则在字符串前添加L

#ifdef  UNICODE
  #define __TEXT(x) L##x
#else
  #define __TEXT(x) x
#endif

------------------------

带T前缀的数据类型,根据是否定义UNICODE使用宽/窄字符

#ifdef  UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif

四丶其他

  笔者学习中,尽量在保持准确性、严谨性的同时使用比较自然的语言来写。

  水平有限,不足之处欢迎批评指正。

  

  本文由Celng原创,转载请标明出处。

Win32 API编程——前言的更多相关文章

  1. win32 C++制作美观按钮,告别win32 API编程中默认的灰色按钮

    使用win32 API制作美观按钮,当鼠标移入/移出按钮时改变按钮背景颜色,类似HTML网页中的效果,告别win32 API编程中默认的灰色按钮,效果图见下面动图和视频. 下载地址: 按钮效果(win ...

  2. WIN32 API编程之 透明static

    createwindow可以直接创建一个staitc,但这个static是不透明的,如果我们把窗口背景设置为GRAY_BRUSH,则static会很明显的有一个白色背景,一般来说这样肯定很难看. 可以 ...

  3. Win32 API编程:使用CreateProcess创建新进程

    #include <windows.h> #include <tchar.h> #include <stdio.h> int main(int argc, char ...

  4. Win32 API编程:网络编程在设置WSAAsyncSelect模型后connect的返回值问题

    通过WSAAsyncSelect()可以设置非阻塞异步套接字 ::WSAAsyncSelect(s, hDlg, WM_SOCKET, FD_CONNECT | FD_CLOSE | FD_WRITE ...

  5. Win32 API编程:显示系统进程列表

    #include <windows.h> #include <tlhelp32.h> // 声明快照函数的头文件 #include "tchar.h" #i ...

  6. Win32 API编程:CHAR TCHAR WCHAR的区别

    #ifdef   UNICODE               typedef   wchar_t   TCHAR;     #else               typedef   unsigned ...

  7. Win32 API编程:WinMain无法重载函数或_tWinMain无法重载

    #include "windows.h" #include "tchar.h" int APIENTRY _tWinMain( HINSTANCE hInsta ...

  8. Win32 API UART编程

    下面是一个使用Win32 API进行UART编程的简单示例. #include <windows.h> #include <stdio.h> int WINAPI WinMai ...

  9. 深入浅出VC++串口编程之基于Win32 API

    1.API描述 在WIN32 API中,串口使用文件方式进行访问,其操作的API基本上与文件操作的API一致. 打开串口 Win32 中用于打开串口的API 函数为CreateFile,其原型为: H ...

随机推荐

  1. 异常:java.lang.RuntimeException: Canvas: trying to draw too large(161740800bytes) bitmap

    现象 今天做一个安卓项目的时候,我使用了10张图片,这10张图片都是放在了drawable目录下. 根据这个错误,我在网上寻找解决问题的方案,然后我放在了mipmap-xxhdpi下结果可以运行. 但 ...

  2. 串的匹配算法--C语言实现

    串这种数据结构,使用是比较多的,但是它的一些方法在更高级的语言中,比如Java,Python中封装的比较完整了.在这里,我只写了串中使用最多的匹配算法,即串的定位操作.串的匹配算法常用的两种就是朴素匹 ...

  3. SpringBoot原理讲解

    一.问题的引入 首先我们来看一个最简单的例子. 我们先创建一个SpringBoot的工程,如何创建一个SpringBoot工程就不说了,不会请自行解决.然后写一个controller类,通过请求路径, ...

  4. 华为云北京四业务,访问北京一OBS桶,配置指南

    [摘要] 华为云跨数据中心,从北京四访问北京一的OBS桶里面的数据.免去数据迁移的麻烦 1      驱动力 跨region访问OBS桶里面的数据时.如果不走云连接,一个OBS桶域名对应的IP地址,是 ...

  5. KETTLE教程实战

    kettle初探 Kettle简介:Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.Kettle 中文名称叫水壶,该项目的主程 ...

  6. NRF51802蓝牙4.0BLE

    今天给大家介绍一款NRF51802的芯片 它是NRF51822的COSTDOWN精简版 本质上跟NRF51822是一致的,原厂为了给大客户节省成本而定制的一个版本 可以跟NRF51822软件硬件完全兼 ...

  7. mininet(二)简单的路由实验

    mininet(一)实验环境搭建 mininet(二)简单的路由实验 mininet(三)简单的NAT实验 在网上找了 好几个代码都是不能直接复现成功,这里把自己实现成功的代码给大家演示一下. 实验的 ...

  8. [TimLinux] Linux shell获取进程pid

    调用脚本时,获取进程PID: (/this/is/a/script/file.sh > /out/to/log.txt & echo $!) & 脚本内部,获取进程PID: ec ...

  9. B.Beautiful Numbers

    题意:你被给予了一个序列 p = [p1, p2, ..., pn](1 ~ n的整数),如果存在l, r左右端点(1 <= l <= r <= n),使得[pl, pl+1,... ...

  10. 使用flatbuffers

    问题 张三是个java程序员,他写产生数据的程序.李四是个python程序员,他要用python处理张三产生的数据.最直观常用的方法就是张三用java把产生的数据保存成csv或者xml文件,然后李四用 ...