从.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

C#调用Win32 api学习总结的更多相关文章

  1. MSIL 教程(二):数组、分支、循环、使用不安全代码和如何调用Win32 API(转)

    转自:http://www.cnblogs.com/Yahong111/archive/2007/08/16/857574.html 续上文[翻译]MSIL 教程(一) ,本文继续讲解数组.分支.循环 ...

  2. Python调用win32 API绘制正弦波

    Python调用win32 API新建窗口与直接创建窗口的流程相同 流程:注册窗口→创建窗口→显示窗口→更新窗口→消息循环 代码: # -*- coding: utf-8 -*- import win ...

  3. C#调用Win32 api时的内存操作

    一般情况下,C#与Win 32 Api的互操作都表现的很一致:值类型传递结构体,一维.二维指针传递IntPtr.在Win32 分配内存时,可以通过IntPtr以类似移动指针的方式读取内存.通过IntP ...

  4. nodejs 调用win32 api

    video 教程文件 win32 api >node -v v12.16.1 >npm install -g node-gyp >npm i @saleae/ffi >node ...

  5. 调用win32 api 函数SendMessage() 实现消息直接调用

    简单的调用例子, 适合初学者学习,当然 我也是初学者. #include <windows.h> #include <stdio.h> #include <stdlib. ...

  6. C#调用win32 api 操作其它窗口

    实现以下功能: 找到窗体 找到控件(也叫子窗体) 获取内容 获取位置 设置 位置 内容 鼠标点击 示范 1. 找窗体 以操作系统自带的计算器为例 string clWindow = "Cal ...

  7. C#调用win32 api程序实例

    1.声明static extern 方法,使用DllImport特性 class MyClass { [DllImport("kernel32", SetLastError = t ...

  8. win32 API 学习

    SendMessage 函数原型 LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam) 详情:百度百科     msd ...

  9. Win32+API学习笔记:创建基本的窗口控件

    创建一个标签 CreateWindowEx(0, "static", "姓名:",                                        ...

随机推荐

  1. 如何修改 Discuz 门户文章页默认视频大小

    在 Discuz 系统中,论坛插入 Flash 等可以输入自定义的尺寸,但是门户文章页不可以修改.经过一番研究,找到了修改门户文章页默认视频大小的方法如下,希望对你有用:找到:/source/func ...

  2. (原创)LINUX_UNIX设计思想-读书笔记

    第一章 一.Unit哲学 1.小即是美 2.让每一个程序只做好一件事情 3.尽快建立原型 4.舍高效率而取可移植性 5.使用纯文本文件来存储数据 6.充分利用软件的杠杆效应 7.使用shell脚本来提 ...

  3. 启动另外一个activity,并返回结果

    欢迎大家光临我的小店:http://clkk.taobao.com 大致步骤: 1.启动另外一个Activity,这里称子Activity: 2.子Activity通过setResult方法设置返回结 ...

  4. sqlserver中distinct的用法(不重复的记录)

    下面先来看看例子: table表 字段1     字段2   id        name   1           a   2           b   3           c   4    ...

  5. VBS基础篇 - 循环

    经常地,当编写代码时,我们希望将一段代码执行若干次,我们可以在代码中使用循环语句来完成这项工作. 循环可分为三类:一类在条件变为 False 之前重复执行语句,一类在条件变为 True 之前重复执行语 ...

  6. iOS10和Xcode8适配

    1 Xib文件的注意事项 使用Xcode8打开xib文件后,会出现下图的提示. 大家选择Choose Device即可. 之后大家会发现布局啊,frame乱了,只需要更新一下frame即可.如下图 注 ...

  7. Careercup - Facebook面试题 - 4909367207919616

    2014-05-01 01:23 题目链接 原题: WAP to modify the array such that arr[I] = arr[arr[I]]. Do this in place i ...

  8. Java 执行 SQL 脚本文件

    转自:http://blog.csdn.net/hongmin118/article/details/4588941 package com.unmi.db; import java.io.FileI ...

  9. 【转】jquery-取消冒泡

    转自:http://blog.163.com/css_mm/blog/static/209182176201262665157634/ 1.通过返回false来取消默认的行为并阻止事件起泡. jQue ...

  10. Vbox下linux虚拟机根分区扩容

    前言 使用一段时间VBox中的linux后可能会显示根分区空间不足的情况,需要扩容. 通过查阅相关资料,VBox中linux扩容主要有两种办法:通过lvm扩容和通过gparted扩容 LVM条件:VB ...