暴强贴 从 NET平台调用Win32 API

暴强:从.NET平台调用Win32 API 作者:刘铁猛日期:2005-12-20关键字:C# .NET Win32 API版权声明:本文章受知识产权法保护,如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladey@tom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢.小序        Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Program 阅读详情

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               
此为转贴,感谢原创作者的为人民服务的精神,致礼!

作者:刘铁猛
日期:2005-12-20
关键字:C# .NET Win32 API

版权声明:本文章受知识产权法保护,如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladey@tom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢.

小序
        Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制Windows的接口。想玩儿吗?呵呵,太难了。
        C#使用非常简单,写程序就像打拱猪,Sorry  -_-! ,搭积木一样简单。想玩儿吗?呵呵,没办法直接控制Windows的核心。
        难道就没有两全其美的办法吗?当然不是!要不微软的产品早就没人买了。其实从C#(或者说.NET平台)调用Win32 API还是非常简单滴~~~~今天偶们大家就一起来研究研究。

一.    基础知识
        Win32 API是C语言(注意,不是C++语言,尽管C语言是C++语言的子集)函数集。C#语言与C语言是完全不同的(除了语法上比较像),所以,要想用C#语言调用C语言的Win32 API,要费上一番周折。首先我们就要准备一些基础知识。
1. Win32 API函数放在哪里?
        Win32 API函数是Windows的核心,比如我们看到的窗体、按钮、对话框什么的,都是依靠Win32函数“画”在屏幕上的,由于这些控件(有时也称组件)都用于用户与Windows进行交互,所以控制这些控件的Win32 API函数称为“用户界面”函数(User Interface Win32 API),简称UI函数;还有一些函数,并不用于交互,比如管理当前系统正在运行的进程、硬件系统状态的监视等等……这些函数只有一套,但是可以被所有的Windows程序调用(只要这个程序的权限足够高),简而言之,API是为程序所共享的。为了达到所有程序能共享一套API的目的,Windows采用了“动态链接库”的办法。之所以叫“动态链接库”,是因为这样的函数库的调用方式是“随用随取”而不是像静态链接库那样“用不用都要带上”。
        这里不太好理解,不要紧,我们举个小例子。我们把Windows比做一个游乐场,而把在游乐场里玩儿的小孩比做一个一个程序。小孩在玩的过程中可能要喝水。我们有两个办法让小家伙们想喝水的时候就有水喝:1.给每个小家伙配一个水壶,小家伙们喝了的话就喝自己带的水;2.给游乐场配一个饮水机,谁渴了谁来喝。显然,第二个方法要好得多,这体现在三个地方。第一,带着水壶,小家伙身体不灵活、玩不爽(影响程序的速度),况且这只是带了一个水壶,要是再带上饭盒呢?还有轮滑、头盔、创可贴、纱布……AK-47 My God,如果带全了就赶上美国大兵了。所以游乐园里还是有个公用“仓库”要来的方便,让大家随用随取(动态链接)。第二,小家伙们带了那么多东西,占了游乐场很多地方,让游乐场拥挤不堪,别的小朋友就进不来了(程序体积大,影响程序和系统的性能)。第三,如果某件物品升级了,比如水壶从一升的改为二升的,那么每个小家伙就必须go home去换新的(重新编译程序,由编译器把新的静态库链接进程序主体里),而第二种情况里,只要游乐场把自己仓库里的水壶换个型号,那么所有小家伙就都在同一时间拥有了大容量的水壶。(悟空!我就一会儿不在,你怎么就乱丢东西?!打到小朋友多不好~~~~~)
        悟空已经急了,我就不再叽叽歪歪了……呃……Win32 API函数是放在Windows系统的核心库文件中的,这些库在硬盘里的存储形式是.dll文件。我们常用到的dll文件是user32.dllkernel32.dll两个文件,还有其它一些dll文件也非常重要,大家要在实践中多积累经验。
        我们知道Win32 API函数是放在dll文件中了,但新问题又来了——我们怎么调用它们呢?这些dll文件是用C语言写的,源代码经C语言编译器编译之后,会以二进制可执行代码形式存放在这些dll文件中,就好像苹果被打碎机打成果酱后装在罐子里一样——你再也分不清哪个是你GF给你的,哪个是你老妈给你的一样。为了能让程序使用这些函数,微软在发布每个新的操作系统的时候,也会放出这个系统的SDK,目前最新的是Win2003 SP1 SDK,据说Vista的马上就要放出来,而且已经把UI的API从核心库中分离出去以提高系统的稳定性了。SDK里有一些C语言的头文件(.h文件),这些文件里描述了核心dll文件里都有哪些Win32 API函数,在写程序的时候,把这些.h文件用#include"....."指令包含进你的程序里,你就可以使用这些Win32 API了。至于程序是怎样链接的,超出了本文的范围——也超出了本人的知识范围:D
         至此,如果你是C语言高手,已经可以使用Windows SDK去调教Windows了!不过,今天我们讨论的是C#语言调用Win32 API的问题。我们现在已经知道API函数放在dll动态链接库文件里,也知道C语言怎么调用它们了,那么C#语言怎么办呢?C#语言是不能使用C语言的.h文件的。C#语言也使用dll动态链接库,不过这些dll都是.NET版本的,具有“自描述性”,也就是自己肚子里都有哪些函数都已经写在自己的metadata里了,不用再附加一个.h文件来说明。现在,我们已经找到了问题的关键点:如何用.NET平台上的C#语言来调用Win32平台上的dll文件。答案非常简单:使用DllImport特性
二.  小试牛刀
        下面,就让我们写一个小程序,试一试如何用C#语言和DllImport特性来调用Win32 API。

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;
     }
}


        新建一个C#的控制台程序,把VS自动生成的代码清空,把上面的代码Copy过去就可以编译执行了。让我们剖析一下这个程序:
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完全一致!这可难煞我们这群初学者——Win32的数据类型比较搞怪,比如什么LPSTR、什么HINSTANCE都是些虾米东东呢?给大家一个小参考,我的Blog里有《Windows数据类型探幽——千回百转你是谁?》系列拙文,可以查一下。另外在此,我从MSDN里摘出一张表来,是常用Win32数据类型与.NET平台数据类型的对应表:
Figure 2 Non-Pointer Data Types

Win32 TypesSpecificationCLR Type
char, INT8, SBYTE, CHAR8-bit signed integerSystem.SByte
short, short int, INT16, SHORT16-bit signed integerSystem.Int16
int, long, long int, INT32, LONG32, BOOL, INT 32-bit signed integerSystem.Int32
__int64, INT64, LONGLONG64-bit signed integerSystem.Int64
unsigned char, UINT8, UCHAR, BYTE8-bit unsigned integerSystem.Byte
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t16-bit unsigned integerSystem.UInt16
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT32-bit unsigned integerSystem.UInt32
unsigned __int64, UINT64, DWORDLONG, ULONGLONG64-bit unsigned integerSystem.UInt64
float, FLOATSingle-precision floating pointSystem.Single
double, long double, DOUBLEDouble-precision floating pointSystem.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的缩写,说白了就是——字符串。所以,用C#里的string类型就对了。
修饰符:要求有相应的DllImport和public static extern

经过上面一番折腾,Win32的MessageBox函数就包装成C#可以调用的函数了:

     [DllImport("User32.dll")]
     public static extern int MessageBox(int h, string m, string c, int type);


        好人做到底,我把四个参数的用处也说一下:
第一个:弹出的MessageBox的父窗口是谁。本例中没有,所以是0,也就是“空指针”。
第二个:MessageBox的内容。本例中是“Hello Win32 API”。
第三个:MessageBox的标题。本例中用的是本人Blog的名字——水之真谛——请大家不要忘记。
第四个:MessageBox上的按钮是什么,如果是0,那就只有一个OK,MessageBox太短了,你将看不全“水之真谛”四个字,于是偶改成了4,这样就有两个按钮了。这些在MSDN的函数用法里都有。不过,我还是非常推荐您阅读一下本人的另一篇拙作《一个Win32程序的进化》 。
        至此,一个麻雀虽小、五毒俱全~~~Sorry  -_-! 五脏俱全的C#调用Win32 API的程序就分析完了。原理并不难吧!应届生拿去蒙HR足够了!真正见功底的地方是你使用MSDN、SDK、.NET Framework类库VC/VC#的熟练程度。相信我——MSDN+SDK+VC/C#绝对足够把Windows收拾得服服帖帖了:D
三. 真的有必要吗?
         嘿嘿嘿嘿……看我的表情,我在坏坏地笑哦!你们都上当啦!操作Windows的底层不一定都要调用Win32 API滴~~~~(哪儿来的砖头!!!)
         我想说的是:.NET Framework是对Win32 API的良好封装,大部分Win32 API函数都已经封装在了.NET Framework类库的各个类里了。如果说Win32 API函数是散落在地上的珍珠的话,那么.NET Framework就是把这些珍珠按种类分放到了各个抽屉里——让我想起我妈来了——我的书放得满地满床的时候我总是能找到,她一收拾我就再也找不到了,郁闷。唉……没办法,我们还是仔细把.NET Framework类库好好翻翻吧,会有很多惊喜哦!
        最后,用一个例子结束我们的文章吧!
        例子是这样滴~~~~~
        那是在很久很久以前,我给一个公司写程序用来控制用户登录,在登录之前,用户不能把鼠标移出登录窗体,因为要控制鼠标,所以我首先想起了调用Win32 API中与Cursor相关的函数来——于是不管三七二十一、花了九牛二虎之力调用了Win32 API中的ClipCursor()这个函数,效果还不错。
        结果前两天翻.NET Framework类库的时候,发现System.Windows.Forms.Cursor类的Clip属性就是专门做这个用的!差点没把鼻子气歪了……请大家自己动手创建一个C#的Windows程序,把下面的核心代码贴到主窗体的双击事件里,试一试。做这个例子的目的就是要告诉大家:1.对类库的了解程序直接决定了你编程的效率和质量——用类库里的组件比我们“从轮子造起”要快得多、安全得多。2.不到万不得已,不要去直接调Win32 API函数——那是不安全的。

         private void Form1_DoubleClick(object sender, EventArgs e)
         {
              Rectangle r = new Rectangle(this.Left, this.Top, this.Width, this.Height);
              System.Windows.Forms.Cursor.Clip = r;
         }


        最后,大家一定非常想知道,.NET Framework都为我们封装好了哪些Win32 API,OK,MSDN里有一篇文章,专门列出了这些。文章的名字是《Microsoft Win32 to Microsoft .NET Framework API Map》请感兴趣的朋友自己阅读。
四.  感恩
        新年快到了,这篇文章也做为一份小小的礼物,一是博大家一乐,二是让我们永远铭记这幸福的时刻。
        送给对我有着知遇之恩的陆经理;
        送给刘莹Lead感谢在工作中给予的指导和支持;
        送给我的Team伙伴乐莲、王勇(Worksoft),没有你们的帮助,我是不可能开始工作的!
        送给我宿舍的兄弟张雄,没有你,我可能要睡在城铁站了。
        送给段玮和陈宁,感谢你们组织的活动和培训。
        送给陈曦、陈建、王勇、常勇、舜贤、挺挺、对面的女孩李芳,还有本组的JJMM,还有小朱……与你们共事是我最大的快乐!

        文章写完鸟~~~~倾城MM大概也把饭做好鸟~~~~回家鸟~~~~


版权声明:本文章受知识产权法保护,如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladey@tom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢.


看贴要回贴,不回贴,小心我用弹弓打你家玻璃!!!

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
CSharp(C#) 调用 C++ SDK dll 摘要 最近3天忙的一个项目,要死了。有个 C++ 写的 SDK dll,需要写成 C# 的接口提供给其他人,项目需要就要死人啊 T_T。接下来就介绍这个项目上使用的东西,下面有说不对的,请大家见谅,谢谢~~~ 文章目录摘要目录1. 非托管调用2. 创建工程,VS20173. C++ 的接口 & 实现4. C++ dll 测试工程5. C++ 中间件设置和问题6. 中间件介绍1. 知识点介... 阅读详情

相关推荐

C# 调用海康相机SDK

一、查找相机设备 /// <summary> /// 枚举相机 /// </summary> public List<string> DeviceListAcq() { var list = new List<string>(); // ch:创建设备列表 | en:Create Device List System.GC.Collect(); //cb

m0_67136031的博客 6263

.NET CORE Swagger+动态API集成

带你从0开始集成Swagger,自定义动态API并加上文档注释。

manmanzainuli的博客 1524

游戏战斗系统架构设计的演绎之路——从一坨意大利面条到一座精密钟表

摘要:游戏战斗系统架构设计的演进之路 本文系统梳理了游戏战斗系统从早期街机到现代3A大作的架构发展历程。70-80年代的街机游戏采用基础碰撞盒判定(如《街头霸王》);90年代实现动画融合与状态机架构(《最终幻想》《拳皇》);2000年后MMO引入服务器验证与同步技术(《魔兽世界》);3D时代融合物理引擎与智能AI(《GTA5》《只狼》);移动端则发展出轻量化架构与云端判定(《王者荣耀》)。现代战斗系统已实现模块化、数据驱动和热更新,未来趋势是AI裁判与云战斗系统。这一演进过程展现了技术与创意的完美结合,数百

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 768

C#调用C++封装的SDK库(dll动态库)——上

要把VS创建的DLL动态库,给C#代码来调用(并且我的动态库中还包含我的计算类)C#调用C++封装的SDK库(dll动态库)本篇文章就介绍如何来封装,并提供调用。但是,我遇到了一个场景:需要把VS创建的DLL动态库,给C#代码来调用(并且我的动态库中还包含我的计算类)。本篇文章就介绍如何来封装,并提供调用

ifeng12358的博客 3606

【asp.net core】实现动态 Web API

序言:远程工作已经一个月了,最近也算是比较闲,每天早上起床打个卡,快速弄完当天要做的工作之后就快乐摸鱼去了。之前在用 ABP 框架(旧版)的时候就觉得应用服务层写起来真的爽,为什么实现了...

kaixincheng2009的专栏 2422

ASP .NET之动态WebApi实践

动态WebApi实践框架名称 SunLight.DynamicWebApi创建一个普通的WebApi引入Swagger Api界面(可选)2.1 为什么要引入?2.2 如何引入2.2.1 安装框架2.2.2 修改SwaggerConfig.cs2.2.3 创建项目XML注释文档2.2.4 修改WebApiConfig.cs2.2.5 测试Swagger引入SunLight.DynamicWebAp...

war3ismylove的博客 1957

转载暴强:从.NET平台调用Win32 API

 前段时间关注过了刘铁猛先生的这篇文章,有点启发.觉得写的不错,起到了抛砖引玉的作用.为了使更多人获益,在此转载.同时向刘先生致谢!  好文章共享,尊重别人的劳动成果!同时在此声明,如有转载者,请按作者的要求转载!  作者:刘铁猛日期:2005-12-20关键字:C# .NET Win32 API版权声明:本文章受知识产权法保护,如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一

masky5310的专栏 346

继续深入C#调用win32 API的学习

找到几篇好文章暴强:从.NET平台调用Win32 API  作者:刘铁猛 Calling Win32 DLLs in C# with P/Invoke 为什么是static extern 类型上面这篇文章讲的不错Now, notice that the MessageBeep method was declared as static. This is a requi

liuchang631的专栏 650

使用C#注册全局快捷键

天试了一下这个, 记录下来, 以后我给自己做小工具时, 肯定用的到.   注册/注销全局快捷键需要用user32.dll中的这两个api: RegisterHotKey UnregisterHotKey 所以使用C#注册全局快捷键就是要用C#调用user32.dll中的这两个函数,   问题1 C#调用dll 这其中涉及的问题有: 1.为了使用[DllImport("...

SAP => Simplify Anything Possible 475

中琅条码打印软件SDK C#调用

中琅条码打印软件SDK C#即成调用 1.新建项目 完成 2.复制sdk中的dll等文件到对应的位置 然后打开他们的sdk把这个文件放你项目目录下面我新建了一个DLL文件夹在项目路径下 在你的项目里面添加两个cs文件一个叫LabelPainter_SDK_Wrapper另外一个叫JaggedArrayMarshaler,只要改LabelPainter_SDK_Wrapper.cs中的文件就行了 LabelPainter_SDK_Wrapper.cs如下 using System; using Syst

BryantJamesHua的博客 850

openssl命令数据摘要详解(SM3、sha256、MD5、dss1、mdc2、ripemd160)

SM3是由中国密码学家设计的密码哈希函数,是中国国家密码管理局(National Cryptographic Authority,简称:CNCA)颁布的国家密码算法标准。SM3属于密码杂凑函数家族,它可以计算任意长度的消息并生成固定长度(256比特,即32字节)的哈希值。SM3生成的哈希值长度为256比特(32字节),不管输入消息的长度如何,输出始终是固定的。SM3将输入数据划分为512比特(64字节)的分组,并对每个分组进行处理。

N阶二进制的博客 4424

1990-2024年 省级-乡村振兴指数数据(+参考文献)

乡村振兴指数以“产业兴旺、生态宜居、乡风文明、治理有效、生活富裕”为总要求,通过构建多层级指标体系,对乡村发展的全面性、系统性进行量化评估。其目标值通常设定为“到2035年基本实现农业农村现代化”,旨在通过动态监测与横向对比,揭示乡村发展的现实水平、区域差距及短板弱项,为政策制定、资源分配和实践优化提供科学依据。实施乡村振兴,产业兴旺是重点,生态宜居是关键,乡风文明是保障,治理有效是基础,生活富裕是根本。相关数据地区 年份 各省乡村振兴指数 人均农业机械总动力(千瓦) 粮食综合生产能力(万吨) 农业劳动生产率(元/人) 规模以上农产品加工企业主营业务收入(亿元) 农药、化肥施用量(万吨) 畜禽粪污综合利用率(%) 对生活污水进行处理的行政村占比(%) 对生活垃圾进行处理的行政村占比(%) 卫生厕所普及率(%) 农村绿化率(%) 农村居民教育文化娱乐支出占比(%) 农村义务教育学校专任教师本科以上学历比例(%) 农村居民平均受教育年限(年) 有线电视覆盖率(%) 开通互联网宽带业务的行政村比重(%) 乡村文化站数量(个) 村主任、书记”一肩挑“比例(%) 已编制村庄规划的行政村占比(%) 已开展村庄整治的行政村占比(%) 农民人均纯收入(元) 农民人均收入增长率(%) 城乡居民收入比(%) 农村贫困发生率(%) 农村居民恩格尔系数(%) 每百户汽车拥有量(辆) 农村居民人均住房面积(平方米) 安全饮用水普及率(%) 村庄道路硬化率(%) 人均道路面积(平方米) 农村每千人拥有卫生技术人员数(人)

上一篇: 程序员们纷纷表示 内牛满面 VS2010视频共5季
下一篇: 崇州 鸡冠山 白塔湖 九龙沟 罨画池 陆游祠{组图及介绍}
小风花
博客等级 码龄8年 73粉丝 207原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值