公司要搭建网站,吉林市今天消息,建设汽车行业网站,怎么评判一个网站做的好与坏作者#xff1a;刘铁猛日期#xff1a;2005-12-20关键字#xff1a;C# .NET Win32 API版权声明:本文章受知识产权法保护#xff0c;如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladeytom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢.小序Win32 …作者刘铁猛日期2005-12-20关键字C# .NET Win32 API 版权声明:本文章受知识产权法保护如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladeytom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢. 小序 Win32 API可以直接控制Microsoft Windows的核心因为APIApplication 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.dll和kernel32.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;导入“运行时-交互服务”。喔~~~~运行时的交互服务不就是“动态链接”吗感谢Microsoft2. 然后我们就可以制造一个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 Typechar, INT8, SBYTE, CHAR8-bit signed integerSystem.SByteshort, short int, INT16, SHORT16-bit signed integerSystem.Int16int, long, long int, INT32, LONG32, BOOL, INT 32-bit signed integerSystem.Int32__int64, INT64, LONGLONG64-bit signed integerSystem.Int64unsigned char, UINT8, UCHAR, BYTE8-bit unsigned integerSystem.Byteunsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t16-bit unsigned integerSystem.UInt16unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT32-bit unsigned integerSystem.UInt32unsigned __int64, UINT64, DWORDLONG, ULONGLONG64-bit unsigned integerSystem.UInt64float, FLOATSingle-precision floating pointSystem.Singledouble, long double, DOUBLEDouble-precision floating pointSystem.DoubleIn 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那就只有一个OKMessageBox太短了你将看不全“水之真谛”四个字于是偶改成了4这样就有两个按钮了。这些在MSDN的函数用法里都有。不过我还是非常推荐您阅读一下本人的另一篇拙作《一个Win32程序的进化》 。 至此一个麻雀虽小、五毒俱全~~~Sorry -_-! 五脏俱全的C#调用Win32 API的程序就分析完了。原理并不难吧应届生拿去蒙HR足够了真正见功底的地方是你使用MSDN、SDK、.NET Framework类库VC/VC#的熟练程度。相信我——MSDNSDKVC/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 APIOKMSDN里有一篇文章专门列出了这些。文章的名字是《Microsoft Win32 to Microsoft .NET Framework API Map》请感兴趣的朋友自己阅读。四. 感恩 新年快到了这篇文章也做为一份小小的礼物一是博大家一乐二是让我们永远铭记这幸福的时刻。 送给对我有着知遇之恩的陆经理 送给刘莹Lead感谢在工作中给予的指导和支持 送给我的Team伙伴乐莲、王勇Worksoft没有你们的帮助我是不可能开始工作的 送给我宿舍的兄弟张雄没有你我可能要睡在城铁站了。 送给段玮和陈宁感谢你们组织的活动和培训。 送给陈曦、陈建、王勇、常勇、舜贤、挺挺、对面的女孩李芳还有本组的JJMM还有小朱……与你们共事是我最大的快乐 文章写完鸟~~~~倾城MM大概也把饭做好鸟~~~~回家鸟~~~~ 版权声明:本文章受知识产权法保护如果阁下想转载,在转载的时候烦劳阁下连同在下的姓名一起转载,并向bladeytom.com发一个Mail,我很想知道我的文章都去哪里了.谢谢.转载于:https://www.cnblogs.com/C-CHERS/p/4875501.html