• C#调用Win32 api学习总结


    windows api 手册

     http://www.juliusun.com/class/docs/winapi/catalog.php

    从.NET平台调用Win32 API

            Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制Windows的接口。

    一.    基础知识

            Win32 API是C语言(注意,不是C++语言,尽管C语言是C++语言的子集)函数集。

    1. Win32 API函数放在哪里?

            Win32 API函数是Windows的核心,比如我们看到的窗体、按钮、对话框什么的,都是依靠Win32函数“画”在屏幕上的,由于这些控件(有时也称组件)都用于用户与Windows进行交互,所以控制这些控件的Win32 API函数称为“用户界面”函数(User Interface Win32 API),简称UI函数;还有一些函数,并不用于交互,比如管理当前系统正在运行的进程、硬件系统状态的监视等等……这些函数只有一套,但是可以被所有的Windows程序调用(只要这个程序的权限足够高),简而言之,API是为程序所共享的。为了达到所有程序能共享一套API的目的,Windows采用了“动态链接库”的办法。之所以叫“动态链接库”,是因为这样的函数库的调用方式是“随用随取”而不是像静态链接库那样“用不用都要带上”。

            

            Win32 API函数是放在Windows系统的核心库文件中的,这些库在硬盘里的存储形式是.dll文件。我们常用到的dll文件是user32.dll和kernel32.dll两个文件。

            这些dll文件是用C语言写的,源代码经C语言编译器编译之后,会以二进制可执行代码形式存放在这些dll文件中。为了能让程序使用这些函数,微软在发布每个新的操作系统的时候,也会放出这个系统的SDK,目前最新的是Win2003 SP1 SDK,据说Vista的马上就要放出来,而且已经把UI的API从核心库中分离出去以提高系统的稳定性了。SDK里有一些C语言的头文件(.h文件),这些文件里描述了核心dll文件里都有哪些Win32 API函数,在写程序的时候,把这些.h文件用#include"....."指令包含进你的程序里,你就可以使用这些Win32 API了。

             C#语言也使用dll动态链接库,不过这些dll都是.NET版本的,具有“自描述性”,也就是自己肚子里都有哪些函数都已经写在自己的metadata里了,不用再附加一个.h文件来说明。现在,我们已经找到了问题的关键点:如何用.NET平台上的C#语言来调用Win32平台上的dll文件。答案非常简单:使用DllImport特性。

    二.  小试        

    using System;

    using System.Runtime.InteropServices;

    class Program

    {

         [DllImport("User32.dll")]

         public static extern int MessageBox(int h, string m, string c, int type);

         static int Main()

         {

             MessageBox(0, "Hello Win32 API", "大爷", 4);

             Console.ReadLine();

             return 0;

         }

    }

            

    1. 要使用DllImport这个特性(特性也是一种类),必须使用这一句using System.Runtime.InteropServices;

    ,导入“运行时->交互服务”。喔~~~~运行时的交互服务不就是“动态链接”吗?感谢Microsoft!

    2. 然后我们就可以制造一个DllImport类的实例,并把这个实例绑定在我们要使用的函数上了。“特性类”这种类非常怪——制造类实例的时候不使用MyClass mc = new MyClass();这种形式,而是使用[特性类(参数列表)]这种形式;特性类不能独立存在,一定要用作修饰其它目标上(本例是修饰后面的一个函数),不同的特性可以用来修饰类、函数、变量等等;特性类实例在被编译的时候也不产生可执行代码,而是被放进metadata里以备检索。总之,你记住特性类很怪就是了,想了解更多就查查MSDN,懒得查就先这么记——不懂惯性定律不影响你学骑自行车。[DllImport("User32.dll")]是说我们要使用的Win32 API函数在User32.dll这个文件里。问题又来了:我怎么知道那么多API函数都在哪个dll文件里呢?这个你可以在MSDN里查到,位置是Root->Win32 and COM Development->Development Guides->Windows API->Windows API->Windows API Reference->Functions by Category。打开这页,你会看到有很多API的分类,API全在这里了。打开一个分类,比如Dialog Box,在Functions段,你会看到很多具体的函数,其中就有上面用到的MessageBox函数,点击进入。你将打开MessageBox的详细解释和具体用法。在这一页的底部,你可以看到一个小表格,里面有一项“Minimum DLL Version   user32.dll”就是说这个函数在user32.dll里。

    3. 接下来就是我们的函数了。在C#里调用Win32函数有这么几个要点。第一:名字要与Win32 API的完全一样。第二:函数除了要有相应的DllImport类修饰外,还要声明成public static extern类型的。第三:函数的返回值和参数类型要与Win32 API完全一致!

    从MSDN里摘出一张表来,是常用Win32数据类型与.NET平台数据类型的对应表:

    Figure 2 Non-Pointer Data Types

    Win32 Types Specification

    CLR Type

    char, INT8, SBYTE, CHAR 8-bit signed integer

    System.SByte

    short, short int, INT16, SHORT 16-bit signed integer

    System.Int16

    int, long, long int, INT32, LONG32, BOOL, INT  32-bit signed integer System.Int32

    __int64, INT64, LONGLONG 64-bit signed integer

    System.Int64

    unsigned char, UINT8, UCHAR, BYTE 8-bit unsigned integer

    System.Byte

    unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t

    16-bit unsigned integer System.UInt16

    unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT

    32-bit unsigned integer System.UInt32

    unsigned __int64, UINT64, DWORDLONG, ULONGLONG  64-bit unsigned integer System.UInt64

    float, FLOAT Single-precision floating point

    System.Single

    double, long double, DOUBLE Double-precision floating point

    System.Double

    In Win32 this type is an integer with a specially assigned meaning; in contrast, the CLR provides a specific type devoted to this meaning.

            有了这些东西,我们就能把一个Win32 API函数转成C#函数了。还拿MessageBox函数为例(看刚才给出的函数表),它的Win32原形如下:

    int MessageBox(  HWND hWnd,   LPCTSTR lpText,    LPCTSTR lpCaption,  UINT uType );

    函数名:MessageBox将保持不变。

    返回值:int 将保持不变(无论是Win32还是C#,int都是32位整数)

    参数表:H开头意味着是Handle,一般情况下Handld都是指针类型,Win32平台的指针类型是用32位来存储的,所以在C#里正好对应一个int整型。不过,既然是指针,就没有什么正负之分,32位都应该用来保存数值——这样一来,用uint(无符号32位整型)来对应Win32的H类型更合理。不过提醒大家一点,int是受C#和.NET CLR双重支持的,而uint只受C#支持而不受.NET CLR支持,所以,本例还是老老实实地使用了int型。

    至于LPCTSTR是Long Pointer to Constant String的缩写,说白了就是——字符串。所以,用

    http://m.blog.csdn.net/article/details?id=50930221

  • 相关阅读:
    Thymeleaf 基本表达式
    html中<radio>单选按钮控件标签用法解析及如何设置默认选中
    <%@ page contentType="text/html; charset=utf-8" language="java"%>每一个字符的含义
    El表达式的关系运算符
    Centos7.6安装Docker安装
    linux必须熟练掌握的基础命令
    CentOS7.x编译安装zabbix4.0
    编译装php7.2 && nginx-1.14
    CentOS7.x安装MySQL5.7.25
    CentOS7.x安装kickstart
  • 原文地址:https://www.cnblogs.com/code1992/p/5965997.html
Copyright © 2020-2023  润新知