api 入门到精通 是什么.docx
《api 入门到精通 是什么.docx》由会员分享,可在线阅读,更多相关《api 入门到精通 是什么.docx(12页珍藏版)》请在冰豆网上搜索。
api入门到精通是什么
回复引用
TOP
杭州元帅
∙发短消息
∙加为好友
杭州元帅当前离线
UID
17052
帖子
1887
精华
8
积分
6212
威望
1852
金钱
2677
人气
11
阅读权限
100
在线时间
349小时
注册时间
2004-2-5
最后登录
2010-7-26
贵宾
帖子
1887
精华
8
威望
1852
擂点
0
人气
11
注册时间
2004-2-5
4楼
发表于2004-2-2812:
06|只看该作者
第三课∶窗口函数
一、关于窗口函数
在上一堂课里,我们已经提出了"句柄"的概念,并为此进行了较深度的讨论。
现在来想,我要补充的是,句柄并非是仅仅是窗口才有的。
似乎所有的WINDOWS对象都具有句柄。
如,GDI对象中的画笔、刷子等,不久即将要学习的设备场景等也有自己的句柄,等等。
但,和一些控件不同,这些对象并不属于窗口。
什么是窗口呢?
有一句非常有趣的话∶如果它位于屏幕,那么它肯定是在一个窗口里;如果它不在于屏幕,它仍然可能在一个窗口里。
窗体也是窗口;滚动条、列表框,文本框,甚至是桌面上的快捷图表也是窗口。
更有趣的是,就连作为背景的桌面也是窗口。
很多控件基本上都提供了hWnd属性,但没有提供的也有。
对于这些控件可以用SetFocus
方法,将输入焦点设向控件,然后用API函数GetFocus取得当前具有焦点的那个窗口的句柄。
当然,这一过程应当写在GoFocus事件中。
在我碰到过的问题中有一个有趣的事情是,
VB提供的IE控件的hWnd属性不管用。
这个问题我一般都采用上述方法来解决的。
很多窗口函数都能对系统的任何窗体进行操作。
这意味了VB程序可以直接操纵正在运行中的其他窗体。
大家知道,如果对VB设计出的程序未做特殊的处理,那么我们可以启动多个该应用程序实例。
我们可以利用API窗口函数来判断一个窗体的先例是否在运行当中,从而可以做到如果有先例则停止启动。
很多应用程序就是这个样子的。
比如四通利方中文平台,在已经启动的情况下再此启动,程序会告诉用户"四通利方已经在运行",并停止启动。
窗口函数主要可分为四个类型(也许说为"这是为了这次讲课分类出来的"更适合一些)∶
1、窗口分级函数;
2、窗口位置与大小函数;
3、窗口信息函数;
4、其他窗口函数。
以下我们就一一讲述。
但由于窗口函数比较多,在这里就选择性的进行讨论。
关于窗口函数有多少,具体的用法如何,您可以注意"小雁侠"的VBAPI站点的技术文档,或者本站
程序下载栏目中的WinAPI帮助文。
由于帮助文其内容来自"小雁侠"的网站,因此其内容更新比较起来会较晚一些。
二、窗口分级函数
系统中运行的窗口是有级别的高低之分的。
谁不知道这样?
这当然是废话。
很多文章都是采用类似的这种废话来做导语,在这里我只不过也是学学而罢。
一、父子关系。
每个窗口都可能有自己的父窗口和子窗口。
但,系统中运行的窗口是有限的,说明总得有个窗口是没有其父,我们把它叫做顶级窗口。
一般把一个应用程序的主窗口就是顶级窗口,VB独立窗体及MDI窗体都是顶级窗口。
窗口间的父子关系一般遵循以下规则∶
1、父窗口显示时,所有包容在其中的可见的子窗口会随着父窗口的显示而显示出来。
2、父窗口隐藏时,所有包容在其中的子窗口会随着父窗口的隐藏而隐藏。
3、父窗口被卸载时,哈,您已经知道我想说什么了,当然是∶跟着自动卸载。
4、父窗口移动时,跟着移动。
二、兄弟关系及Z序列
当然,一位父亲有好几个儿女,都是常见的事情。
同样,一个父窗口可以拥有多个子窗体。
比如,位于一个窗体中的各种控件之间以及MDI窗口的各子窗口之间的关系。
父窗口与子窗口的显示、隐藏、卸载及移动,其先后顺序是显而易见的。
那么各兄弟窗口之间的情况会是如何呢?
显然,两个互相重叠的两个子窗体不能都同时显示出它的全貌,自然有个显示的顺序规则。
这个顺序规则叫做Z序列。
有个解释为,如果把屏幕坐标看层X和Y轴组成的平面(事实上正是如此),那么作为三维坐标系统Z轴可看做是垂直于屏幕的坐标轴。
这样,可以认为屏幕上的所有窗口是垂直于这个Z轴的。
在Z轴上,谁在前,谁在后,就产生了一个Z序列。
很生动!
可用WINDOWSAPI函数和VisualBasicZ序列方法对Z序列进行控制。
有了以上简单的知识以后,我们就不难应用API窗口分级函数,主要有以下及个∶
窗口分级函数
函数名说明
FindWindow按类名或窗口名(Caption)查找一个窗口
FindWindowEx类似于FindWindow提供了更多的功能
GetLastActivePopup针对指定的窗口,取回上一个活动的弹出式窗口的句柄
GetParent获得指定窗口父窗口的句柄
GetTopWindow获得指定窗口的第一个子窗口的句柄
GetWindow如给定一个窗口句柄,该函数能取回具有特定关系的另一个窗口的句柄。
如,第一个子窗口、父窗口或窗口列表内的上一个或下一个窗口。
SetParent改变任何窗口的父窗口。
从我个人的经验来看,我最常用的是GetWindow和SetParent函数。
三、窗口位置与大小函数
WindowsAPI函数基本上都是(尤其是USER32.DLL动态连接库内的函数)以屏幕像素为度量单位的。
这一点很重要,必须牢记。
为此,在使用API函数的时候,我们经常把窗体或图片框控件的ScaleMode属性设置为3,即vbPixels(像素)。
理解窗口位置及大小函数的关键在于分清屏幕坐标、窗口坐标及客户坐标这三个概念。
以下图展示了这三个坐标系统之间的关系。
屏目、窗口与客户区坐标系统
只要对这些坐标有了明确的概念,对使用窗口位置及大小函数就不难了。
关于窗口的位置,有些函数返回的是上一堂课学习到的RECT结构。
有关窗口位置及大小函数如下表所列∶
窗口位置及大小函数
函数名说明
BringWindowToTop使指定的窗口进入可见窗口列表的顶部,如它被部分或全部隐藏,则令其全部可见。
同时,该窗口成为当前活动窗口。
只有从前台线程调用时,才生效。
ChildWindowFromPoint在规定的坐标取得某子窗口的句柄(如果有的话),这儿的坐标是指相对于父窗口的客户区坐标。
ChildWindowFromPointEx与ChildWindowFromPoint相同,功能更强。
ClientToScreen判断指定点在窗口客户区内的屏幕坐标。
GetClientRect获得对窗口客户区进行表述的一个矩形(RECT)。
这是以像素为单位判断客户区大小的一个简便的方法。
GetWindowPlacement获得指定窗口的一个WINDOWPLACEMENT结构。
该结构说明了窗口的状态。
GetWindowRect用于获得一个矩形(RECT)结构,它描述了窗体在屏幕坐标系统中的位置。
MapWindowPoints对某窗口客户区坐标内的一个或多个点进行转换,用另一窗口的客户区坐标表示。
MoveWindow移动指定窗口的位置,并能改变它的大小。
OpenIcon将一个最小化窗口恢复为原始状态。
ScreenToClient针对屏幕内一个指定的点,用某个特定窗口内的客户区坐标表示它。
SetWindowsPos更改窗口的位置和大小,并能修改它在内部窗口列表内的位置(这个列表起着控制窗口先是顺序)。
SetWindowPlacement在一个WINDOWPLACEMENT结构的基础上,设置某窗口的特征。
该结构描述了窗口的状态,以及它在最小化、最大化或正常显示时的位置。
WindowFromPoint根据屏幕上一个指定的点,判断哪个窗口正位于它的下面。
以上函数的具体用法均可在WinAPI帮助文中找到。
在这些函数当中,SetWindowsPos
函数的使用率比较高,现在很多人都是用这个函数来实现"窗口总在前面"的效果,即通过
HWND_TOPMOST常数把窗口置于列表顶部。
如果想把From1置于列表顶部,方法如下∶
SetWindowPosForm1.hWnd,HWND_TOPMOST,Form1.Left/Screen.TwipsPerPixelX,Form1.TopScreen.TwipsPerPixelY,Form1.WidthScreen.TwipsPerPixelX,Form1.HeightScreen.TwipsPerPixelY,0
您可以把这行代码放在Paint事件中。
另外,GetWindowRect函数、MoveWindow函数以及下一课堂即将要学到的
GetCursorPos函数的相互配合能够实现一个拖动无标题栏的窗口。
这是您必须掌握的技巧之一。
感兴趣的朋友,可以到《前线》的《源码解析》栏目,下载第4号演示程序。
以下是其主要的代码部分∶
PrivateMyRectAsRECT
PrivateMyPointAsPOINTAPI
PrivateMovexAsLong,MoveyAsLong
PrivateSubImage1_MouseDown(ButtonAsInteger,ShiftAsInteger,XAsSingle,YAsSingle)
Dimdl&
dl&=GetWindowRect(Form1.hwnd,MyRect)
dl&=GetCursorPos(MyPoint)
IfButton=1Then
Movex=MyPoint.X-MyRect.Left
Movey=MyPoint.Y-MyRect.Top
EndIf
EndSub
PrivateSubImage1_MouseMove(ButtonAsInteger,ShiftAsInteger,XAsSingle,YAsSingle)
Dimdl&
dl&=GetCursorPos(MyPoint)
IfButton=1Then
dl&=MoveWindow(Form1.hwnd,MyPoint.X-Movex,MyPoint.Y-Movey,_
MyRect.Right-MyRect.Left,MyRect.Bottom-MyRect.Top,-1)
EndIf
EndSub
在MouseDown事件中,程序首先用GetWindowRect函数确定窗口在屏幕中的位置。
再次是通过GetCursorPos函数确鼠标在屏幕中的位置。
从而可通过计算获得鼠标位置与窗口左上角之间的横向与纵向距离(Movex与Movey)。
在紧接着发生的MouseMove事件中程序不断地用GetCursorPos函数获得鼠标当前的位置,并按前面已经求得的Movex与Movey判断窗口所应处的位置,而这在MoveWindow函数调用中直接完成。
MoveWindow函数将窗体移动到新的位置。
四、窗口信息函数
所谓窗口信息函数就是用来获取有关窗口当前状态信息的函数。
这类函数主要有∶
函数说明
GetClassInfo取得指定窗口的类信息结构
GetClassInfoEx效果类似于GetClassInfo,但增加了一些功能
GetClassLong,GetClassWord用于获取窗口类信息
SetClassLong,SetClassWord用于设置窗口类信息
GetClassName获取窗口类名
GetDesktopWindow获取整个桌面(屏幕)的窗口句柄
GetWindowLong,GetWindowWord获取与窗口有关的信息
SetWindowLong,SetWindowWord设置与窗口有关的信息
GetWindowText获得窗口文本。
它的效果大致等价于窗体或控件的Text属性
GetWindowTextLength获得窗口文本的长度,用字符数表示。
IsChild判断某窗口是否为另一窗口的子窗口或从属窗口。
IsIconic判断某窗口是否处于最小化状态
IsWindow判断指定的句柄是否为窗口句柄。
IsWindowEnabled判断指定的窗口是否处于活动状态。
IsWindowVisible判断某窗口是否可见。
IsZoomed判断窗口是否处于最大化状态。
SetWindowText设置窗口文本。
大致等价于窗体或控件的Text属性。
大部分窗口信息函数是非常好理解的,按照有关手册中进行的函数说明,按指定数据类型进行调用即可。
有必要说明的是,关于类和窗口的样式位。
Windows是用一个长整形的数据的位设置方式来记录类和窗口的样式的。
其中,窗口样式由一个32位样式以及另一个32
位扩展样式来构成。
类样式操作由上述列表中的GetClassLong以及GetClassLong来进行,窗口样式操作由GetWindowLong以及SetWindowLong来进行。
由于样式位的内容较多,我无法在此给出,您可以参考有关手册。
这里有必要提醒大家的是,您想改变或获取当前窗口或类的样式,绝大多数情况可以考虑样式位操作。
下面,就这个问题举一个简单了例子来说明。
下面是用BS_LEFTTEXT样式位将VB复选框或选项按钮的文本在左边和右边之间相互移动来、移动去的程序(是附带的Program1.vbp的部分内容)。
程序的原理很简单。
首先用
GetWindowLong函数获得当前样式位的信息,然后通过位操作来准备新的样式位信息,最后用SetWindowLong实际地去更改。
如下∶
Dimf&,dl&
f&=GetWindowLong(Option1.hWnd,GWL_STYLE)'获得当前样式位的信息
IfIndex=0Then
f&=f&OrBS_LEFTTEXT
Else
f&=f&AndNotBS_LEFTTEXT
EndIf
dl&=SetWindowLong(Option1.hWnd,GWL_STYLE,f&)'设置新的样式位
Option1.Refresh
(对Or和And位操作不熟悉的朋友,请参考有关技术资料)
在这里,对样式位不进行更详细讨论,主要有这样一个原因。
用SetWindowLong函数改变一个样式位之后,不会导致窗口发生相应的变化(至少不会立即变化)。
有些样式位可能在运行时候才会成功变化,而大多数都只在窗口创建时才生效。
因为,用API方式创建一个窗体已经超出了本教程的范围,就算我在这里对样式位谈得再多,您可能也没有多大用处。
同时,微软公司没有告诉我们哪些样式位在运行期间安全地改变,因此对具体的情况,只好靠自己进行具体试验。
而从我个人的实际编程经验来看,没有特别的要求,我们不大会涉及到这些样式位操作,很多都可在VB中很方便地实现。
本教程还附带了一个Program2.vbp的演示程序。
是我本人随便编写的,没什么特别希罕之处。
想看就看看好了。
最后,想简单提一提的是,使用SetWindowLong函数的时候,改变GWL_WNDPROC
数据是非常危险的(系统或VB经常挂死),即更改窗口函数的位置。
一般,这种更改在需要进行子类处理的地方应用到。
每次试运行程序,都应当习惯性地进行存盘。
五、其他窗口函数
API中还有以下本教程未列出的窗口函数,以供大家参考。
函数名说明
AnyPopup判断是否存在可见的弹出式窗口
CascadeWindows令窗口在一个父窗口内层叠显示
CloseWindow对指定的窗口进行最小化处理(如果它是个钉级窗口)对弹出式及子窗口无效
DestroyWindow清除指定的窗口以及下属所有子窗口与包容窗口
DrawAnimatedRects获得窗口打开或关闭的动画效果
EnableWindow激活或屏蔽(禁用)指定窗口
FlashWindow令指定窗口的标题闪烁显示
GetUpdateRect判断需要更新的那个窗口的位置
GetWindowContextHelpId取得与窗口关联在一起的帮助场景
InvalidateRect指定窗口内需要更新的全部或部分客户区
IsWindowUnicode判断一个窗口是否期望文本消息采用Unicode格式
LockWindowUpdate允许或禁止描绘指定的窗口
RedrawWindow一个功能强大的函数,用于控制全部或部分窗口重画
ScrollWindow,ScrollWindowEx滚动显示窗口的全部或部分客户区
SetWindowContextHelpId设置与窗口关联在一起的帮助场景
ShowOwnedPopups隐藏或显示从属于指定窗口的所有保容弹出窗口
ShowWindow用于设置窗口的状态,其中包括窗口的隐藏、显示、最小化、最大化以及激活等
ShowWindowAsync类似于ShowWindow,增加了对其他进程内的窗口进行操作的能力
TileWindows令窗口在一个父窗口内平铺显示
UpdateWindow立即更新窗口内需要更新的任何部分
ValidateRect指出全部或部分矩形已经更新,毋需再更新
其中,FlashWindow函数非常有趣,不妨大家试一试。
VBGood论坛新手发帖必读