1,试着自己从小程序开始写起。
写小程序?对!在你写小程序时应该拣你最感兴趣的程序写,否则有可能你写到一半以后会觉得自己这个程序写得毫无价值,简直是在浪费时间,最后到头来还是功亏一篑。这里我拿什么当题材呢?我在这里也想了很久,最后还是决定选择一个注销Windows程序来做题材(其实这是我当初学API最想实现的功能)。
注销Windows也就是退出Windows(重启,关机等都一样,不都是退出的意思吗?),根据表面意思在API浏览器中输入Exit(退出)Windows,看看有没有这个API?这里提醒一下,你在查找这个API的时候还会看到ExitWindowsEX这个API,其实这两个API实现的功能一样,前者是用在16位操作系统上,只不过在Win32位操作系统上一般都使用ExitWindowsEX。所以这里就使用后者。API见以下:
Private Declare Function ExitWindowsEx Lib \al uFlags As Long, ByVal dwReserved As Long) As Long 看看里面的两个参数,ByVal uFlags As Long?这里我们需要传入一个整形数字,可是应该传入什么数字呢?这里说下,API中的参数可以传入不同的值,不同的值从而导致产生不同的结果。分析API中参数应该传递哪些值其实是有技巧的,以后大家只要是看到参数字符中包函Flags字符的话那就说明该参数可以被传入一个或多个标志,并且大部分都是传入API常数(什么是API常数就不用我说了吧)。说白话点,就是我们可以传入多个API常量,并且可以在API浏览器中找到,当然,不一定所有的API常数都可以在API浏览器中找到,不过大部分都可以。
在API浏览器查API常量时我前面就教过大家技巧,现在该是我们实践的时候了,分析如下:
Exit :头一个大写字符 E Windows:头一个大写字符 W Ex :头一个大写字符 E 组合 :EWE_
好了,现在在API浏览器的中常数中找找,咦?发现好像没有以EWE开头的常数??只发现以EWX开头的?现在先别着急,咱们回过头来再分析下,咱们是失败在最后一步Ex上,这里我不得不否决我前面教过大家的技巧,但是又不能完全否决,出现这种情况时就需要大家灵活运用API常数的分析法,可以看到EWX最后一个X是以Ex的X作结尾的,以这种方法做API常数开头的不止这一个,所以这里我特意留了一个陷阱,希望给大家带来一些经验将来能够灵活运用。现在我把关机uFlags所能用到的相关常数发上来,如下:
Private Const EWX_FORCE = 4 Private Const EWX_LOGOFF = 0 Private Const EWX_REBOOT = 2
Private Const EWX_SHUTDOWN = 1
怎么样?看得懂吧?英语稍微好一点基本上没问题。不过这里我还是要解释一番,照顾新手嘛!
EWX_FORCE 前面的 EWX_ 我就不说了,关键是看 _ 符号后面的,Force 单词翻译:强制,强迫。人工在翻译一下(我英文不好,翻译错了请别见怪,呵呵 ^_^ ),意思是说:强制执行ExitWindowsEx API关机函数。不知道这样解释你能不能明白。那到底这个常数有什么用呢?这里我们先回忆一下以前关机的时候,当Windows无法关闭某些窗口的时候就停止继续关机了,最后还得把无法关闭的窗口手动关闭方可,现在,如果我们使用这个常数进行关机,那Windows不管你窗口能不能关闭,直接强制关闭。希望你懂了。
EWX_LOGOFF 这个嘛,貌似组合单词,不可直接翻译,那样就不是那个意思了。Logout Off,是这样写吗?注销的意思。
EWX_REBOOT 不浪费时间了,直接说明意思:重新启动。
EWX_SHUTDOWN 关机。
至于第二个ByVal dwReserved As Long,为保留整形,一般为0即可。至于为什么为0,大家可以到网上下载一些专门讲解API函数的电子书看看,里面有大部分API函数的详细讲解。或者下载VS.MSDN看看,在MSDN中说Windows 2000/95/98/Me中此参数忽略,XP中是指定关机消息说明。
最后看看这个API为Function声明,说明该函数有返回值,返回值为Long,MSDN中说:如果执行成功,则返回非零,否则为零。
现在上面已经把这个关机API和相关参数常量都给你分析透了,你可别告诉我你还不知道怎么写?好了,这里我们做一个定时注销程序,呵呵,虽然很简单,不过很多时候用得上哦!在Form窗口上添加Timer控件,Interval 设置为1000,Enabled 设置为 True。好了,代码如下:
Private Declare Function ExitWindowsEx Lib \(ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Private Const EWX_LOGOFF = 0 Private Sub Timer1_Timer() Static i As Integer
i = i + 1
Me.Caption = i '这一步纯粹是想看看当前已经执行到几秒了?可不要
If i = 10 Then '秒数判断,可以根据自己的需要进行运算 ExitWindowsEx EWX_LOGOFF, 0 End If End Sub
其实我都有点不想分析了,不过为了照顾大众,不得不说下,Static i As Integer 静态变量(问:啥叫静态变量?答:我晕!),i = i + 1是每执行Timer一次i就加1,Timer的interval
设置为1000,1000为一秒,2000为二秒。。。。后面一个If i = 10 Then是判断当i=10以后,也就是10秒,就执行注销,这个时候你可别忘了保存好你的其它没有保存的文件哦,如果没保存资料丢失的话偶不承担任何法律责任的。其实这里我们可以自己做一个,如可以写成这样:ExitWindowsEx EWX_LOGOFF Or EWX_FORCE, 0,其中用了Or运算,整体的意思是强制Windows注销。这样理解就够了,只要能让你明白。
现在我又要说一下了,不说不行的!就是在API中使用 Or 运算,关于Or运算符VB书中都有详细解释的,别告诉我你没看?没看马上去看!上面EWX_LOGOFF Or EWX_FORCE 的使用是把 注销 和 强制 进行Or位运算,对两个数值执行按位析取,这里涉及到二进制运算,说多了你可能不明白(如果你还是想追根到底的想知道到底是怎么一回
事
的
话
,
我
也
没
办
法
,
给
个
网
址
你
慢
慢
看
http://book.csdn.net/bookfiles/110/1001103366.shtml),我就说简单点的吧,以后如果你想组合两个API常数的功能,一般都是用 Or 进行运行的。如上面写的。
好了,保存其它文件,然后F5运行之,看着Form标题的数字慢慢添加,当为10时,Windows开始注销。。。
小提示:在使用EWX_SHUTDOWN的时候你可能会感觉没有作用,主要是NT系统的安全性提高,需要用其它API进行提升自己的权限才可以。关于如何提升应用程序权限请百度一下。
2,先从一些最简单的API开始
无疑自己试着写程序是最好的提升方法,学完一些知识以后自己试着写写,这样能让你理解的更快更好,好了不说废话了,接着往下看。
最简单的API,呵呵,哪些最简单呢?这个我也说不好,这样吧,咱们就从Get(获取)开始,那Get什么呢?Window(窗口),还是从窗口下手吧,这样更接近我们日常的编程,谁叫这是一个Windows操作系统呢?先列几个常用的API:
GetWindow、GetWindowDC、GetWindowLong、GetWindowRect、GetWindowRgn、GetWindowsDirectory、GetWindowText、GetWindowThreadProcessId
还有很多,我就先列举几个简单点的,咱们就从这几个中间随便抽几个来讲讲吧。
先从GetWindowText下手,大家就表面的意思进行理解下,Get(获取)Window(窗口)Text(文本),Very Good!这个API以前不错的,可以获取密码框中的密码,呵呵,说到这里,我估计有些人开始兴奋起来了!那好,Follow Me!
新建一个Form窗口,然后添加一个CommandButton,Caption设置为:显示密码。接着添加两个TextBox,Text1属性设置:PasswordChar=*;Text=123456789,Text2的属性基本上没有什么需要设置的,只需要把Text属性为空就可以了,它主要是用来帮助咱们显示出密
码的。好了,在Form1代码框中填入以下代码:
Private Declare Function GetWindowText Lib \Alias \(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long Private Sub Command1_Click() Dim sBuffer As String
sBuffer = Space(255)
GetWindowText Text1.hwnd, sBuffer, 255
Text2.Text = sBuffer End Sub
OK,F5运行,点击Command1,怎么样?Text1中的密码字符显示在Text2中了吧?你可以再更改下Text1中的密码,然后再点击Command1试试。也许你觉得会多此一举,为何不Text2.Text=Text1.Text这样?如果真的这样的话看似简单,那你就学不到API了。
又到了开始分析的时候了,打起精神来,先看第一句:Dim sBuffer As String,不用说,声明一个字符串变量呗!接着看第二句:sBuffer = Space(255) 那这一句呢?有些人可能不知道了,没事,我会仔细讲的。Space是VB内置的字符串处理函数,VB中的帮助文件中有说明:
开始{
本示例使用 Space 函数来生成一个字符串,字符串的内容为空格,长度为指定的长度。 Dim MyString
' 返回 10 个空格的字符串。
MyString = Space(10)
' 将 10 个空格插入两个字符串中间。
MyString = \
}结束 很显然,我这一句是要分配255个空格字符串内存,为啥要用分配?这都是为后面所要用到打定的基础。接着往下:
GetWindowText Text1.hwnd, sBuffer, 255 这一步是关键,通过它来获取咱们想要的窗口文本,看第一个参数,我前面讲过hwnd一般都是需要传入句柄的,这时咱们传入了Text1.hwnd(Text1控件的句柄),第二个参数,lpSting为字符串变量,所以这里咱们传入sBuffer字符串变量。最后一个cch为Long整形,所以理应传入数字,这里我们传入了255。现在又有人想问了,为什么需要这么传入值?貌似和以前的传入不一样?确实!一刚开始你可能搞不懂,这时候我先讲讲大概的意思,我们用GetWindowText来获取窗口中的文本,当获取成功以后,理所当然会返回窗口中的字符串,但是当我们用这个API进行获取时,必须需要一个缓冲来保存我们所获取的字符串,你如果不信去试试把sBuffer = Space(255)去掉,
后面的255其实就是告诉这个API我们缓冲字符串的大小,这里再告诉大家一个技巧,以后只要是看见包函有cch字符时,大部分都是输入相关类型的大小。
再附加一点,就里我说过,hwnd是用来传句柄的,你也可以传入其它窗口句柄,只要其它窗口有文本,都是可以通过这个API获取的。还有Text2.Text = sBuffer其实是可以先把sBuffer处理一下再传给Text2.Text的,关于字符串处理这里不讲。
好了,分析结束,来个小提示:在Windows操作系统中,任何有句柄的东东都可被看作为一个窗口。另外你可能会去试试QQ的密码框,^_^ 这里我要告诉你一下,无法成功,为什么无法成功呢?这是一个技术问题目前不提!
接着再来试试GetWindowsDirectory,大家看表面意思吧!Get(获取)Windows(就是Windows目录)Directory(目录),也就是获取咱们那个系统目录,如:C:\\Windows。可能我的Windows目录中在C盘,而其它人的可能在D盘、E盘也说不定,所以有的时候软件需要这个API进行获取操作系统具体的Windows目录。
好了,还是新建一个标准EXE,添加一个CommandButton,属性Caption=显示Windows目录,OK,写入以下代码: Private
Declare
Function
GetWindowsDirectory
Lib
\
Alias
\al lpBuffer As String, ByVal nSize As Long) As Long Private Sub Command1_Click() Dim sBuffer As String
sBuffer = Space(255)
GetWindowsDirectory sBuffer, 255
MsgBox \目录在: \
End Sub
分析!第一个Dim sBuffer As String字符串变量,sBuffer = Space(255)缓冲字符串,GetWindowsDirectory sBuffer, 255这个和上面所讲的一样,最后一个参数nSize为Long整形,所以传入数值,那传入什么数值呢?Size???当然是缓冲字符串大小了,以后遇到这个nSize一般也是传入相关类型的大小的。MsgBox \目录在: \& sBuffer,是用MsgBox消息框显示出Windows目录的位置。
OK,恭喜你,你又会使用了一个API,还要继续吗?(问:当然还要啦!答:最后一次哦!)
GetWindowThreadProcessId,这次玩玩窗口进程,我估计有些人只要看见与进程有关的东东也会变得兴奋,呵呵!好了,先看看这个API是什么样的?如下:
Private Declare Function GetWindowThreadProcessId Lib \\al hwnd As Long, lpdwProcessId As Long) As Long
Alias