VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 69677|回复: 178

[原创] VB API 中级入门(接VB API初级入门)(一)

[复制链接]
 楼主| 发表于 2007-5-22 23:32:46 | 显示全部楼层 |阅读模式
阔别多日,这次再让我们回到VB API的神奇世界中。鉴于上次文章作品给网友们的反响很大,并强烈要求继续写下去,所以这些天特意抽了一点点时间。不过最近因为身体很不适,所以坐在电脑前的时间也比以前少了,以致拖到现在才把文章发布出来。呵呵,好了,废话不多说了,转入正题。


        这次咱们来深入了解API在VB程序中的运用,并且有些复杂的API使用可能会使你感到很悲观,不过我会尽量用最容易让人理解的方式表达出来。注:如果你是一个刚入门API的初学者,那么请你先看看关于我写的初级API入门教程,也许会对了解API有帮助,地址:http://www.vbgood.com/viewthread.php?tid=50241&extra=page%3D1


        一、API的类型结构。


            API的类型结构与VB中差不多,一般声明时使用Type定义类型。如果你不懂的话麻烦你先打开你的VB入门教程书看看。好了,文字理论咋不多说,用实例证实理论(偶喜欢这句话)。


        1,在Form窗体上用API画文字,最初了解类型结构填充


            ;Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

        ;Private Const DT_CENTER = &H1

        ;Private Type RECT
                    Left As Long
                    Top As Long
                    Right As Long
                    Bottom As Long
        End Type


        Private Sub Form_Load()
                Dim lpRect As RECT

                    Me.AutoRedraw = True
                Me.ScaleMode = 3
                            '填充结构
                With lpRect
                    .Left = 0
                    .Top = 0
                    .Right = Me.ScaleWidth
                    .Bottom = Me.ScaleHeight
            End With

                    DrawText Me.hdc, "这是文字效果", -1, lpRect, DT_CENTER
        End Sub


            好了,咱们开始分析,首先看Form_Load里面的代码。


            Dim lpRect As RECT。这一句是声明一个RECT自定义类型,这个类型可在VB浏览器的类型中找到。


            Me.AutoRedraw = True。这一句其实就是设置当前窗体的AutoRedraw属性,设为True,表示持久输出图像。不懂查帮助。


            Me.ScaleMode = 3。设置当前窗体的像素模式。至于为啥要设置为3,下面将会讲到。


            With lpRect...End With。从With 到 End With为填充咱们声明的lpRect类型结构。具体看里面的。


            .Left=0。这里相当于x坐标的初始值。


            .Top=0。这里相当于y坐标的初始值。


            .Right = Me.ScaleWidth。Right表示从Left开始的宽度。这里赋值为Me.ScaleWidth表示当前窗体像素的宽度。


            .Bottom = Me.ScaleHeight。同上。Bottom表示从Top开始的高度。Me.ScaleHeight表示当前窗体像素的高度。


            关键的就是下面一句,是它帮助我们在窗体中画出文字的。这里说一下为什么需要把当前窗体的坐标度量单位(ScaleMode)改成3(Pixel像素),因为Windows不管画什么都是以像素为单位,所以我们为了确定咱们所画的文本显示在正常位置,就必须使用像素为单位!明白了么??(问:还是不明白?答:默默无语两眼泪啊~~)


            DrawText Me.hdc, "这是文字效果", -1, lpRect, DT_CENTER


            现在分析这条API。看看里面需要传入的参数:ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long


            ByVal hdc As Long。hdc为Long整形,所以应该传入数值,不过给大家一个技巧,以后凡是看到hdc这个变量字符,表示需要传入的为一个hdc句柄,注意可不是hwnd句柄哦!这个句柄窗体和Picture控件都有,大家注意看就是了。


            ByVal lpStr As String。传入字符串。这里就是咱们需要画到窗体上的文本。


            ByVal nCount As Long。传入数值。看看里面的声明字符nCount,可以看出来这与数目有关,与什么数目呢?当然是文本罗。也就是说要显示的字符个数,一般如果需要全部显示出来可设为-1即可,表示显示所有字符。


            lpRect As RECT。一个Rect类型,这里需要使用Rect类型,上面我们已经在API浏览器找到了这个类型并声明了,所以只需要传入相应的类型声明就可以了。不过这次与我上一次讲的有所不同,上次是通过API类型结构获取相关的信息,而这次需要你把API类型结构填充好以后再传入进去。希望大家在这里注意下。可能有人要问了,那为什么这次就要这么做?我的回答是:因为API并不是万能的和灵活的,有的时候需要我们人为的设置一些参数来完成自己所需要这个API的功能,大家可以通过上面的结构填充就可知道,我们所要画文本的整个范围就是整个Form窗体的范围啊!


            ByVal wFormat As Long。传入数值,不过可以看看nFormat声明字符,可以想像这里可能需要传入这个API的使用格式,就如我们前面所讲的那样。现在打开API浏览器,在常数中找找,输入这个API的开头,Draw(D)Text(T)=DT_,可以看到有很多吧。具体这些都是什么意思可以查查相关的API资料。这里我们只传入了一个DT_CENTER常数,意思是居中显示。默认可以为0,因为这里为文字显示格式,所以你什么格式也不想要的话可设为0以后文字显示在左上角。


            OK。F5运行之。。。窗体中间正常显示“这就是文字效果”的几个文字。


            至此这里API相关结构的填充与获取我不想再多说了,不懂的话建议把我以前发的API入门帖子与这里的第一小节一起看看,或许你会明白些什么??

评分

参与人数 4威望 +11 人气 +1 收起 理由
火龙 + 2 + 1 精品文章
584296826 + 2 精品文章
xiaochengjushi + 2 好东西
wjp1015 + 5

查看全部评分

本帖被以下淘专辑推荐:

发表于 2007-5-22 23:35:15 | 显示全部楼层
又开始新的教程了,得顶了,支持你~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-22 23:35:31 | 显示全部楼层
二、Windows 消息


            可以说这节是本文中的重点,当你能理解该节中的所有内容时,我相信你已经可以用该方法写出不错的程序功能了,好了,不说多了,接着往下来看。


            在了解消息之前,先让我们看看Windows 消息到底是什么?


            Windows系统是一个消息驱动的OS,所以操作都是基本消息驱动的,这就好比我用鼠标按下一个按钮,这时Windows会先发送该鼠标的左键按下消息,也就是WM_LBUTTONDOWN到你按下的那个CommandButton,这时就会激发按钮的CommandButton_MouseDown事件,然后松开鼠标,Windows这时会发送WM_LBUTTONUP消息,激发CommandButton_MouseUp事件,说明该鼠标按键已经弹起(松开),这时就会激发咱们VB中的 CommandButton_Click 事件,所以你点击某个按钮以后就会执行相应的操作。这里我不想说得太深太复杂,只是想以这种简单的理解方式让你明白Windows消息到底是什么,也许说得太含糊,但是对你第一次理解这东西已经足够了!


        实践1:


            现在就让我们以消息来写一个入门程序,先是打开VB(问:废话。答:……),然后打开API浏览器(问:早打开了。答:……),然后在API浏览器找到 SendMessage ,再然后在API 常数中找到 WM_CLOSE,好了,在VB工程中新建一个标准EXE,添加一个Command1按钮,写入以下代码:

            Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

            Private Const WM_CLOSE = &H10

            Private Sub Command1_Click()
                        SendMessage Me.hwnd, WM_CLOSE, 0, ByVal 0&
            End Sub


            好了,先看看 SendMessage 这个API,第一个参数,hWnd 为Long,所以传入一个对象的句柄,第二个参数 wMsg 同样为 Long,这里要说一下,在该API的第二个参数,大多数都是传入以 WM_ 为开关的常数,希望大家注意!第三个 wParam 也是 Long,该参数的意思大多数是取决于第二个参数 uMsg ,这里传入的常数是 WM_CLOSE,所以这里输入 0 即可,最后一个参数,lParam 为 Any,Any是什么意思这里我说一下,也就是是说明该参数可以指定为任何标准数据类型,允许将任意数据类型传递给该参数!希望你明白,该参数的值也是取决于 uMsg。


                    再看看 Command1_Click 事件中的代码,其中使用了SendMessage API,第一个是当前的窗口句柄,至于什么是句柄我在API初级入门时讲过,第二个为 WM_CLOSE 常数消息,也就是说给当前窗口发送关闭消息,第三、四个参数分别为0,具体参数我已经说过,取决于你在 uMsg 传入的常数。

                    现在 F5 运行点击Command1按钮试试。

                    小提示:注意这里的句柄当然也可以输入其它窗口的句柄,执行效果同上面一样,可以关闭你传递的那个句柄窗口!自己试一下,具体怎么获取窗口句柄我在VB初级入门时讲过,自己去试试吧!!!


                实践2:


                    现在我们开始第二个消息程序,还是使用 SendMessage ,这次我们是要给一个按钮传递 Click(点击)事件,最近貌似有些人在问这个问题?现在就写出来大家实践实践。


                    新建一个标准EXE,添加两个 CommandButton 控件,分别为 Command1 和 Command2 ,然后输入以下代码:

                    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

            Private Const BM_CLICK = &HF5

            Private Sub Command1_Click()
                        SendMessage Command2.hwnd, BM_CLICK, 0, ByVal 0&
            End Sub

            Private Sub Command2_Click()
                        MsgBox "command2"
            End Sub

                    这里先看看 BM_CLICK 常数,这个常数好像在VB自带的API浏览器中没有,所以大家可以把该常数自行复制到各自的VB程序中,也可以新建一个记事本保存下来,也可以把它添加到VB的API浏览器文本中等等。


                    再来看看 Command1_Click 事件,可见调用了 SendMessage API 向 Command2 中发送了 BM_CLICK 消息,该消息为按钮点击消息,后面的参数取决于 wMsg,所以后面两个为0即可,现在说一个为什么最后一个参数是写成 Byval 0&,写成这样的原因主要是因为最后一个参数变量,大家可以看看最后的参数变量 lParam As Any ,Any 是什么意思我已经说过,0& 后面的 & 其实为 Long 的简写,说白了 & 就是 Long 的意思,当然你可以在你程序写在 Dim ABC& 声明一个 Long 类型,而 Byval 0& 代表着是以传值方式进行传递该参数。不明白意思不要紧,翻开你的VB书多看看过程这章。

                    最后一个 Command2_Click 的 MsgBox "command2" 自然是显示一个消息。

                    好了,F5 运行试试。

                    小提示:同样该 hWnd 参数可以传递其它按钮句柄,实现效果同上面一样。

                            现在让我们看看 GetWindowLong 和 SetWindowLong 这两个“超级”API,为什么说超级呢?因为我们实现子类化少不了它们啊!



                        未完待续……

评分

参与人数 1威望 +2 收起 理由
石油暴徒 + 2 我很赞同,谢谢

查看全部评分

回复 支持 反对

使用道具 举报

发表于 2007-5-23 08:33:38 | 显示全部楼层
想请教个问题,我如何知道其它窗体上的一个控件句柄,比如我做的程序只有FORM1窗口,现在我想在已经运行的程序如FORM2窗口上的TEXT1传入“你好”信息,该怎么做?
回复 支持 反对

使用道具 举报

发表于 2007-5-23 09:00:56 | 显示全部楼层
支持菜新,永远的好老师
回复 支持 反对

使用道具 举报

发表于 2007-5-23 09:04:18 | 显示全部楼层
支持``````````````````````````
回复 支持 反对

使用道具 举报

发表于 2007-5-23 09:35:43 | 显示全部楼层
已经有人写了生动含demo的经典东西->Win32 API 讲座

http://www.vbgood.com/viewthread.php?tid=54482&extra=page%3D1
回复 支持 反对

使用道具 举报

发表于 2007-5-23 09:37:04 | 显示全部楼层
基于vb的ocx和dll属性,代码论文重用性

直接调用这个api吧。

  今天开始,我向大家讲有关API的是实质性内容。我们就从"句柄"开始。
    只要你来到了API的世界,经常碰到的问题之一就是句柄。那么究竟什么是句柄呢?
    如果你从来都没有听说过"句柄"这个词,可能首先觉得句柄当中有很多内容。其实不然,所谓句柄实际上是一个数据,是一个Long (整长型)的数据。在API中,它经常是以一个参数的形式传递给各种API函数。如:
Public Declare Function GetWindow& Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long)

    其中,hwnd就是句柄。在VB里,句柄是一种属性,您打开VB中的对象游览器看一看Form窗体或者PictureBox控件等究竟有没有hwnd属性。是有的。VB中的解释是这样的∶
    Microsoft Windows 运行环境,通过给应用程序中的每个窗体和控件分配一个句柄(或 hWnd)来标识它们。hWnd
属性用于Windows API调用。许多 Windows 运行环境函数需要活动窗口的 hWnd 作为参数。

   如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?

    为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载
(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。
句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象

    但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。
    在VB中获得一个对象的句柄十分简单,如要获取Form1窗体的句柄,就可以这样写∶Form1.Hwnd

    对象的句柄还可以通过API函数来获得,如∶

GetActiveWindow        返回位于最顶部的具有输入焦点的窗口句柄
GetFocus        获得当前线程里补获鼠标输入的窗口句柄
GetForegroundWindow        从位于前台的线程里返回活动窗口的句柄
GetCursor        取得当前指针的句柄
GetDesktopWindow        获取整个桌面的句柄
GetWindow        获得一个窗口的句柄,该窗口与某源窗口有特定的关系
《以上函数说明均可在WinAPI.hlp文件中找到。》

    本教程提供了演示例程──play1.vbp,正是为了说明这些函数的具体用法的。
程序运行后,用鼠标做一些任何你想做的事情,并观察各项目数据的变化。
通过本程序,注意观察以下几点∶
1,线程内与线程外。(VB不支持多线程)。其他应用程序对此程序来说都是线程外。
2,在windows95操作系统下,各个窗体(包括一些控件,如文本框,图片框等,MICROSORT对它们均统称为窗体)拥有各自的鼠标指针。这和win16下各应用程序使用同样一个指针是截然不同的。

3,每次从新启动,各窗体的句柄都有所变化。Text5 的装载和卸载过程中,句柄始终是在变化着的。这说明了上面提的影院售门票中存在的现象是真实的。
    获得对象句柄的函数还有很多,以后碰到它们时再介绍给大家

[ 本帖最后由 weiyi75 于 2007-5-23 09:38 编辑 ]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-23 12:24:31 | 显示全部楼层
想请教个问题,我如何知道其它窗体上的一个控件句柄,比如我做的程序只有FORM1窗口,现在我想在已经运行的程序如FORM2窗口上的TEXT1传入“你好”信息,该怎么做?



        这次我专门为你开一个小灶,这是第一次,不过也是最后一次!好了,现在让我们看看如何向其它窗口的文本框传入字符串.还是老样子,新建一个标准EXE,接着新建两个Form窗体,分别为 Form1 和 Form2 ,现在我们在 Form1 中添加一个 CommandButton 按钮,然后再在 Form2 中添加一个 TextBox 文本控件和一个 CommandButton 按钮控件,现在在 Form1 中写入以下代码(一会下面有相关的源码下载):


        Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

        Private Const WM_SETTEXT = &HC

        Private Sub Command1_Click()
                SendMessage Form2.Text1.hwnd, WM_SETTEXT, 0, ByVal "abcdefg"
                SendMessage Form2.Command1.hwnd, WM_SETTEXT, 0, ByVal "hehe"
        End Sub

        Private Sub Form_Load()
                Form2.Show
        End Sub


        其它的我不再分析了,大家注意看就是了,现在让我们看看 WM_SETTEXT 这个常数,该常数所代表的意思是向某对象发送设置文本消息,具体可以参考MSDN,其它的参数还是老样子,第一个是对象句柄(也可以说控件句柄),第二个是你给某某对象发的消息,第三个 wParam 参数我上面说过,以 wMsg 的值为定,这里保留为 0,现在关键是看看最后一个,lParam ,该参数为一个 Any 类型,也就是说我们可以传递任何值给任何对象,也就是说我们 wMsg 参数传递的为 WM_SETTEXT 消息,第三个参数为 Long 长整形,所以无法传递字符串,只能看最后一个,而恰好最好一个是可以传递任何类型的参数,所以这里就把我们需要传递的字符串输入即可,注意 lParam 是缺省 ByRef 传递的,ByRef 与 Byval 不同的是,ByRef 是以地址传递,而 Byval 是以参数值传递,所以你把上面的 Byval 去掉看看会产生什么后果?也就是说你传递的字符是一个地址,但是地址必须是整形,所以你去掉以后将会发生重大问题,不信自己试试!!轻则达不到预想的效果,重则 VB IDE(编程环境) 直接崩溃!!!


                好了, F5 运行试试,希望这下大家能明白其中的原因,下面将不会再多说!


                未完待续……

demo.rar

1.59 KB, 下载次数: 1263

回复 支持 反对

使用道具 举报

发表于 2007-5-23 15:16:05 | 显示全部楼层
老师得 ... 顶 一下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2021-3-5 17:34

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表